/lib/string.c

https://bitbucket.org/Don2x/mod-kernel-m7-sources · C · 588 lines · 503 code · 77 blank · 8 comment · 129 complexity · 0c666e7e42242dd007359f0d154eb638 MD5 · raw file

  1. /*
  2. * linux/lib/string.c
  3. *
  4. * Copyright (C) 1991, 1992 Linus Torvalds
  5. */
  6. #include <linux/types.h>
  7. #include <linux/string.h>
  8. #include <linux/ctype.h>
  9. #include <linux/kernel.h>
  10. #include <linux/export.h>
  11. #include <linux/bug.h>
  12. #include <linux/errno.h>
  13. #include <linux/memcopy.h>
  14. #ifndef __HAVE_ARCH_STRNICMP
  15. int strnicmp(const char *s1, const char *s2, size_t len)
  16. {
  17. unsigned char c1, c2;
  18. if (!len)
  19. return 0;
  20. do {
  21. c1 = *s1++;
  22. c2 = *s2++;
  23. if (!c1 || !c2)
  24. break;
  25. if (c1 == c2)
  26. continue;
  27. c1 = tolower(c1);
  28. c2 = tolower(c2);
  29. if (c1 != c2)
  30. break;
  31. } while (--len);
  32. return (int)c1 - (int)c2;
  33. }
  34. EXPORT_SYMBOL(strnicmp);
  35. #endif
  36. #ifndef __HAVE_ARCH_STRCASECMP
  37. int strcasecmp(const char *s1, const char *s2)
  38. {
  39. int c1, c2;
  40. do {
  41. c1 = tolower(*s1++);
  42. c2 = tolower(*s2++);
  43. } while (c1 == c2 && c1 != 0);
  44. return c1 - c2;
  45. }
  46. EXPORT_SYMBOL(strcasecmp);
  47. #endif
  48. #ifndef __HAVE_ARCH_STRNCASECMP
  49. int strncasecmp(const char *s1, const char *s2, size_t n)
  50. {
  51. int c1, c2;
  52. do {
  53. c1 = tolower(*s1++);
  54. c2 = tolower(*s2++);
  55. } while ((--n > 0) && c1 == c2 && c1 != 0);
  56. return c1 - c2;
  57. }
  58. EXPORT_SYMBOL(strncasecmp);
  59. #endif
  60. #ifndef __HAVE_ARCH_STRCPY
  61. #undef strcpy
  62. char *strcpy(char *dest, const char *src)
  63. {
  64. char *tmp = dest;
  65. while ((*dest++ = *src++) != '\0')
  66. ;
  67. return tmp;
  68. }
  69. EXPORT_SYMBOL(strcpy);
  70. #endif
  71. #ifndef __HAVE_ARCH_STRNCPY
  72. char *strncpy(char *dest, const char *src, size_t count)
  73. {
  74. char *tmp = dest;
  75. while (count) {
  76. if ((*tmp = *src) != 0)
  77. src++;
  78. tmp++;
  79. count--;
  80. }
  81. return dest;
  82. }
  83. EXPORT_SYMBOL(strncpy);
  84. #endif
  85. #ifndef __HAVE_ARCH_STRLCPY
  86. size_t strlcpy(char *dest, const char *src, size_t size)
  87. {
  88. size_t ret = strlen(src);
  89. if (size) {
  90. size_t len = (ret >= size) ? size - 1 : ret;
  91. memcpy(dest, src, len);
  92. dest[len] = '\0';
  93. }
  94. return ret;
  95. }
  96. EXPORT_SYMBOL(strlcpy);
  97. #endif
  98. #ifndef __HAVE_ARCH_STRCAT
  99. #undef strcat
  100. char *strcat(char *dest, const char *src)
  101. {
  102. char *tmp = dest;
  103. while (*dest)
  104. dest++;
  105. while ((*dest++ = *src++) != '\0')
  106. ;
  107. return tmp;
  108. }
  109. EXPORT_SYMBOL(strcat);
  110. #endif
  111. #ifndef __HAVE_ARCH_STRNCAT
  112. char *strncat(char *dest, const char *src, size_t count)
  113. {
  114. char *tmp = dest;
  115. if (count) {
  116. while (*dest)
  117. dest++;
  118. while ((*dest++ = *src++) != 0) {
  119. if (--count == 0) {
  120. *dest = '\0';
  121. break;
  122. }
  123. }
  124. }
  125. return tmp;
  126. }
  127. EXPORT_SYMBOL(strncat);
  128. #endif
  129. #ifndef __HAVE_ARCH_STRLCAT
  130. size_t strlcat(char *dest, const char *src, size_t count)
  131. {
  132. size_t dsize = strlen(dest);
  133. size_t len = strlen(src);
  134. size_t res = dsize + len;
  135. BUG_ON(dsize >= count);
  136. dest += dsize;
  137. count -= dsize;
  138. if (len >= count)
  139. len = count-1;
  140. memcpy(dest, src, len);
  141. dest[len] = 0;
  142. return res;
  143. }
  144. EXPORT_SYMBOL(strlcat);
  145. #endif
  146. #ifndef __HAVE_ARCH_STRCMP
  147. #undef strcmp
  148. int strcmp(const char *cs, const char *ct)
  149. {
  150. unsigned char c1, c2;
  151. while (1) {
  152. c1 = *cs++;
  153. c2 = *ct++;
  154. if (c1 != c2)
  155. return c1 < c2 ? -1 : 1;
  156. if (!c1)
  157. break;
  158. }
  159. return 0;
  160. }
  161. EXPORT_SYMBOL(strcmp);
  162. #endif
  163. #ifndef __HAVE_ARCH_STRNCMP
  164. int strncmp(const char *cs, const char *ct, size_t count)
  165. {
  166. unsigned char c1, c2;
  167. while (count) {
  168. c1 = *cs++;
  169. c2 = *ct++;
  170. if (c1 != c2)
  171. return c1 < c2 ? -1 : 1;
  172. if (!c1)
  173. break;
  174. count--;
  175. }
  176. return 0;
  177. }
  178. EXPORT_SYMBOL(strncmp);
  179. #endif
  180. #ifndef __HAVE_ARCH_STRCHR
  181. char *strchr(const char *s, int c)
  182. {
  183. for (; *s != (char)c; ++s)
  184. if (*s == '\0')
  185. return NULL;
  186. return (char *)s;
  187. }
  188. EXPORT_SYMBOL(strchr);
  189. #endif
  190. #ifndef __HAVE_ARCH_STRRCHR
  191. char *strrchr(const char *s, int c)
  192. {
  193. const char *p = s + strlen(s);
  194. do {
  195. if (*p == (char)c)
  196. return (char *)p;
  197. } while (--p >= s);
  198. return NULL;
  199. }
  200. EXPORT_SYMBOL(strrchr);
  201. #endif
  202. #ifndef __HAVE_ARCH_STRNCHR
  203. char *strnchr(const char *s, size_t count, int c)
  204. {
  205. for (; count-- && *s != '\0'; ++s)
  206. if (*s == (char)c)
  207. return (char *)s;
  208. return NULL;
  209. }
  210. EXPORT_SYMBOL(strnchr);
  211. #endif
  212. char *skip_spaces(const char *str)
  213. {
  214. while (isspace(*str))
  215. ++str;
  216. return (char *)str;
  217. }
  218. EXPORT_SYMBOL(skip_spaces);
  219. char *strim(char *s)
  220. {
  221. size_t size;
  222. char *end;
  223. size = strlen(s);
  224. if (!size)
  225. return s;
  226. end = s + size - 1;
  227. while (end >= s && isspace(*end))
  228. end--;
  229. *(end + 1) = '\0';
  230. return skip_spaces(s);
  231. }
  232. EXPORT_SYMBOL(strim);
  233. #ifndef __HAVE_ARCH_STRLEN
  234. size_t strlen(const char *s)
  235. {
  236. const char *sc;
  237. for (sc = s; *sc != '\0'; ++sc)
  238. ;
  239. return sc - s;
  240. }
  241. EXPORT_SYMBOL(strlen);
  242. #endif
  243. #ifndef __HAVE_ARCH_STRNLEN
  244. size_t strnlen(const char *s, size_t count)
  245. {
  246. const char *sc;
  247. for (sc = s; count-- && *sc != '\0'; ++sc)
  248. ;
  249. return sc - s;
  250. }
  251. EXPORT_SYMBOL(strnlen);
  252. #endif
  253. #ifndef __HAVE_ARCH_STRSPN
  254. size_t strspn(const char *s, const char *accept)
  255. {
  256. const char *p;
  257. const char *a;
  258. size_t count = 0;
  259. for (p = s; *p != '\0'; ++p) {
  260. for (a = accept; *a != '\0'; ++a) {
  261. if (*p == *a)
  262. break;
  263. }
  264. if (*a == '\0')
  265. return count;
  266. ++count;
  267. }
  268. return count;
  269. }
  270. EXPORT_SYMBOL(strspn);
  271. #endif
  272. #ifndef __HAVE_ARCH_STRCSPN
  273. size_t strcspn(const char *s, const char *reject)
  274. {
  275. const char *p;
  276. const char *r;
  277. size_t count = 0;
  278. for (p = s; *p != '\0'; ++p) {
  279. for (r = reject; *r != '\0'; ++r) {
  280. if (*p == *r)
  281. return count;
  282. }
  283. ++count;
  284. }
  285. return count;
  286. }
  287. EXPORT_SYMBOL(strcspn);
  288. #endif
  289. #ifndef __HAVE_ARCH_STRPBRK
  290. char *strpbrk(const char *cs, const char *ct)
  291. {
  292. const char *sc1, *sc2;
  293. for (sc1 = cs; *sc1 != '\0'; ++sc1) {
  294. for (sc2 = ct; *sc2 != '\0'; ++sc2) {
  295. if (*sc1 == *sc2)
  296. return (char *)sc1;
  297. }
  298. }
  299. return NULL;
  300. }
  301. EXPORT_SYMBOL(strpbrk);
  302. #endif
  303. #ifndef __HAVE_ARCH_STRSEP
  304. char *strsep(char **s, const char *ct)
  305. {
  306. char *sbegin = *s;
  307. char *end;
  308. if (sbegin == NULL)
  309. return NULL;
  310. end = strpbrk(sbegin, ct);
  311. if (end)
  312. *end++ = '\0';
  313. *s = end;
  314. return sbegin;
  315. }
  316. EXPORT_SYMBOL(strsep);
  317. #endif
  318. bool sysfs_streq(const char *s1, const char *s2)
  319. {
  320. while (*s1 && *s1 == *s2) {
  321. s1++;
  322. s2++;
  323. }
  324. if (*s1 == *s2)
  325. return true;
  326. if (!*s1 && *s2 == '\n' && !s2[1])
  327. return true;
  328. if (*s1 == '\n' && !s1[1] && !*s2)
  329. return true;
  330. return false;
  331. }
  332. EXPORT_SYMBOL(sysfs_streq);
  333. int strtobool(const char *s, bool *res)
  334. {
  335. switch (s[0]) {
  336. case 'y':
  337. case 'Y':
  338. case '1':
  339. *res = true;
  340. break;
  341. case 'n':
  342. case 'N':
  343. case '0':
  344. *res = false;
  345. break;
  346. default:
  347. return -EINVAL;
  348. }
  349. return 0;
  350. }
  351. EXPORT_SYMBOL(strtobool);
  352. #ifndef __HAVE_ARCH_MEMSET
  353. void *memset(void *s, int c, size_t count)
  354. {
  355. char *xs = s;
  356. while (count--)
  357. *xs++ = c;
  358. return s;
  359. }
  360. EXPORT_SYMBOL(memset);
  361. #endif
  362. #ifndef __HAVE_ARCH_MEMCPY
  363. void *memcpy(void *dest, const void *src, size_t count)
  364. {
  365. unsigned long dstp = (unsigned long)dest;
  366. unsigned long srcp = (unsigned long)src;
  367. /* Copy from the beginning to the end */
  368. mem_copy_fwd(dstp, srcp, count);
  369. return dest;
  370. }
  371. EXPORT_SYMBOL(memcpy);
  372. #endif
  373. #ifndef __HAVE_ARCH_MEMMOVE
  374. void *memmove(void *dest, const void *src, size_t count)
  375. {
  376. unsigned long dstp = (unsigned long)dest;
  377. unsigned long srcp = (unsigned long)src;
  378. if (dest - src >= count) {
  379. /* Copy from the beginning to the end */
  380. mem_copy_fwd(dstp, srcp, count);
  381. } else {
  382. /* Copy from the end to the beginning */
  383. mem_copy_bwd(dstp, srcp, count);
  384. }
  385. return dest;
  386. }
  387. EXPORT_SYMBOL(memmove);
  388. #endif
  389. #ifndef __HAVE_ARCH_MEMCMP
  390. #undef memcmp
  391. int memcmp(const void *cs, const void *ct, size_t count)
  392. {
  393. const unsigned char *su1, *su2;
  394. int res = 0;
  395. for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
  396. if ((res = *su1 - *su2) != 0)
  397. break;
  398. return res;
  399. }
  400. EXPORT_SYMBOL(memcmp);
  401. #endif
  402. #ifndef __HAVE_ARCH_MEMSCAN
  403. void *memscan(void *addr, int c, size_t size)
  404. {
  405. unsigned char *p = addr;
  406. while (size) {
  407. if (*p == c)
  408. return (void *)p;
  409. p++;
  410. size--;
  411. }
  412. return (void *)p;
  413. }
  414. EXPORT_SYMBOL(memscan);
  415. #endif
  416. #ifndef __HAVE_ARCH_STRSTR
  417. char *strstr(const char *s1, const char *s2)
  418. {
  419. size_t l1, l2;
  420. l2 = strlen(s2);
  421. if (!l2)
  422. return (char *)s1;
  423. l1 = strlen(s1);
  424. while (l1 >= l2) {
  425. l1--;
  426. if (!memcmp(s1, s2, l2))
  427. return (char *)s1;
  428. s1++;
  429. }
  430. return NULL;
  431. }
  432. EXPORT_SYMBOL(strstr);
  433. #endif
  434. #ifndef __HAVE_ARCH_STRNSTR
  435. char *strnstr(const char *s1, const char *s2, size_t len)
  436. {
  437. size_t l2;
  438. l2 = strlen(s2);
  439. if (!l2)
  440. return (char *)s1;
  441. while (len >= l2) {
  442. len--;
  443. if (!memcmp(s1, s2, l2))
  444. return (char *)s1;
  445. s1++;
  446. }
  447. return NULL;
  448. }
  449. EXPORT_SYMBOL(strnstr);
  450. #endif
  451. #ifndef __HAVE_ARCH_MEMCHR
  452. void *memchr(const void *s, int c, size_t n)
  453. {
  454. const unsigned char *p = s;
  455. while (n-- != 0) {
  456. if ((unsigned char)c == *p++) {
  457. return (void *)(p - 1);
  458. }
  459. }
  460. return NULL;
  461. }
  462. EXPORT_SYMBOL(memchr);
  463. #endif
  464. static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
  465. {
  466. while (bytes) {
  467. if (*start != value)
  468. return (void *)start;
  469. start++;
  470. bytes--;
  471. }
  472. return NULL;
  473. }
  474. void *memchr_inv(const void *start, int c, size_t bytes)
  475. {
  476. u8 value = c;
  477. u64 value64;
  478. unsigned int words, prefix;
  479. if (bytes <= 16)
  480. return check_bytes8(start, value, bytes);
  481. value64 = value;
  482. #if defined(ARCH_HAS_FAST_MULTIPLIER) && BITS_PER_LONG == 64
  483. value64 *= 0x0101010101010101;
  484. #elif defined(ARCH_HAS_FAST_MULTIPLIER)
  485. value64 *= 0x01010101;
  486. value64 |= value64 << 32;
  487. #else
  488. value64 |= value64 << 8;
  489. value64 |= value64 << 16;
  490. value64 |= value64 << 32;
  491. #endif
  492. prefix = (unsigned long)start % 8;
  493. if (prefix) {
  494. u8 *r;
  495. prefix = 8 - prefix;
  496. r = check_bytes8(start, value, prefix);
  497. if (r)
  498. return r;
  499. start += prefix;
  500. bytes -= prefix;
  501. }
  502. words = bytes / 8;
  503. while (words) {
  504. if (*(u64 *)start != value64)
  505. return check_bytes8(start, value, 8);
  506. start += 8;
  507. words--;
  508. }
  509. return check_bytes8(start, value, bytes % 8);
  510. }
  511. EXPORT_SYMBOL(memchr_inv);