string.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Format.h>
  7. #include <AK/MemMem.h>
  8. #include <AK/Memory.h>
  9. #include <AK/Platform.h>
  10. #include <AK/StdLibExtras.h>
  11. #include <AK/Types.h>
  12. #include <assert.h>
  13. #include <ctype.h>
  14. #include <errno.h>
  15. #include <signal.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. extern "C" {
  20. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strspn.html
  21. size_t strspn(const char* s, const char* accept)
  22. {
  23. const char* p = s;
  24. cont:
  25. char ch = *p++;
  26. char ac;
  27. for (const char* ap = accept; (ac = *ap++) != '\0';) {
  28. if (ac == ch)
  29. goto cont;
  30. }
  31. return p - 1 - s;
  32. }
  33. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strcspn.html
  34. size_t strcspn(const char* s, const char* reject)
  35. {
  36. for (auto* p = s;;) {
  37. char c = *p++;
  38. auto* rp = reject;
  39. char rc;
  40. do {
  41. if ((rc = *rp++) == c)
  42. return p - 1 - s;
  43. } while (rc);
  44. }
  45. }
  46. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strlen.html
  47. size_t strlen(const char* str)
  48. {
  49. size_t len = 0;
  50. while (*(str++))
  51. ++len;
  52. return len;
  53. }
  54. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strnlen.html
  55. size_t strnlen(const char* str, size_t maxlen)
  56. {
  57. size_t len = 0;
  58. for (; len < maxlen && *str; str++)
  59. len++;
  60. return len;
  61. }
  62. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strdup.html
  63. char* strdup(const char* str)
  64. {
  65. size_t len = strlen(str);
  66. char* new_str = (char*)malloc(len + 1);
  67. memcpy(new_str, str, len);
  68. new_str[len] = '\0';
  69. return new_str;
  70. }
  71. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strndup.html
  72. char* strndup(const char* str, size_t maxlen)
  73. {
  74. size_t len = strnlen(str, maxlen);
  75. char* new_str = (char*)malloc(len + 1);
  76. memcpy(new_str, str, len);
  77. new_str[len] = 0;
  78. return new_str;
  79. }
  80. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strcmp.html
  81. int strcmp(const char* s1, const char* s2)
  82. {
  83. while (*s1 == *s2++)
  84. if (*s1++ == 0)
  85. return 0;
  86. return *(const unsigned char*)s1 - *(const unsigned char*)--s2;
  87. }
  88. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strncmp.html
  89. int strncmp(const char* s1, const char* s2, size_t n)
  90. {
  91. if (!n)
  92. return 0;
  93. do {
  94. if (*s1 != *s2++)
  95. return *(const unsigned char*)s1 - *(const unsigned char*)--s2;
  96. if (*s1++ == 0)
  97. break;
  98. } while (--n);
  99. return 0;
  100. }
  101. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/memcmp.html
  102. int memcmp(const void* v1, const void* v2, size_t n)
  103. {
  104. auto* s1 = (const uint8_t*)v1;
  105. auto* s2 = (const uint8_t*)v2;
  106. while (n-- > 0) {
  107. if (*s1++ != *s2++)
  108. return s1[-1] < s2[-1] ? -1 : 1;
  109. }
  110. return 0;
  111. }
  112. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/memcpy.html
  113. void* memcpy(void* dest_ptr, const void* src_ptr, size_t n)
  114. {
  115. void* original_dest = dest_ptr;
  116. asm volatile(
  117. "rep movsb"
  118. : "+D"(dest_ptr), "+S"(src_ptr), "+c"(n)::"memory");
  119. return original_dest;
  120. }
  121. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/memset.html
  122. void* memset(void* dest_ptr, int c, size_t n)
  123. {
  124. size_t dest = (size_t)dest_ptr;
  125. // FIXME: Support starting at an unaligned address.
  126. if (!(dest & 0x3) && n >= 12) {
  127. size_t size_ts = n / sizeof(size_t);
  128. size_t expanded_c = explode_byte((u8)c);
  129. #if ARCH(I386)
  130. asm volatile(
  131. "rep stosl\n"
  132. : "=D"(dest)
  133. : "D"(dest), "c"(size_ts), "a"(expanded_c)
  134. : "memory");
  135. #else
  136. asm volatile(
  137. "rep stosq\n"
  138. : "=D"(dest)
  139. : "D"(dest), "c"(size_ts), "a"(expanded_c)
  140. : "memory");
  141. #endif
  142. n -= size_ts * sizeof(size_t);
  143. if (n == 0)
  144. return dest_ptr;
  145. }
  146. asm volatile(
  147. "rep stosb\n"
  148. : "=D"(dest), "=c"(n)
  149. : "0"(dest), "1"(n), "a"(c)
  150. : "memory");
  151. return dest_ptr;
  152. }
  153. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/memmove.html
  154. void* memmove(void* dest, const void* src, size_t n)
  155. {
  156. if (((FlatPtr)dest - (FlatPtr)src) >= n)
  157. return memcpy(dest, src, n);
  158. u8* pd = (u8*)dest;
  159. const u8* ps = (const u8*)src;
  160. for (pd += n, ps += n; n--;)
  161. *--pd = *--ps;
  162. return dest;
  163. }
  164. const void* memmem(const void* haystack, size_t haystack_length, const void* needle, size_t needle_length)
  165. {
  166. return AK::memmem(haystack, haystack_length, needle, needle_length);
  167. }
  168. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strcpy.html
  169. char* strcpy(char* dest, const char* src)
  170. {
  171. char* original_dest = dest;
  172. while ((*dest++ = *src++) != '\0')
  173. ;
  174. return original_dest;
  175. }
  176. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strncpy.html
  177. char* strncpy(char* dest, const char* src, size_t n)
  178. {
  179. size_t i;
  180. for (i = 0; i < n && src[i] != '\0'; ++i)
  181. dest[i] = src[i];
  182. for (; i < n; ++i)
  183. dest[i] = '\0';
  184. return dest;
  185. }
  186. size_t strlcpy(char* dest, const char* src, size_t n)
  187. {
  188. size_t i;
  189. // Would like to test i < n - 1 here, but n might be 0.
  190. for (i = 0; i + 1 < n && src[i] != '\0'; ++i)
  191. dest[i] = src[i];
  192. if (n)
  193. dest[i] = '\0';
  194. for (; src[i] != '\0'; ++i)
  195. ; // Determine the length of src, don't copy.
  196. return i;
  197. }
  198. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strchr.html
  199. char* strchr(const char* str, int c)
  200. {
  201. char ch = c;
  202. for (;; ++str) {
  203. if (*str == ch)
  204. return const_cast<char*>(str);
  205. if (!*str)
  206. return nullptr;
  207. }
  208. }
  209. // https://pubs.opengroup.org/onlinepubs/9699959399/functions/index.html
  210. char* index(const char* str, int c)
  211. {
  212. return strchr(str, c);
  213. }
  214. char* strchrnul(const char* str, int c)
  215. {
  216. char ch = c;
  217. for (;; ++str) {
  218. if (*str == ch || !*str)
  219. return const_cast<char*>(str);
  220. }
  221. }
  222. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/memchr.html
  223. void* memchr(const void* ptr, int c, size_t size)
  224. {
  225. char ch = c;
  226. auto* cptr = (const char*)ptr;
  227. for (size_t i = 0; i < size; ++i) {
  228. if (cptr[i] == ch)
  229. return const_cast<char*>(cptr + i);
  230. }
  231. return nullptr;
  232. }
  233. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strrchr.html
  234. char* strrchr(const char* str, int ch)
  235. {
  236. char* last = nullptr;
  237. char c;
  238. for (; (c = *str); ++str) {
  239. if (c == ch)
  240. last = const_cast<char*>(str);
  241. }
  242. return last;
  243. }
  244. // https://pubs.opengroup.org/onlinepubs/9699959399/functions/rindex.html
  245. char* rindex(const char* str, int ch)
  246. {
  247. return strrchr(str, ch);
  248. }
  249. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strcat.html
  250. char* strcat(char* dest, const char* src)
  251. {
  252. size_t dest_length = strlen(dest);
  253. size_t i;
  254. for (i = 0; src[i] != '\0'; i++)
  255. dest[dest_length + i] = src[i];
  256. dest[dest_length + i] = '\0';
  257. return dest;
  258. }
  259. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strncat.html
  260. char* strncat(char* dest, const char* src, size_t n)
  261. {
  262. size_t dest_length = strlen(dest);
  263. size_t i;
  264. for (i = 0; i < n && src[i] != '\0'; i++)
  265. dest[dest_length + i] = src[i];
  266. dest[dest_length + i] = '\0';
  267. return dest;
  268. }
  269. const char* const sys_errlist[] = {
  270. #define __ENUMERATE_ERRNO_CODE(c, s) s,
  271. ENUMERATE_ERRNO_CODES(__ENUMERATE_ERRNO_CODE)
  272. #undef __ENUMERATE_ERRNO_CODE
  273. };
  274. static_assert(array_size(sys_errlist) == (EMAXERRNO + 1));
  275. int sys_nerr = EMAXERRNO;
  276. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strerror_r.html
  277. int strerror_r(int errnum, char* buf, size_t buflen)
  278. {
  279. auto saved_errno = errno;
  280. if (errnum < 0 || errnum >= EMAXERRNO) {
  281. auto rc = strlcpy(buf, "unknown error", buflen);
  282. if (rc >= buflen)
  283. dbgln("strerror_r(): Invalid error number '{}' specified and the output buffer is too small.", errnum);
  284. errno = saved_errno;
  285. return EINVAL;
  286. }
  287. auto text = strerror(errnum);
  288. auto rc = strlcpy(buf, text, buflen);
  289. if (rc >= buflen) {
  290. errno = saved_errno;
  291. return ERANGE;
  292. }
  293. errno = saved_errno;
  294. return 0;
  295. }
  296. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strerror.html
  297. char* strerror(int errnum)
  298. {
  299. if (errnum < 0 || errnum >= EMAXERRNO) {
  300. return const_cast<char*>("Unknown error");
  301. }
  302. return const_cast<char*>(sys_errlist[errnum]);
  303. }
  304. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strsignal.html
  305. char* strsignal(int signum)
  306. {
  307. if (signum >= NSIG) {
  308. dbgln("strsignal() missing string for signum={}", signum);
  309. return const_cast<char*>("Unknown signal");
  310. }
  311. return const_cast<char*>(sys_siglist[signum]);
  312. }
  313. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strstr.html
  314. char* strstr(const char* haystack, const char* needle)
  315. {
  316. char nch;
  317. char hch;
  318. if ((nch = *needle++) != 0) {
  319. size_t len = strlen(needle);
  320. do {
  321. do {
  322. if ((hch = *haystack++) == 0)
  323. return nullptr;
  324. } while (hch != nch);
  325. } while (strncmp(haystack, needle, len) != 0);
  326. --haystack;
  327. }
  328. return const_cast<char*>(haystack);
  329. }
  330. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strpbrk.html
  331. char* strpbrk(const char* s, const char* accept)
  332. {
  333. while (*s)
  334. if (strchr(accept, *s++))
  335. return const_cast<char*>(--s);
  336. return nullptr;
  337. }
  338. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtok_r.html
  339. char* strtok_r(char* str, const char* delim, char** saved_str)
  340. {
  341. if (!str) {
  342. if (!saved_str)
  343. return nullptr;
  344. str = *saved_str;
  345. }
  346. size_t token_start = 0;
  347. size_t token_end = 0;
  348. size_t str_len = strlen(str);
  349. size_t delim_len = strlen(delim);
  350. for (size_t i = 0; i < str_len; ++i) {
  351. bool is_proper_delim = false;
  352. for (size_t j = 0; j < delim_len; ++j) {
  353. if (str[i] == delim[j]) {
  354. // Skip beginning delimiters
  355. if (token_end - token_start == 0) {
  356. ++token_start;
  357. break;
  358. }
  359. is_proper_delim = true;
  360. }
  361. }
  362. ++token_end;
  363. if (is_proper_delim && token_end > 0) {
  364. --token_end;
  365. break;
  366. }
  367. }
  368. if (str[token_start] == '\0')
  369. return nullptr;
  370. if (token_end == 0) {
  371. *saved_str = nullptr;
  372. return &str[token_start];
  373. }
  374. if (str[token_end] == '\0')
  375. *saved_str = &str[token_end];
  376. else
  377. *saved_str = &str[token_end + 1];
  378. str[token_end] = '\0';
  379. return &str[token_start];
  380. }
  381. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtok.html
  382. char* strtok(char* str, const char* delim)
  383. {
  384. static char* saved_str;
  385. return strtok_r(str, delim, &saved_str);
  386. }
  387. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strcoll.html
  388. int strcoll(const char* s1, const char* s2)
  389. {
  390. return strcmp(s1, s2);
  391. }
  392. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strxfrm.html
  393. size_t strxfrm(char* dest, const char* src, size_t n)
  394. {
  395. size_t i;
  396. for (i = 0; i < n && src[i] != '\0'; ++i)
  397. dest[i] = src[i];
  398. for (; i < n; ++i)
  399. dest[i] = '\0';
  400. return i;
  401. }
  402. void explicit_bzero(void* ptr, size_t size)
  403. {
  404. secure_zero(ptr, size);
  405. }
  406. }