1 /*************************************************************************************************** 2 3 Zyan Core Library (Zycore-C) 4 5 Original Author : Florian Bernd, Joel Hoener 6 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 25 ***************************************************************************************************/ 26 27 /** 28 * @file 29 * Provides a simple LibC abstraction and fallback routines. 30 */ 31 32 #ifndef ZYCORE_LIBC_H 33 #define ZYCORE_LIBC_H 34 35 #ifndef ZYAN_CUSTOM_LIBC 36 37 // Include a custom LibC header and define `ZYAN_CUSTOM_LIBC` to provide your own LibC 38 // replacement functions 39 40 #ifndef ZYAN_NO_LIBC 41 42 /* ============================================================================================== */ 43 /* LibC is available */ 44 /* ============================================================================================== */ 45 46 /* ---------------------------------------------------------------------------------------------- */ 47 /* errno.h */ 48 /* ---------------------------------------------------------------------------------------------- */ 49 50 #include <errno.h> 51 52 #define ZYAN_ERRNO errno 53 54 /* ---------------------------------------------------------------------------------------------- */ 55 /* stdarg.h */ 56 /* ---------------------------------------------------------------------------------------------- */ 57 58 #include <stdarg.h> 59 60 /** 61 * Defines the `ZyanVAList` datatype. 62 */ 63 typedef va_list ZyanVAList; 64 65 #define ZYAN_VA_START va_start 66 #define ZYAN_VA_ARG va_arg 67 #define ZYAN_VA_END va_end 68 #define ZYAN_VA_COPY(dest, source) va_copy((dest), (source)) 69 70 /* ---------------------------------------------------------------------------------------------- */ 71 /* stdio.h */ 72 /* ---------------------------------------------------------------------------------------------- */ 73 74 #include <stdio.h> 75 76 #define ZYAN_FPUTS fputs 77 #define ZYAN_FPUTC fputc 78 #define ZYAN_FPRINTF fprintf 79 #define ZYAN_PRINTF printf 80 #define ZYAN_PUTC putc 81 #define ZYAN_PUTS puts 82 #define ZYAN_SCANF scanf 83 #define ZYAN_SSCANF sscanf 84 #define ZYAN_VSNPRINTF vsnprintf 85 86 /** 87 * Defines the `ZyanFile` datatype. 88 */ 89 typedef FILE ZyanFile; 90 91 #define ZYAN_STDIN stdin 92 #define ZYAN_STDOUT stdout 93 #define ZYAN_STDERR stderr 94 95 /* ---------------------------------------------------------------------------------------------- */ 96 /* stdlib.h */ 97 /* ---------------------------------------------------------------------------------------------- */ 98 99 #include <stdlib.h> 100 #define ZYAN_CALLOC calloc 101 #define ZYAN_FREE free 102 #define ZYAN_GETENV getenv 103 #define ZYAN_MALLOC malloc 104 #define ZYAN_REALLOC realloc 105 106 /* ---------------------------------------------------------------------------------------------- */ 107 /* string.h */ 108 /* ---------------------------------------------------------------------------------------------- */ 109 110 #include <string.h> 111 #define ZYAN_MEMCHR memchr 112 #define ZYAN_MEMCMP memcmp 113 #define ZYAN_MEMCPY memcpy 114 #define ZYAN_MEMMOVE memmove 115 #define ZYAN_MEMSET memset 116 #define ZYAN_STRCAT strcat 117 #define ZYAN_STRCHR strchr 118 #define ZYAN_STRCMP strcmp 119 #define ZYAN_STRCOLL strcoll 120 #define ZYAN_STRCPY strcpy 121 #define ZYAN_STRCSPN strcspn 122 #define ZYAN_STRLEN strlen 123 #define ZYAN_STRNCAT strncat 124 #define ZYAN_STRNCMP strncmp 125 #define ZYAN_STRNCPY strncpy 126 #define ZYAN_STRPBRK strpbrk 127 #define ZYAN_STRRCHR strrchr 128 #define ZYAN_STRSPN strspn 129 #define ZYAN_STRSTR strstr 130 #define ZYAN_STRTOK strtok 131 #define ZYAN_STRXFRM strxfrm 132 133 /* ---------------------------------------------------------------------------------------------- */ 134 135 #else // if ZYAN_NO_LIBC 136 137 /* ============================================================================================== */ 138 /* No LibC available, use our own functions */ 139 /* ============================================================================================== */ 140 141 #include <Zycore/Defines.h> 142 #include <Zycore/Types.h> 143 144 /* 145 * These implementations are by no means optimized and will be outperformed by pretty much any 146 * libc implementation out there. We do not aim towards providing competetive implementations here, 147 * but towards providing a last resort fallback for environments without a working libc. 148 */ 149 150 /* ---------------------------------------------------------------------------------------------- */ 151 /* stdarg.h */ 152 /* ---------------------------------------------------------------------------------------------- */ 153 154 #if defined(ZYAN_MSVC) || defined(ZYAN_ICC) 155 156 /** 157 * Defines the `ZyanVAList` datatype. 158 */ 159 typedef char* ZyanVAList; 160 161 # define ZYAN_VA_START __crt_va_start 162 # define ZYAN_VA_ARG __crt_va_arg 163 # define ZYAN_VA_END __crt_va_end 164 # define ZYAN_VA_COPY(destination, source) ((destination) = (source)) 165 166 #elif defined(ZYAN_GNUC) 167 168 /** 169 * Defines the `ZyanVAList` datatype. 170 */ 171 typedef __builtin_va_list ZyanVAList; 172 173 # define ZYAN_VA_START(v, l) __builtin_va_start(v, l) 174 # define ZYAN_VA_END(v) __builtin_va_end(v) 175 # define ZYAN_VA_ARG(v, l) __builtin_va_arg(v, l) 176 # define ZYAN_VA_COPY(d, s) __builtin_va_copy(d, s) 177 178 #else 179 # error "Unsupported compiler for no-libc mode." 180 #endif 181 182 /* ---------------------------------------------------------------------------------------------- */ 183 /* stdio.h */ 184 /* ---------------------------------------------------------------------------------------------- */ 185 186 // ZYAN_INLINE int ZYAN_VSNPRINTF (char* const buffer, ZyanUSize const count, 187 // char const* const format, ZyanVAList args) 188 // { 189 // // We cant provide a fallback implementation for this function 190 // ZYAN_UNUSED(buffer); 191 // ZYAN_UNUSED(count); 192 // ZYAN_UNUSED(format); 193 // ZYAN_UNUSED(args); 194 // return ZYAN_NULL; 195 // } 196 197 /* ---------------------------------------------------------------------------------------------- */ 198 /* stdlib.h */ 199 /* ---------------------------------------------------------------------------------------------- */ 200 201 // ZYAN_INLINE void* ZYAN_CALLOC(ZyanUSize nitems, ZyanUSize size) 202 // { 203 // // We cant provide a fallback implementation for this function 204 // ZYAN_UNUSED(nitems); 205 // ZYAN_UNUSED(size); 206 // return ZYAN_NULL; 207 // } 208 // 209 // ZYAN_INLINE void ZYAN_FREE(void *p) 210 // { 211 // // We cant provide a fallback implementation for this function 212 // ZYAN_UNUSED(p); 213 // } 214 // 215 // ZYAN_INLINE void* ZYAN_MALLOC(ZyanUSize n) 216 // { 217 // // We cant provide a fallback implementation for this function 218 // ZYAN_UNUSED(n); 219 // return ZYAN_NULL; 220 // } 221 // 222 // ZYAN_INLINE void* ZYAN_REALLOC(void* p, ZyanUSize n) 223 // { 224 // // We cant provide a fallback implementation for this function 225 // ZYAN_UNUSED(p); 226 // ZYAN_UNUSED(n); 227 // return ZYAN_NULL; 228 // } 229 230 /* ---------------------------------------------------------------------------------------------- */ 231 /* string.h */ 232 /* ---------------------------------------------------------------------------------------------- */ 233 234 ZYAN_INLINE void* ZYAN_MEMCHR(const void* str, int c, ZyanUSize n) 235 { 236 const ZyanU8* p = (ZyanU8*)str; 237 while (n--) 238 { 239 if (*p != (ZyanU8)c) 240 { 241 p++; 242 } else 243 { 244 return (void*)p; 245 } 246 } 247 return 0; 248 } 249 250 ZYAN_INLINE int ZYAN_MEMCMP(const void* s1, const void* s2, ZyanUSize n) 251 { 252 const ZyanU8* p1 = s1, *p2 = s2; 253 while (n--) 254 { 255 if (*p1 != *p2) 256 { 257 return *p1 - *p2; 258 } 259 p1++, p2++; 260 } 261 return 0; 262 } 263 264 ZYAN_INLINE void* ZYAN_MEMCPY(void* dst, const void* src, ZyanUSize n) 265 { 266 volatile ZyanU8* dp = dst; 267 const ZyanU8* sp = src; 268 while (n--) 269 { 270 *dp++ = *sp++; 271 } 272 return dst; 273 } 274 275 ZYAN_INLINE void* ZYAN_MEMMOVE(void* dst, const void* src, ZyanUSize n) 276 { 277 volatile ZyanU8* pd = dst; 278 const ZyanU8* ps = src; 279 if (ps < pd) 280 { 281 for (pd += n, ps += n; n--;) 282 { 283 *--pd = *--ps; 284 } 285 } else 286 { 287 while (n--) 288 { 289 *pd++ = *ps++; 290 } 291 } 292 return dst; 293 } 294 295 ZYAN_INLINE void* ZYAN_MEMSET(void* dst, int val, ZyanUSize n) 296 { 297 volatile ZyanU8* p = dst; 298 while (n--) 299 { 300 *p++ = (unsigned char)val; 301 } 302 return dst; 303 } 304 305 ZYAN_INLINE char* ZYAN_STRCAT(char* dest, const char* src) 306 { 307 char* ret = dest; 308 while (*dest) 309 { 310 dest++; 311 } 312 while ((*dest++ = *src++)); 313 return ret; 314 } 315 316 ZYAN_INLINE char* ZYAN_STRCHR(const char* s, int c) 317 { 318 while (*s != (char)c) 319 { 320 if (!*s++) 321 { 322 return 0; 323 } 324 } 325 return (char*)s; 326 } 327 328 ZYAN_INLINE int ZYAN_STRCMP(const char* s1, const char* s2) 329 { 330 while (*s1 && (*s1 == *s2)) 331 { 332 s1++, s2++; 333 } 334 return *(const ZyanU8*)s1 - *(const ZyanU8*)s2; 335 } 336 337 ZYAN_INLINE int ZYAN_STRCOLL(const char *s1, const char *s2) 338 { 339 // TODO: Implement 340 341 ZYAN_UNUSED(s1); 342 ZYAN_UNUSED(s2); 343 344 return 0; 345 } 346 347 ZYAN_INLINE char* ZYAN_STRCPY(char* dest, const char* src) 348 { 349 char* ret = dest; 350 while ((*dest++ = *src++)); 351 return ret; 352 } 353 354 ZYAN_INLINE ZyanUSize ZYAN_STRCSPN(const char *s1, const char *s2) 355 { 356 ZyanUSize ret = 0; 357 while (*s1) 358 { 359 if (ZYAN_STRCHR(s2, *s1)) 360 { 361 return ret; 362 } 363 s1++, ret++; 364 } 365 return ret; 366 } 367 368 ZYAN_INLINE ZyanUSize ZYAN_STRLEN(const char* str) 369 { 370 const char* p = str; 371 while (*str) 372 { 373 ++str; 374 } 375 return str - p; 376 } 377 378 ZYAN_INLINE char* ZYAN_STRNCAT(char* dest, const char* src, ZyanUSize n) 379 { 380 char* ret = dest; 381 while (*dest) 382 { 383 dest++; 384 } 385 while (n--) 386 { 387 if (!(*dest++ = *src++)) 388 { 389 return ret; 390 } 391 } 392 *dest = 0; 393 return ret; 394 } 395 396 ZYAN_INLINE int ZYAN_STRNCMP(const char* s1, const char* s2, ZyanUSize n) 397 { 398 while (n--) 399 { 400 if (*s1++ != *s2++) 401 { 402 return *(unsigned char*)(s1 - 1) - *(unsigned char*)(s2 - 1); 403 } 404 } 405 return 0; 406 } 407 408 ZYAN_INLINE char* ZYAN_STRNCPY(char* dest, const char* src, ZyanUSize n) 409 { 410 char* ret = dest; 411 do 412 { 413 if (!n--) 414 { 415 return ret; 416 } 417 } while ((*dest++ = *src++)); 418 while (n--) 419 { 420 *dest++ = 0; 421 } 422 return ret; 423 } 424 425 ZYAN_INLINE char* ZYAN_STRPBRK(const char* s1, const char* s2) 426 { 427 while (*s1) 428 { 429 if(ZYAN_STRCHR(s2, *s1++)) 430 { 431 return (char*)--s1; 432 } 433 } 434 return 0; 435 } 436 437 ZYAN_INLINE char* ZYAN_STRRCHR(const char* s, int c) 438 { 439 char* ret = 0; 440 do 441 { 442 if (*s == (char)c) 443 { 444 ret = (char*)s; 445 } 446 } while (*s++); 447 return ret; 448 } 449 450 ZYAN_INLINE ZyanUSize ZYAN_STRSPN(const char* s1, const char* s2) 451 { 452 ZyanUSize ret = 0; 453 while (*s1 && ZYAN_STRCHR(s2, *s1++)) 454 { 455 ret++; 456 } 457 return ret; 458 } 459 460 ZYAN_INLINE char* ZYAN_STRSTR(const char* s1, const char* s2) 461 { 462 const ZyanUSize n = ZYAN_STRLEN(s2); 463 while (*s1) 464 { 465 if (!ZYAN_MEMCMP(s1++, s2, n)) 466 { 467 return (char*)(s1 - 1); 468 } 469 } 470 return 0; 471 } 472 473 ZYAN_INLINE char* ZYAN_STRTOK(char* str, const char* delim) 474 { 475 static char* p = 0; 476 if (str) 477 { 478 p = str; 479 } else 480 if (!p) 481 { 482 return 0; 483 } 484 str = p + ZYAN_STRSPN(p, delim); 485 p = str + ZYAN_STRCSPN(str, delim); 486 if (p == str) 487 { 488 return p = 0; 489 } 490 p = *p ? *p = 0, p + 1 : 0; 491 return str; 492 } 493 494 ZYAN_INLINE ZyanUSize ZYAN_STRXFRM(char* dest, const char* src, ZyanUSize n) 495 { 496 const ZyanUSize n2 = ZYAN_STRLEN(src); 497 if (n > n2) 498 { 499 ZYAN_STRCPY(dest, src); 500 } 501 return n2; 502 } 503 504 /* ---------------------------------------------------------------------------------------------- */ 505 506 #endif 507 508 #endif 509 510 /* ============================================================================================== */ 511 512 #endif /* ZYCORE_LIBC_H */ 513