string.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /* string.c - common string routines */
  2. /*
  3. * Copyright (c) 2014 Wind River Systems, Inc.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. */
  7. #include <string.h>
  8. #include <stdint.h>
  9. #include <sys/types.h>
  10. extern void *memcpy32(void *d, const void *s, size_t n);
  11. extern void *memset32(void *d, int c, size_t n);
  12. /**
  13. *
  14. * @brief Copy a string
  15. *
  16. * @return pointer to destination buffer <d>
  17. */
  18. char *strcpy(char *_MLIBC_RESTRICT d, const char *_MLIBC_RESTRICT s)
  19. {
  20. char *dest = d;
  21. while (*s != '\0') {
  22. *d = *s;
  23. d++;
  24. s++;
  25. }
  26. *d = '\0';
  27. return dest;
  28. }
  29. /**
  30. *
  31. * @brief Copy part of a string
  32. *
  33. * @return pointer to destination buffer <d>
  34. */
  35. char *strncpy(char *_MLIBC_RESTRICT d, const char *_MLIBC_RESTRICT s, size_t n)
  36. {
  37. char *dest = d;
  38. while ((n > 0) && *s != '\0') {
  39. *d = *s;
  40. s++;
  41. d++;
  42. n--;
  43. }
  44. while (n > 0) {
  45. *d = '\0';
  46. d++;
  47. n--;
  48. }
  49. return dest;
  50. }
  51. /**
  52. *
  53. * @brief String scanning operation
  54. *
  55. * @return pointer to 1st instance of found byte, or NULL if not found
  56. */
  57. char *strchr(const char *s, int c)
  58. {
  59. char tmp = (char) c;
  60. while ((*s != tmp) && (*s != '\0')) {
  61. s++;
  62. }
  63. return (*s == tmp) ? (char *) s : NULL;
  64. }
  65. /**
  66. *
  67. * @brief String scanning operation
  68. *
  69. * @return pointer to last instance of found byte, or NULL if not found
  70. */
  71. char *strrchr(const char *s, int c)
  72. {
  73. char *match = NULL;
  74. do {
  75. if (*s == (char)c) {
  76. match = (char *)s;
  77. }
  78. } while (*s++);
  79. return match;
  80. }
  81. /**
  82. *
  83. * @brief Get string length
  84. *
  85. * @return number of bytes in string <s>
  86. */
  87. size_t strlen(const char *s)
  88. {
  89. size_t n = 0;
  90. while (*s != '\0') {
  91. s++;
  92. n++;
  93. }
  94. return n;
  95. }
  96. /**
  97. *
  98. * @brief Get fixed-size string length
  99. *
  100. * @return number of bytes in fixed-size string <s>
  101. */
  102. size_t strnlen(const char *s, size_t maxlen)
  103. {
  104. size_t n = 0;
  105. while (*s != '\0' && n < maxlen) {
  106. s++;
  107. n++;
  108. }
  109. return n;
  110. }
  111. /**
  112. *
  113. * @brief Compare two strings
  114. *
  115. * @return negative # if <s1> < <s2>, 0 if <s1> == <s2>, else positive #
  116. */
  117. int strcmp(const char *s1, const char *s2)
  118. {
  119. while ((*s1 == *s2) && (*s1 != '\0')) {
  120. s1++;
  121. s2++;
  122. }
  123. return *s1 - *s2;
  124. }
  125. /**
  126. *
  127. * @brief Compare part of two strings
  128. *
  129. * @return negative # if <s1> < <s2>, 0 if <s1> == <s2>, else positive #
  130. */
  131. int strncmp(const char *s1, const char *s2, size_t n)
  132. {
  133. while ((n > 0) && (*s1 == *s2) && (*s1 != '\0')) {
  134. s1++;
  135. s2++;
  136. n--;
  137. }
  138. return (n == 0) ? 0 : (*s1 - *s2);
  139. }
  140. /**
  141. * @brief Separate `str` by any char in `sep` and return NULL terminated
  142. * sections. Consecutive `sep` chars in `str` are treated as a single
  143. * separator.
  144. *
  145. * @return pointer to NULL terminated string or NULL on errors.
  146. */
  147. char *strtok_r(char *str, const char *sep, char **state)
  148. {
  149. char *start, *end;
  150. start = str ? str : *state;
  151. /* skip leading delimiters */
  152. while (*start && strchr(sep, *start)) {
  153. start++;
  154. }
  155. if (*start == '\0') {
  156. *state = start;
  157. return NULL;
  158. }
  159. /* look for token chars */
  160. end = start;
  161. while (*end && !strchr(sep, *end)) {
  162. end++;
  163. }
  164. if (*end != '\0') {
  165. *end = '\0';
  166. *state = end + 1;
  167. } else {
  168. *state = end;
  169. }
  170. return start;
  171. }
  172. char *strcat(char *_MLIBC_RESTRICT dest, const char *_MLIBC_RESTRICT src)
  173. {
  174. strcpy(dest + strlen(dest), src);
  175. return dest;
  176. }
  177. char *strncat(char *_MLIBC_RESTRICT dest, const char *_MLIBC_RESTRICT src,
  178. size_t n)
  179. {
  180. char *orig_dest = dest;
  181. size_t len = strlen(dest);
  182. dest += len;
  183. while ((n-- > 0) && (*src != '\0')) {
  184. *dest++ = *src++;
  185. }
  186. *dest = '\0';
  187. return orig_dest;
  188. }
  189. /**
  190. *
  191. * @brief Compare two memory areas
  192. *
  193. * @return negative # if <m1> < <m2>, 0 if <m1> == <m2>, else positive #
  194. */
  195. int memcmp(const void *m1, const void *m2, size_t n)
  196. {
  197. const char *c1 = m1;
  198. const char *c2 = m2;
  199. if (!n) {
  200. return 0;
  201. }
  202. while ((--n > 0) && (*c1 == *c2)) {
  203. c1++;
  204. c2++;
  205. }
  206. return *c1 - *c2;
  207. }
  208. /**
  209. *
  210. * @brief Copy bytes in memory with overlapping areas
  211. *
  212. * @return pointer to destination buffer <d>
  213. */
  214. void *memmove(void *d, const void *s, size_t n)
  215. {
  216. char *dest = d;
  217. const char *src = s;
  218. if ((size_t) (dest - src) < n) {
  219. /*
  220. * The <src> buffer overlaps with the start of the <dest> buffer.
  221. * Copy backwards to prevent the premature corruption of <src>.
  222. */
  223. while (n > 0) {
  224. n--;
  225. dest[n] = src[n];
  226. }
  227. } else {
  228. /* It is safe to perform a forward-copy */
  229. while (n > 0) {
  230. *dest = *src;
  231. dest++;
  232. src++;
  233. n--;
  234. }
  235. }
  236. return d;
  237. }
  238. /**
  239. *
  240. * @brief Copy bytes in memory
  241. *
  242. * @return pointer to start of destination buffer
  243. */
  244. void *memcpy(void *_MLIBC_RESTRICT d, const void *_MLIBC_RESTRICT s, size_t n)
  245. {
  246. /* attempt word-sized copying only if buffers have identical alignment */
  247. unsigned char *d_byte = (unsigned char *)d;
  248. const unsigned char *s_byte = (const unsigned char *)s;
  249. #if !defined(CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE)
  250. const uintptr_t mask = sizeof(mem_word_t) - 1;
  251. if ((((uintptr_t)d ^ (uintptr_t)s_byte) & mask) == 0) {
  252. /* do byte-sized copying until word-aligned or finished */
  253. while (((uintptr_t)d_byte) & mask) {
  254. if (n == 0) {
  255. return d;
  256. }
  257. *(d_byte++) = *(s_byte++);
  258. n--;
  259. }
  260. /* do cacheline-sized copying as long as possible */
  261. if (n >= 32) {
  262. unsigned int cnt = n / 32;
  263. unsigned int sz = cnt * 32;
  264. memcpy32(d_byte, s_byte, cnt);
  265. d_byte += sz;
  266. s_byte += sz;
  267. n -= sz;
  268. }
  269. /* do word-sized copying as long as possible */
  270. mem_word_t *d_word = (mem_word_t *)d_byte;
  271. const mem_word_t *s_word = (const mem_word_t *)s_byte;
  272. while (n >= sizeof(mem_word_t)) {
  273. *(d_word++) = *(s_word++);
  274. n -= sizeof(mem_word_t);
  275. }
  276. d_byte = (unsigned char *)d_word;
  277. s_byte = (unsigned char *)s_word;
  278. }
  279. #endif
  280. /* do byte-sized copying until finished */
  281. while (n > 0) {
  282. *(d_byte++) = *(s_byte++);
  283. n--;
  284. }
  285. return d;
  286. }
  287. /**
  288. *
  289. * @brief Set bytes in memory
  290. *
  291. * @return pointer to start of buffer
  292. */
  293. void *memset(void *buf, int c, size_t n)
  294. {
  295. /* do byte-sized initialization until word-aligned or finished */
  296. unsigned char *d_byte = (unsigned char *)buf;
  297. unsigned char c_byte = (unsigned char)c;
  298. #if !defined(CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE)
  299. while (((uintptr_t)d_byte) & (sizeof(mem_word_t) - 1)) {
  300. if (n == 0) {
  301. return buf;
  302. }
  303. *(d_byte++) = c_byte;
  304. n--;
  305. }
  306. mem_word_t *d_word = (mem_word_t *)d_byte;
  307. mem_word_t c_word = (mem_word_t)c_byte;
  308. c_word |= c_word << 8;
  309. c_word |= c_word << 16;
  310. #if Z_MEM_WORD_T_WIDTH > 32
  311. c_word |= c_word << 32;
  312. #endif
  313. /* do cacheline-sized initialization as long as possible */
  314. if (n >= 32) {
  315. unsigned int cnt = n / 32;
  316. unsigned int sz = cnt * 32;
  317. memset32(d_word, c_word, cnt);
  318. d_word += sz / sizeof(mem_word_t);
  319. n -= sz;
  320. }
  321. /* do word-sized initialization as long as possible */
  322. while (n >= sizeof(mem_word_t)) {
  323. *(d_word++) = c_word;
  324. n -= sizeof(mem_word_t);
  325. }
  326. /* do byte-sized initialization until finished */
  327. d_byte = (unsigned char *)d_word;
  328. #endif
  329. while (n > 0) {
  330. *(d_byte++) = c_byte;
  331. n--;
  332. }
  333. return buf;
  334. }
  335. /**
  336. *
  337. * @brief Scan byte in memory
  338. *
  339. * @return pointer to start of found byte
  340. */
  341. void *memchr(const void *s, int c, size_t n)
  342. {
  343. if (n != 0) {
  344. const unsigned char *p = s;
  345. do {
  346. if (*p++ == (unsigned char)c) {
  347. return ((void *)(p - 1));
  348. }
  349. } while (--n != 0);
  350. }
  351. return NULL;
  352. }