1/*
2 * Copyright (C) 2020-2022 The opuntiaOS Project Authors.
3 * + Contributed by Nikita Melekhin <nimelehin@gmail.com>
4 * + Contributed by bellrise <bellrise.dev@gmail.com>
5 *
6 * Use of this source code is governed by a BSD-style license that can be
7 * found in the LICENSE file.
8 */
9#include <string.h>
10
11#ifdef __i386__
12void* memset(void* dest, int fill, size_t nbytes)
13{
14 for (int i = 0; i < nbytes; ++i)
15 ((uint8_t*)dest)[i] = fill;
16
17 return dest;
18}
19#endif //__i386__
20
21void* memmove(void* dest, const void* src, size_t nbytes)
22{
23 if (src > dest) {
24 memcpy(dest, src, nbytes);
25 return dest;
26 }
27
28 for (int i = nbytes - 1; i >= 0; --i)
29 ((uint8_t*)dest)[i] = ((uint8_t*)src)[i];
30
31 return dest;
32}
33
34/* This optimized version of memcpy uses 32 bit chunks to copy over data on
35 the 32 bit architecture this library is built for. If this function gets
36 used on a 64 bit arch, be sure to use 8 byte chunks so each chunk fits
37 in a single register. The important part is this should be compiled with
38 atleast -O1 or -Os, because -O0 just makes this function too big for what
39 it does.
40
41 GCC does a better job at optimizing this if the pointers are restricted,
42 making the copying part have less instructions. Clang on the other hand
43 does not really change anything if the pointers are restricted or not. */
44void* memcpy(void* __restrict dest, const void* __restrict src, size_t nbytes)
45{
46 size_t chunks, rest, i;
47
48 rest = nbytes % 4;
49 chunks = (nbytes - rest) >> 2;
50
51 if (!chunks)
52 goto skip_chunks;
53
54 for (i = 0; i < chunks; i++)
55 ((uint32_t*)dest)[i] = ((uint32_t*)src)[i];
56
57skip_chunks:
58
59 /* Multiplying chunks by 4 will give us the offset of the 'rest' bytes,
60 which were not copied over along with the 4 byte chunks. */
61 chunks <<= 2;
62
63 for (i = 0; i < rest; i++)
64 ((uint8_t*)dest)[chunks + i] = ((uint8_t*)src)[chunks + i];
65
66 return dest;
67}
68
69void* memccpy(void* dest, const void* src, int stop, size_t nbytes)
70{
71 for (int i = 0; i < nbytes; i++) {
72 *((uint8_t*)dest + i) = *((uint8_t*)src + i);
73
74 if (*((uint8_t*)src + i) == stop)
75 return ((uint8_t*)dest + i + 1);
76 }
77 return NULL;
78}
79
80int memcmp(const void* src1, const void* src2, size_t nbytes)
81{
82 const uint8_t* first = src1;
83 const uint8_t* second = src2;
84
85 for (int i = 0; i < nbytes; i++) {
86 /* Return the difference if the byte does not match. */
87 if (first[i] != second[i])
88 return (int)first[i] - (int)second[i];
89 }
90
91 return 0;
92}
93
94int strcmp(const char* a, const char* b)
95{
96 while (*a == *b && *a != '\0' && *b != '\0') {
97 a++;
98 b++;
99 }
100
101 if (*a < *b) {
102 return -1;
103 }
104 if (*a > *b) {
105 return 1;
106 }
107 return 0;
108}
109
110int strncmp(const char* a, const char* b, size_t num)
111{
112 while (*a == *b && *a != 0 && *b != 0 && num) {
113 a++;
114 b++;
115 num--;
116 }
117
118 if (!num) {
119 return 0;
120 }
121
122 if (*a < *b) {
123 return -1;
124 }
125 if (*a > *b) {
126 return 1;
127 }
128 return 0;
129}
130
131size_t strlen(const char* str)
132{
133 size_t i = 0;
134 while (str[i])
135 ++i;
136 return i;
137}
138
139char* strcpy(char* dest, const char* src)
140{
141 size_t i;
142 for (i = 0; src[i] != 0; i++)
143 dest[i] = src[i];
144
145 dest[i] = '\0';
146 return dest;
147}
148
149char* strncpy(char* dest, const char* src, size_t nbytes)
150{
151 size_t i;
152
153 for (i = 0; i < nbytes && src[i] != 0; i++)
154 dest[i] = src[i];
155
156 /* Fill the rest with null bytes */
157 for (; i < nbytes; i++)
158 dest[i] = 0;
159
160 return dest;
161}
162
163char* strchr(const char* s, int c)
164{
165 for (;; s++) {
166 if (*s == c) {
167 return (char*)s;
168 }
169 if (!(*s)) {
170 return NULL;
171 }
172 }
173}