opuntiaOS - an operating system targeting x86 and ARMv7
at master 4.0 kB view raw
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}