string.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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 <stddef.h>
  22. #include <string.h>
  23. #include <kern/macros.h>
  24. #include <machine/string.h>
  25. #ifndef STRING_ARCH_MEMCPY
  26. void *
  27. memcpy(void *dest, const void *src, size_t n)
  28. {
  29. const char *src_ptr;
  30. char *dest_ptr;
  31. size_t i;
  32. dest_ptr = dest;
  33. src_ptr = src;
  34. for (i = 0; i < n; i++) {
  35. *dest_ptr = *src_ptr;
  36. dest_ptr++;
  37. src_ptr++;
  38. }
  39. return dest;
  40. }
  41. #endif /* STRING_ARCH_MEMCPY */
  42. #ifndef STRING_ARCH_MEMMOVE
  43. void *
  44. memmove(void *dest, const void *src, size_t n)
  45. {
  46. const char *src_ptr;
  47. char *dest_ptr;
  48. size_t i;
  49. if (dest <= src) {
  50. dest_ptr = dest;
  51. src_ptr = src;
  52. for (i = 0; i < n; i++) {
  53. *dest_ptr = *src_ptr;
  54. dest_ptr++;
  55. src_ptr++;
  56. }
  57. } else {
  58. dest_ptr = dest + n - 1;
  59. src_ptr = src + n - 1;
  60. for (i = 0; i < n; i++) {
  61. *dest_ptr = *src_ptr;
  62. dest_ptr--;
  63. src_ptr--;
  64. }
  65. }
  66. return dest;
  67. }
  68. #endif /* STRING_ARCH_MEMMOVE */
  69. #ifndef STRING_ARCH_MEMSET
  70. void *
  71. memset(void *s, int c, size_t n)
  72. {
  73. char *buffer;
  74. size_t i;
  75. buffer = s;
  76. for (i = 0; i < n; i++) {
  77. buffer[i] = c;
  78. }
  79. return s;
  80. }
  81. #endif /* STRING_ARCH_MEMSET */
  82. #ifndef STRING_ARCH_MEMCMP
  83. int
  84. memcmp(const void *s1, const void *s2, size_t n)
  85. {
  86. const unsigned char *a1, *a2;
  87. size_t i;
  88. a1 = s1;
  89. a2 = s2;
  90. for (i = 0; i < n; i++) {
  91. if (a1[i] != a2[i]) {
  92. return (int)a1[i] - (int)a2[i];
  93. }
  94. }
  95. return 0;
  96. }
  97. #endif /* STRING_ARCH_MEMCMP */
  98. #ifndef STRING_ARCH_STRLEN
  99. size_t
  100. strlen(const char *s)
  101. {
  102. const char *start;
  103. start = s;
  104. while (*s != '\0') {
  105. s++;
  106. }
  107. return (s - start);
  108. }
  109. #endif /* STRING_ARCH_STRLEN */
  110. #ifndef STRING_ARCH_STRCPY
  111. char *
  112. strcpy(char *dest, const char *src)
  113. {
  114. char *tmp;
  115. tmp = dest;
  116. while ((*dest = *src) != '\0') {
  117. dest++;
  118. src++;
  119. }
  120. return tmp;
  121. }
  122. #endif /* STRING_ARCH_STRCPY */
  123. size_t
  124. strlcpy(char *dest, const char *src, size_t n)
  125. {
  126. size_t len;
  127. len = strlen(src);
  128. if (n == 0) {
  129. goto out;
  130. }
  131. n = (len < n) ? len : n - 1;
  132. memcpy(dest, src, n);
  133. dest[n] = '\0';
  134. out:
  135. return len;
  136. }
  137. #ifndef STRING_ARCH_STRCMP
  138. int
  139. strcmp(const char *s1, const char *s2)
  140. {
  141. char c1, c2;
  142. while ((c1 = *s1) == (c2 = *s2)) {
  143. if (c1 == '\0') {
  144. return 0;
  145. }
  146. s1++;
  147. s2++;
  148. }
  149. /* See C11 7.24.4 Comparison functions */
  150. return (int)(unsigned char)c1 - (int)(unsigned char)c2;
  151. }
  152. #endif /* STRING_ARCH_STRCMP */
  153. #ifndef STRING_ARCH_STRNCMP
  154. int
  155. strncmp(const char *s1, const char *s2, size_t n)
  156. {
  157. char c1, c2;
  158. if (unlikely(n == 0)) {
  159. return 0;
  160. }
  161. while ((n != 0) && (c1 = *s1) == (c2 = *s2)) {
  162. if (c1 == '\0') {
  163. return 0;
  164. }
  165. n--;
  166. s1++;
  167. s2++;
  168. }
  169. /* See C11 7.24.4 Comparison functions */
  170. return (int)(unsigned char)c1 - (int)(unsigned char)c2;
  171. }
  172. #endif /* STRING_ARCH_STRNCMP */
  173. #ifndef STRING_ARCH_STRCHR
  174. char *
  175. strchr(const char *s, int c)
  176. {
  177. for (;;) {
  178. if (*s == c) {
  179. return (char *)s;
  180. } else if (*s == '\0') {
  181. return NULL;
  182. }
  183. s++;
  184. }
  185. }
  186. #endif /* STRING_ARCH_STRCHR */
  187. const char *
  188. strerror(int error)
  189. {
  190. switch (error) {
  191. case 0:
  192. return "success";
  193. case ENOMEM:
  194. return "out of memory";
  195. case EAGAIN:
  196. return "resource temporarily unavailable";
  197. case EINVAL:
  198. return "invalid argument";
  199. case EBUSY:
  200. return "device or resource busy";
  201. case EFAULT:
  202. return "bad address";
  203. case ENODEV:
  204. return "no such device";
  205. case EEXIST:
  206. return "entry exists";
  207. case EIO:
  208. return "input/output error";
  209. case ESRCH:
  210. return "no such process";
  211. case ETIMEDOUT:
  212. return "timeout error";
  213. case ENOENT:
  214. return "no such file or directory";
  215. case EOVERFLOW:
  216. return "value too large to be stored in data type";
  217. case EMSGSIZE:
  218. return "message too long";
  219. default:
  220. return "unknown error";
  221. }
  222. }