string.c 11 KB

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