string.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #include <ctype.h>
  2. #include <errno.h>
  3. #include <signal.h>
  4. #include <stdint.h>
  5. #include <stdlib.h>
  6. #define BYTES_PER_MAX_COPY_UNIT (sizeof(uint32_t) / sizeof(uint8_t))
  7. static void* _memcpy(void* _dst, const void* _src, size_t n)
  8. {
  9. void* orig_dst = _dst;
  10. uint8_t* dst = (uint8_t*)_dst;
  11. const uint8_t* src = (const uint8_t*)_src;
  12. for (size_t i = 0; i < n / BYTES_PER_MAX_COPY_UNIT; ++i) {
  13. *(uint32_t*)dst = *(uint32_t*)src;
  14. dst += BYTES_PER_MAX_COPY_UNIT;
  15. src += BYTES_PER_MAX_COPY_UNIT;
  16. }
  17. for (size_t i = 0; i < (n % BYTES_PER_MAX_COPY_UNIT); ++i) {
  18. *((char*)dst++) = *((char*)src++);
  19. }
  20. return orig_dst;
  21. }
  22. static void* _memset(void* _dst, int c, size_t n)
  23. {
  24. uint8_t* dst = (uint8_t*)_dst;
  25. c &= 0xff;
  26. int cc = (c + (c << 8) + (c << 16) + (c << 24));
  27. for (size_t i = 0; i < n / BYTES_PER_MAX_COPY_UNIT; ++i) {
  28. *(uint32_t*)dst = cc;
  29. dst += BYTES_PER_MAX_COPY_UNIT;
  30. }
  31. for (size_t i = 0; i < (n % BYTES_PER_MAX_COPY_UNIT); ++i) {
  32. *((char*)dst++) = c;
  33. }
  34. return dst;
  35. }
  36. static size_t _strlen(const char* str)
  37. {
  38. size_t n = 0;
  39. while (*(str++) != '\0')
  40. ++n;
  41. return n;
  42. }
  43. char* strchr(const char* str, int c)
  44. {
  45. const char* p = str;
  46. while (*p) {
  47. if (*p == c)
  48. return (char*)p;
  49. ++p;
  50. }
  51. return NULL;
  52. }
  53. char* strrchr(const char* str, int c)
  54. {
  55. const char* p = str + _strlen(str) - 1;
  56. while (p >= str) {
  57. if (*p == c)
  58. return (char*)p;
  59. --p;
  60. }
  61. return NULL;
  62. }
  63. char* strchrnul(const char* str, int c)
  64. {
  65. char* ret = strchr(str, c);
  66. if (ret)
  67. return ret;
  68. return (char*)str + _strlen(str);
  69. }
  70. char* strcpy(char* dst, const char* src)
  71. {
  72. return _memcpy(dst, src, _strlen(src) + 1);
  73. }
  74. char* strncpy(char* dst, const char* src, size_t n)
  75. {
  76. size_t len = _strlen(src);
  77. if (len < n) {
  78. _memset(dst + len, 0x00, n - len);
  79. _memcpy(dst, src, len);
  80. } else {
  81. _memcpy(dst, src, n);
  82. }
  83. return dst;
  84. }
  85. char* stpcpy(char* restrict dst, const char* restrict src)
  86. {
  87. return _memcpy(dst, src, _strlen(src) + 1) + _strlen(src);
  88. }
  89. char* stpncpy(char* restrict dst, const char* restrict src, size_t n)
  90. {
  91. size_t len = _strlen(src);
  92. if (len < n) {
  93. _memset(dst + len, 0x00, n - len);
  94. _memcpy(dst, src, len);
  95. } else {
  96. _memcpy(dst, src, n);
  97. }
  98. return dst + len;
  99. }
  100. int strncmp(const char* s1, const char* s2, size_t n)
  101. {
  102. if (n == 0)
  103. return 0;
  104. int c;
  105. while (n-- && (c = *s1 - *s2) == 0 && *s1) {
  106. ++s1;
  107. ++s2;
  108. }
  109. return c;
  110. }
  111. int strcmp(const char* s1, const char* s2)
  112. {
  113. return strncmp(s1, s2, __SIZE_MAX__);
  114. }
  115. int strncasecmp(const char* s1, const char* s2, size_t n)
  116. {
  117. if (n == 0)
  118. return 0;
  119. int c;
  120. while (n-- && (c = tolower(*s1) - tolower(*s2)) == 0 && *s1) {
  121. ++s1;
  122. ++s2;
  123. }
  124. return c;
  125. }
  126. int strcasecmp(const char* s1, const char* s2)
  127. {
  128. return strncasecmp(s1, s2, __SIZE_MAX__);
  129. }
  130. size_t strcspn(const char* str1, const char* str2)
  131. {
  132. size_t ret = 0;
  133. while (*str1) {
  134. ++ret;
  135. for (const char* p = str2; *p; ++p) {
  136. if (*str1 == *p)
  137. return ret;
  138. }
  139. ++str1;
  140. }
  141. return ret;
  142. }
  143. char* strstr(const char* str1, const char* str2)
  144. {
  145. const char* p = str1;
  146. while (*p) {
  147. if (*p != *str2) {
  148. ++p;
  149. continue;
  150. }
  151. const char* p1 = p;
  152. const char* q = str2;
  153. while (*q) {
  154. if (*p1 != *q)
  155. break;
  156. ++p1;
  157. ++q;
  158. }
  159. if (!*q)
  160. break;
  161. p = p1;
  162. }
  163. if (*p)
  164. return (char*)p;
  165. return NULL;
  166. }
  167. char* strpbrk(const char* str1, const char* str2)
  168. {
  169. size_t n = strcspn(str1, str2);
  170. if (str1[n])
  171. return (char*)str1 + n;
  172. return NULL;
  173. }
  174. char* strerror(int errnum)
  175. {
  176. switch (errnum) {
  177. case EPERM:
  178. return "Operation not permitted";
  179. case ENOENT:
  180. return "No such file or directory";
  181. case ESRCH:
  182. return "No such process";
  183. case EINTR:
  184. return "Interrupted system call";
  185. case EBADF:
  186. return "Bad file descriptor";
  187. case ECHILD:
  188. return "No child process";
  189. case ENOMEM:
  190. return "Out of memory";
  191. case EEXIST:
  192. return "File exists";
  193. case ENOTDIR:
  194. return "Not a directory";
  195. case EISDIR:
  196. return "Is a directory";
  197. case EINVAL:
  198. return "Invalid argument";
  199. case ENOTTY:
  200. return "Not a tty";
  201. case EPIPE:
  202. return "Broken pipe";
  203. default:
  204. return "No error information";
  205. }
  206. }
  207. char* strndup(const char* str, size_t n)
  208. {
  209. size_t len = _strlen(str);
  210. if (len > n)
  211. len = n;
  212. char* ret = malloc(len + 1);
  213. if (!ret)
  214. return NULL;
  215. _memcpy(ret, str, len);
  216. ret[len] = 0;
  217. return ret;
  218. }
  219. char* strdup(const char* str)
  220. {
  221. return strndup(str, __SIZE_MAX__);
  222. }
  223. char* strsignal(int sig)
  224. {
  225. switch (sig) {
  226. default:
  227. return "Unknown signal";
  228. case SIGINT:
  229. return "Interrupt";
  230. case SIGQUIT:
  231. return "Quit";
  232. case SIGSTOP:
  233. return "Stopped (signal)";
  234. case SIGPIPE:
  235. return "Broken pipe";
  236. }
  237. }