string.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. /*
  2. * File : string.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2008, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2008-08-14 Bernard the first version
  13. * 2010-02-15 Gary Lee add strlcpy
  14. * 2010-03-17 Bernard add strlcpy implementation to this file.
  15. * fix strlcpy declaration
  16. */
  17. #include <rtthread.h>
  18. #if !defined (RT_USING_NEWLIB) && defined (RT_USING_MINILIBC)
  19. #include "string.h"
  20. /* there is no strcpy and strcmp implementation in RT-Thread */
  21. char *strcpy(char *dest, const char *src)
  22. {
  23. return (char *)rt_strncpy(dest, src, rt_strlen(src) + 1);
  24. }
  25. char *strncpy(char *dest, const char *src, size_t siz)
  26. {
  27. return (char *)rt_strncpy(dest, src, siz);
  28. }
  29. size_t strlcpy(char *dst, const char *src, size_t siz)
  30. {
  31. register char *d = dst;
  32. register const char *s = src;
  33. register size_t n = siz;
  34. /* Copy as many bytes as will fit */
  35. if (n != 0)
  36. {
  37. do
  38. {
  39. if ((*d++ = *s++) == 0) break;
  40. } while (--n != 0);
  41. }
  42. /* Not enough room in dst, add NUL and traverse rest of src */
  43. if (n == 0)
  44. {
  45. if (siz != 0) *d = '\0'; /* NUL-terminate dst */
  46. while (*s++) ;
  47. }
  48. return(s - src - 1); /* count does not include NUL */
  49. }
  50. int strcmp (const char *s1, const char *s2)
  51. {
  52. while (*s1 && *s1 == *s2)
  53. s1++, s2++;
  54. return (*s1 - *s2);
  55. }
  56. /**
  57. * strncmp - Compare two length-limited strings
  58. * @cs: One string
  59. * @ct: Another string
  60. * @count: The maximum number of bytes to compare
  61. */
  62. int strncmp(const char *cs,const char *ct, size_t count)
  63. {
  64. register signed char __res = 0;
  65. while (count) {
  66. if ((__res = *cs - *ct++) != 0 || !*cs++)
  67. break;
  68. count--;
  69. }
  70. return __res;
  71. }
  72. char *strcat(char * dest, const char * src)
  73. {
  74. char *tmp = dest;
  75. while (*dest)
  76. dest++;
  77. while ((*dest++ = *src++) != '\0')
  78. ;
  79. return tmp;
  80. }
  81. char *strncat(char *dest, const char *src, size_t count)
  82. {
  83. char *tmp = dest;
  84. if (count) {
  85. while (*dest)
  86. dest++;
  87. while ((*dest++ = *src++)) {
  88. if (--count == 0) {
  89. *dest = '\0';
  90. break;
  91. }
  92. }
  93. }
  94. return tmp;
  95. }
  96. char *strrchr(const char *t, int c)
  97. {
  98. register char ch;
  99. register const char *l=0;
  100. ch = c;
  101. for (;;)
  102. {
  103. if (*t == ch) l=t;
  104. if (!*t) return (char*)l;
  105. ++t;
  106. }
  107. return (char*)l;
  108. }
  109. int strncasecmp ( const char* s1, const char* s2, size_t len )
  110. {
  111. register unsigned int x2;
  112. register unsigned int x1;
  113. register const char* end = s1 + len;
  114. while (1)
  115. {
  116. if ((s1 >= end) )
  117. return 0;
  118. x2 = *s2 - 'A'; if ((x2 < 26u)) x2 += 32;
  119. x1 = *s1 - 'A'; if ((x1 < 26u)) x1 += 32;
  120. s1++; s2++;
  121. if ((x2 != x1))
  122. break;
  123. if ((x1 == (unsigned int)-'A'))
  124. break;
  125. }
  126. return x1 - x2;
  127. }
  128. /* private function */
  129. #define isdigit(c) ((unsigned)((c) - '0') < 10)
  130. rt_inline int divide(int *n, int base)
  131. {
  132. rt_int32_t res;
  133. /* optimized for processor which does not support divide instructions. */
  134. if (base == 10)
  135. {
  136. res = ((int)*n) % 10U;
  137. *n = ((int)*n) / 10U;
  138. }
  139. else
  140. {
  141. res = ((int)*n) % 16U;
  142. *n = ((int)*n) / 16U;
  143. }
  144. return res;
  145. }
  146. rt_inline int skip_atoi(const char **s)
  147. {
  148. register int i=0;
  149. while (isdigit(**s)) i = i*10 + *((*s)++) - '0';
  150. return i;
  151. }
  152. unsigned char _ctype[] = {
  153. _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
  154. _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
  155. _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
  156. _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
  157. _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
  158. _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
  159. _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
  160. _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
  161. _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
  162. _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
  163. _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
  164. _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
  165. _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
  166. _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
  167. _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
  168. _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
  169. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
  170. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
  171. _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
  172. _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
  173. _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
  174. _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
  175. _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
  176. _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
  177. #define __ismask(x) (_ctype[(int)(unsigned char)(x)])
  178. #define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
  179. #define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
  180. #define iscntrl(c) ((__ismask(c)&(_C)) != 0)
  181. #define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
  182. #define islower(c) ((__ismask(c)&(_L)) != 0)
  183. #define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
  184. #define ispunct(c) ((__ismask(c)&(_P)) != 0)
  185. #define isspace(c) ((__ismask(c)&(_S)) != 0)
  186. #define isupper(c) ((__ismask(c)&(_U)) != 0)
  187. #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
  188. #define isascii(c) (((unsigned char)(c))<=0x7f)
  189. #define toascii(c) (((unsigned char)(c))&0x7f)
  190. static inline unsigned char __tolower(unsigned char c)
  191. {
  192. if (isupper(c))
  193. c -= 'A'-'a';
  194. return c;
  195. }
  196. static inline unsigned char __toupper(unsigned char c)
  197. {
  198. if (islower(c))
  199. c -= 'a'-'A';
  200. return c;
  201. }
  202. int tolower(int c)
  203. {
  204. return __tolower(c);
  205. }
  206. int toupper(int c)
  207. {
  208. return __toupper(c);
  209. }
  210. /**
  211. * simple_strtoul - convert a string to an unsigned long
  212. * @cp: The start of the string
  213. * @endp: A pointer to the end of the parsed string will be placed here
  214. * @base: The number base to use
  215. */
  216. unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
  217. {
  218. unsigned long result = 0,value;
  219. if (!base) {
  220. base = 10;
  221. if (*cp == '0') {
  222. base = 8;
  223. cp++;
  224. if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
  225. cp++;
  226. base = 16;
  227. }
  228. }
  229. } else if (base == 16) {
  230. if (cp[0] == '0' && toupper(cp[1]) == 'X')
  231. cp += 2;
  232. }
  233. while (isxdigit(*cp) &&
  234. (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
  235. result = result*base + value;
  236. cp++;
  237. }
  238. if (endp)
  239. *endp = (char *)cp;
  240. return result;
  241. }
  242. /**
  243. * simple_strtol - convert a string to a signed long
  244. * @cp: The start of the string
  245. * @endp: A pointer to the end of the parsed string will be placed here
  246. * @base: The number base to use
  247. */
  248. long simple_strtol(const char *cp,char **endp,unsigned int base)
  249. {
  250. if(*cp=='-')
  251. return -simple_strtoul(cp+1,endp,base);
  252. return simple_strtoul(cp,endp,base);
  253. }
  254. /**
  255. * simple_strtoull - convert a string to an unsigned long long
  256. * @cp: The start of the string
  257. * @endp: A pointer to the end of the parsed string will be placed here
  258. * @base: The number base to use
  259. */
  260. unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
  261. {
  262. unsigned long long result = 0, value;
  263. if (*cp == '0') {
  264. cp++;
  265. if ((toupper(*cp) == 'X') && isxdigit (cp[1])) {
  266. base = 16;
  267. cp++;
  268. }
  269. if (!base) {
  270. base = 8;
  271. }
  272. }
  273. if (!base) {
  274. base = 10;
  275. }
  276. while (isxdigit (*cp) && (value = isdigit (*cp)
  277. ? *cp - '0'
  278. : (islower (*cp) ? toupper (*cp) : *cp) - 'A' + 10) < base) {
  279. result = result * base + value;
  280. cp++;
  281. }
  282. if (endp)
  283. *endp = (char *) cp;
  284. return result;
  285. }
  286. /**
  287. * simple_strtoll - convert a string to a signed long long
  288. * @cp: The start of the string
  289. * @endp: A pointer to the end of the parsed string will be placed here
  290. * @base: The number base to use
  291. */
  292. long long simple_strtoll(const char *cp,char **endp,unsigned int base)
  293. {
  294. if(*cp=='-')
  295. return -simple_strtoull(cp+1,endp,base);
  296. return simple_strtoull(cp,endp,base);
  297. }
  298. /**
  299. * vsscanf - Unformat a buffer into a list of arguments
  300. * @buf: input buffer
  301. * @fmt: format of buffer
  302. * @args: arguments
  303. */
  304. int vsscanf(const char * buf, const char * fmt, va_list args)
  305. {
  306. const char *str = buf;
  307. char *next;
  308. int num = 0;
  309. int qualifier;
  310. int base;
  311. int field_width = -1;
  312. int is_sign = 0;
  313. while(*fmt && *str) {
  314. /* skip any white space in format */
  315. /* white space in format matchs any amount of
  316. * white space, including none, in the input.
  317. */
  318. if (isspace(*fmt)) {
  319. while (isspace(*fmt))
  320. ++fmt;
  321. while (isspace(*str))
  322. ++str;
  323. }
  324. /* anything that is not a conversion must match exactly */
  325. if (*fmt != '%' && *fmt) {
  326. if (*fmt++ != *str++)
  327. break;
  328. continue;
  329. }
  330. if (!*fmt)
  331. break;
  332. ++fmt;
  333. /* skip this conversion.
  334. * advance both strings to next white space
  335. */
  336. if (*fmt == '*') {
  337. while (!isspace(*fmt) && *fmt)
  338. fmt++;
  339. while (!isspace(*str) && *str)
  340. str++;
  341. continue;
  342. }
  343. /* get field width */
  344. if (isdigit(*fmt))
  345. field_width = skip_atoi(&fmt);
  346. /* get conversion qualifier */
  347. qualifier = -1;
  348. if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z') {
  349. qualifier = *fmt;
  350. fmt++;
  351. }
  352. base = 10;
  353. is_sign = 0;
  354. if (!*fmt || !*str)
  355. break;
  356. switch(*fmt++) {
  357. case 'c':
  358. {
  359. char *s = (char *) va_arg(args,char*);
  360. if (field_width == -1)
  361. field_width = 1;
  362. do {
  363. *s++ = *str++;
  364. } while(field_width-- > 0 && *str);
  365. num++;
  366. }
  367. continue;
  368. case 's':
  369. {
  370. char *s = (char *) va_arg(args, char *);
  371. if(field_width == -1)
  372. field_width = INT_MAX;
  373. /* first, skip leading white space in buffer */
  374. while (isspace(*str))
  375. str++;
  376. /* now copy until next white space */
  377. while (*str && !isspace(*str) && field_width--) {
  378. *s++ = *str++;
  379. }
  380. *s = '\0';
  381. num++;
  382. }
  383. continue;
  384. case 'n':
  385. /* return number of characters read so far */
  386. {
  387. int *i = (int *)va_arg(args,int*);
  388. *i = str - buf;
  389. }
  390. continue;
  391. case 'o':
  392. base = 8;
  393. break;
  394. case 'x':
  395. case 'X':
  396. base = 16;
  397. break;
  398. case 'd':
  399. case 'i':
  400. is_sign = 1;
  401. case 'u':
  402. break;
  403. case '%':
  404. /* looking for '%' in str */
  405. if (*str++ != '%')
  406. return num;
  407. continue;
  408. default:
  409. /* invalid format; stop here */
  410. return num;
  411. }
  412. /* have some sort of integer conversion.
  413. * first, skip white space in buffer.
  414. */
  415. while (isspace(*str))
  416. str++;
  417. if (!*str || !isdigit(*str))
  418. break;
  419. switch(qualifier) {
  420. case 'h':
  421. if (is_sign) {
  422. short *s = (short *) va_arg(args,short *);
  423. *s = (short) simple_strtol(str,&next,base);
  424. } else {
  425. unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
  426. *s = (unsigned short) simple_strtoul(str, &next, base);
  427. }
  428. break;
  429. case 'l':
  430. if (is_sign) {
  431. long *l = (long *) va_arg(args,long *);
  432. *l = simple_strtol(str,&next,base);
  433. } else {
  434. unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
  435. *l = simple_strtoul(str,&next,base);
  436. }
  437. break;
  438. case 'L':
  439. if (is_sign) {
  440. long long *l = (long long*) va_arg(args,long long *);
  441. *l = simple_strtoll(str,&next,base);
  442. } else {
  443. unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
  444. *l = simple_strtoull(str,&next,base);
  445. }
  446. break;
  447. case 'Z':
  448. {
  449. unsigned long *s = (unsigned long*) va_arg(args,unsigned long*);
  450. *s = (unsigned long) simple_strtoul(str,&next,base);
  451. }
  452. break;
  453. default:
  454. if (is_sign) {
  455. int *i = (int *) va_arg(args, int*);
  456. *i = (int) simple_strtol(str,&next,base);
  457. } else {
  458. unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
  459. *i = (unsigned int) simple_strtoul(str,&next,base);
  460. }
  461. break;
  462. }
  463. num++;
  464. if (!next)
  465. break;
  466. str = next;
  467. }
  468. return num;
  469. }
  470. /**
  471. * sscanf - Unformat a buffer into a list of arguments
  472. * @buf: input buffer
  473. * @fmt: formatting of buffer
  474. * @...: resulting arguments
  475. */
  476. int sscanf(const char * buf, const char * fmt, ...)
  477. {
  478. va_list args;
  479. int i;
  480. va_start(args,fmt);
  481. i = vsscanf(buf,fmt,args);
  482. va_end(args);
  483. return i;
  484. }
  485. #endif