string.c 7.2 KB

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