string.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * Copyright (c) 2012-2019 Richard Braun.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. *
  18. * Trivial, portable implementations.
  19. */
  20. #include <errno.h>
  21. #include <stdbool.h>
  22. #include <stddef.h>
  23. #include <stdint.h>
  24. #include <string.h>
  25. #include <kern/macros.h>
  26. #include <machine/string.h>
  27. #ifndef STRING_ARCH_MEMCPY
  28. void*
  29. memcpy (void *dest, const void *src, size_t n)
  30. {
  31. char *dest_ptr = dest;
  32. const char *src_ptr = src;
  33. for (size_t i = 0; i < n; i++)
  34. *dest_ptr++ = *src_ptr++;
  35. return (dest);
  36. }
  37. #endif
  38. #ifndef STRING_ARCH_MEMMOVE
  39. void*
  40. memmove (void *dest, const void *src, size_t n)
  41. {
  42. if (dest <= src)
  43. return (memcpy (dest, src, n));
  44. char *dest_ptr = dest + n - 1;
  45. const char *src_ptr = src + n - 1;
  46. for (size_t i = 0; i < n; i++)
  47. *--dest_ptr = *--src_ptr;
  48. return (dest);
  49. }
  50. #endif
  51. #ifndef STRING_ARCH_MEMSET
  52. void*
  53. memset (void *s, int c, size_t n)
  54. {
  55. for (size_t i = 0; i < n; ++i)
  56. ((unsigned char *)s)[i] = c;
  57. return (s);
  58. }
  59. #endif
  60. #ifndef STRING_ARCH_MEMCMP
  61. int
  62. memcmp (const void *s1, const void *s2, size_t n)
  63. {
  64. const unsigned char *a1 = s1, *a2 = s2;
  65. for (size_t i = 0; i < n; i++)
  66. if (a1[i] != a2[i])
  67. return ((int)a1[i] - (int)a2[i]);
  68. return (0);
  69. }
  70. #endif
  71. #ifndef STRING_ARCH_STRLEN
  72. size_t
  73. strlen (const char *s)
  74. {
  75. const char *start = s;
  76. for (; *s; ++s)
  77. ;
  78. return (s - start);
  79. }
  80. #endif
  81. #ifndef STRING_ARCH_STRCPY
  82. char *
  83. strcpy (char *dest, const char *src)
  84. {
  85. char *tmp = dest;
  86. while (*dest++ = *src++)
  87. ;
  88. return (tmp);
  89. }
  90. #endif
  91. size_t
  92. strlcpy (char *dest, const char *src, size_t n)
  93. {
  94. size_t len = strlen (src);
  95. if (! n)
  96. return (len);
  97. n = len < n ? len : n - 1;
  98. memcpy (dest, src, n);
  99. dest[n] = '\0';
  100. return len;
  101. }
  102. #ifndef STRING_ARCH_STRCMP
  103. int
  104. strcmp (const char *s1, const char *s2)
  105. {
  106. char c1, c2;
  107. for (; (c1 = *s1) == (c2 = *s2); ++s1, ++s2)
  108. if (! c1)
  109. return (0);
  110. // See C11 7.24.4 Comparison functions.
  111. return ((int)(unsigned char)c1 - (int)(unsigned char)c2);
  112. }
  113. #endif
  114. #ifndef STRING_ARCH_STRNCMP
  115. int
  116. strncmp (const char *s1, const char *s2, size_t n)
  117. {
  118. if (unlikely (! n))
  119. return (0);
  120. char c1, c2;
  121. for (; n && (c1 = *s1) == (c2 = *s2); --n, ++s1, ++s2)
  122. if (! c1)
  123. return (0);
  124. // See C11 7.24.4 Comparison functions */
  125. return ((int) (unsigned char)c1 - (int)(unsigned char)c2);
  126. }
  127. #endif
  128. #ifndef STRING_ARCH_STRCHR
  129. char*
  130. strchr (const char *s, int c)
  131. {
  132. for ( ; ; ++s)
  133. if (*s == c)
  134. return ((char *)s);
  135. else if (*s == '\0')
  136. return (NULL);
  137. }
  138. #endif
  139. static const uintptr_t ONES_ZEROES = (~((uintptr_t)0)) / 0xff;
  140. static const uintptr_t HIGH_BITS = ONES_ZEROES * (0xff / 2 + 1);
  141. static inline bool
  142. has_zero (uintptr_t v)
  143. {
  144. return ((v - ONES_ZEROES) & ~v & HIGH_BITS);
  145. }
  146. void*
  147. memchr (const void *src, int c, size_t n)
  148. {
  149. _Auto s = (const unsigned char *)src;
  150. for (; ((uintptr_t)s & (sizeof (uintptr_t) - 1)) && n && *s != c; ++s, --n)
  151. ;
  152. if (n && *s != c)
  153. {
  154. uintptr_t key = ONES_ZEROES * c;
  155. const uintptr_t __attribute__ ((may_alias)) *w = (const void *)s;
  156. for (; n >= sizeof (uintptr_t) && !has_zero (*w ^ key);
  157. ++w, n -= sizeof (uintptr_t))
  158. ;
  159. s = (const void *)w;
  160. }
  161. for (; n && *s != c; ++s, --n)
  162. ;
  163. return (n ? (void *)s : NULL);
  164. }
  165. const char*
  166. strerror (int error)
  167. {
  168. switch (error)
  169. {
  170. case 0:
  171. return ("success");
  172. case ENOMEM:
  173. return ("out of memory");
  174. case EAGAIN:
  175. return ("resource temporarily unavailable");
  176. case EINVAL:
  177. return ("invalid argument");
  178. case EBUSY:
  179. return ("device or resource busy");
  180. case EFAULT:
  181. return ("bad address");
  182. case ENODEV:
  183. return ("no such device");
  184. case EEXIST:
  185. return ("entry exists");
  186. case EIO:
  187. return ("input/output error");
  188. case ESRCH:
  189. return ("no such process");
  190. case ETIMEDOUT:
  191. return ("timeout error");
  192. case ENOENT:
  193. return ("no such file or directory");
  194. case EOVERFLOW:
  195. return ("value too large to be stored in data type");
  196. case EMSGSIZE:
  197. return ("message too long");
  198. case EACCES:
  199. return ("permission denied");
  200. case EINTR:
  201. return ("interrupted call");
  202. case EBADF:
  203. return ("bad file descriptor");
  204. case E2BIG:
  205. return ("value too big");
  206. case EINPROGRESS:
  207. return ("operation in progress");
  208. case EALREADY:
  209. return ("operation already in progress");
  210. case EPERM:
  211. return ("operation not permitted");
  212. case ENXIO:
  213. return ("no such device or address");
  214. default:
  215. return ("unknown error");
  216. }
  217. }