/*************************************************************************************************** Zyan Core Library (Zycore-C) Original Author : Florian Bernd, Joel Hoener * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Provides a simple LibC abstraction and fallback routines. */ #ifndef ZYCORE_LIBC_H #define ZYCORE_LIBC_H #ifndef ZYAN_CUSTOM_LIBC // Include a custom LibC header and define `ZYAN_CUSTOM_LIBC` to provide your own LibC // replacement functions #ifndef ZYAN_NO_LIBC /* ============================================================================================== */ /* LibC is available */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* errno.h */ /* ---------------------------------------------------------------------------------------------- */ #include #define ZYAN_ERRNO errno /* ---------------------------------------------------------------------------------------------- */ /* stdarg.h */ /* ---------------------------------------------------------------------------------------------- */ #include /** * Defines the `ZyanVAList` datatype. */ typedef va_list ZyanVAList; #define ZYAN_VA_START va_start #define ZYAN_VA_ARG va_arg #define ZYAN_VA_END va_end #define ZYAN_VA_COPY(dest, source) va_copy((dest), (source)) /* ---------------------------------------------------------------------------------------------- */ /* stdio.h */ /* ---------------------------------------------------------------------------------------------- */ #include #define ZYAN_FPUTS fputs #define ZYAN_FPUTC fputc #define ZYAN_FPRINTF fprintf #define ZYAN_PRINTF printf #define ZYAN_PUTC putc #define ZYAN_PUTS puts #define ZYAN_SCANF scanf #define ZYAN_SSCANF sscanf #define ZYAN_VSNPRINTF vsnprintf /** * Defines the `ZyanFile` datatype. */ typedef FILE ZyanFile; #define ZYAN_STDIN stdin #define ZYAN_STDOUT stdout #define ZYAN_STDERR stderr /* ---------------------------------------------------------------------------------------------- */ /* stdlib.h */ /* ---------------------------------------------------------------------------------------------- */ #include #define ZYAN_CALLOC calloc #define ZYAN_FREE free #define ZYAN_MALLOC malloc #define ZYAN_REALLOC realloc /* ---------------------------------------------------------------------------------------------- */ /* string.h */ /* ---------------------------------------------------------------------------------------------- */ #include #define ZYAN_MEMCHR memchr #define ZYAN_MEMCMP memcmp #define ZYAN_MEMCPY memcpy #define ZYAN_MEMMOVE memmove #define ZYAN_MEMSET memset #define ZYAN_STRCAT strcat #define ZYAN_STRCHR strchr #define ZYAN_STRCMP strcmp #define ZYAN_STRCOLL strcoll #define ZYAN_STRCPY strcpy #define ZYAN_STRCSPN strcspn #define ZYAN_STRLEN strlen #define ZYAN_STRNCAT strncat #define ZYAN_STRNCMP strncmp #define ZYAN_STRNCPY strncpy #define ZYAN_STRPBRK strpbrk #define ZYAN_STRRCHR strrchr #define ZYAN_STRSPN strspn #define ZYAN_STRSTR strstr #define ZYAN_STRTOK strtok #define ZYAN_STRXFRM strxfrm /* ---------------------------------------------------------------------------------------------- */ #else // if ZYAN_NO_LIBC /* ============================================================================================== */ /* No LibC available, use our own functions */ /* ============================================================================================== */ #include #include /* * These implementations are by no means optimized and will be outperformed by pretty much any * libc implementation out there. We do not aim towards providing competetive implementations here, * but towards providing a last resort fallback for environments without a working libc. */ /* ---------------------------------------------------------------------------------------------- */ /* stdarg.h */ /* ---------------------------------------------------------------------------------------------- */ #if defined(ZYAN_MSVC) || defined(ZYAN_ICC) /** * Defines the `ZyanVAList` datatype. */ typedef char* ZyanVAList; # define ZYAN_VA_START __crt_va_start # define ZYAN_VA_ARG __crt_va_arg # define ZYAN_VA_END __crt_va_end # define ZYAN_VA_COPY(destination, source) ((destination) = (source)) #elif defined(ZYAN_GNUC) /** * Defines the `ZyanVAList` datatype. */ typedef __builtin_va_list ZyanVAList; # define ZYAN_VA_START(v, l) __builtin_va_start(v, l) # define ZYAN_VA_END(v) __builtin_va_end(v) # define ZYAN_VA_ARG(v, l) __builtin_va_arg(v, l) # define ZYAN_VA_COPY(d, s) __builtin_va_copy(d, s) #else # error "Unsupported compiler for no-libc mode." #endif /* ---------------------------------------------------------------------------------------------- */ /* stdio.h */ /* ---------------------------------------------------------------------------------------------- */ // ZYAN_INLINE int ZYAN_VSNPRINTF (char* const buffer, ZyanUSize const count, // char const* const format, ZyanVAList args) // { // // We cant provide a fallback implementation for this function // ZYAN_UNUSED(buffer); // ZYAN_UNUSED(count); // ZYAN_UNUSED(format); // ZYAN_UNUSED(args); // return ZYAN_NULL; // } /* ---------------------------------------------------------------------------------------------- */ /* stdlib.h */ /* ---------------------------------------------------------------------------------------------- */ // ZYAN_INLINE void* ZYAN_CALLOC(ZyanUSize nitems, ZyanUSize size) // { // // We cant provide a fallback implementation for this function // ZYAN_UNUSED(nitems); // ZYAN_UNUSED(size); // return ZYAN_NULL; // } // // ZYAN_INLINE void ZYAN_FREE(void *p) // { // // We cant provide a fallback implementation for this function // ZYAN_UNUSED(p); // } // // ZYAN_INLINE void* ZYAN_MALLOC(ZyanUSize n) // { // // We cant provide a fallback implementation for this function // ZYAN_UNUSED(n); // return ZYAN_NULL; // } // // ZYAN_INLINE void* ZYAN_REALLOC(void* p, ZyanUSize n) // { // // We cant provide a fallback implementation for this function // ZYAN_UNUSED(p); // ZYAN_UNUSED(n); // return ZYAN_NULL; // } /* ---------------------------------------------------------------------------------------------- */ /* string.h */ /* ---------------------------------------------------------------------------------------------- */ ZYAN_INLINE void* ZYAN_MEMCHR(const void* str, int c, ZyanUSize n) { const ZyanU8* p = (ZyanU8*)str; while (n--) { if (*p != (ZyanU8)c) { p++; } else { return (void*)p; } } return 0; } ZYAN_INLINE int ZYAN_MEMCMP(const void* s1, const void* s2, ZyanUSize n) { const ZyanU8* p1 = s1, *p2 = s2; while (n--) { if (*p1 != *p2) { return *p1 - *p2; } p1++, p2++; } return 0; } ZYAN_INLINE void* ZYAN_MEMCPY(void* dst, const void* src, ZyanUSize n) { volatile ZyanU8* dp = dst; const ZyanU8* sp = src; while (n--) { *dp++ = *sp++; } return dst; } ZYAN_INLINE void* ZYAN_MEMMOVE(void* dst, const void* src, ZyanUSize n) { volatile ZyanU8* pd = dst; const ZyanU8* ps = src; if (ps < pd) { for (pd += n, ps += n; n--;) { *--pd = *--ps; } } else { while (n--) { *pd++ = *ps++; } } return dst; } ZYAN_INLINE void* ZYAN_MEMSET(void* dst, int val, ZyanUSize n) { volatile ZyanU8* p = dst; while (n--) { *p++ = (unsigned char)val; } return dst; } ZYAN_INLINE char* ZYAN_STRCAT(char* dest, const char* src) { char* ret = dest; while (*dest) { dest++; } while ((*dest++ = *src++)); return ret; } ZYAN_INLINE char* ZYAN_STRCHR(const char* s, int c) { while (*s != (char)c) { if (!*s++) { return 0; } } return (char*)s; } ZYAN_INLINE int ZYAN_STRCMP(const char* s1, const char* s2) { while (*s1 && (*s1 == *s2)) { s1++, s2++; } return *(const ZyanU8*)s1 - *(const ZyanU8*)s2; } ZYAN_INLINE int ZYAN_STRCOLL(const char *s1, const char *s2) { // TODO: Implement ZYAN_UNUSED(s1); ZYAN_UNUSED(s2); return 0; } ZYAN_INLINE char* ZYAN_STRCPY(char* dest, const char* src) { char* ret = dest; while ((*dest++ = *src++)); return ret; } ZYAN_INLINE ZyanUSize ZYAN_STRCSPN(const char *s1, const char *s2) { ZyanUSize ret = 0; while (*s1) { if (ZYAN_STRCHR(s2, *s1)) { return ret; } s1++, ret++; } return ret; } ZYAN_INLINE ZyanUSize ZYAN_STRLEN(const char* str) { const char* p = str; while (*str) { ++str; } return str - p; } ZYAN_INLINE char* ZYAN_STRNCAT(char* dest, const char* src, ZyanUSize n) { char* ret = dest; while (*dest) { dest++; } while (n--) { if (!(*dest++ = *src++)) { return ret; } } *dest = 0; return ret; } ZYAN_INLINE int ZYAN_STRNCMP(const char* s1, const char* s2, ZyanUSize n) { while (n--) { if (*s1++ != *s2++) { return *(unsigned char*)(s1 - 1) - *(unsigned char*)(s2 - 1); } } return 0; } ZYAN_INLINE char* ZYAN_STRNCPY(char* dest, const char* src, ZyanUSize n) { char* ret = dest; do { if (!n--) { return ret; } } while ((*dest++ = *src++)); while (n--) { *dest++ = 0; } return ret; } ZYAN_INLINE char* ZYAN_STRPBRK(const char* s1, const char* s2) { while (*s1) { if(ZYAN_STRCHR(s2, *s1++)) { return (char*)--s1; } } return 0; } ZYAN_INLINE char* ZYAN_STRRCHR(const char* s, int c) { char* ret = 0; do { if (*s == (char)c) { ret = (char*)s; } } while (*s++); return ret; } ZYAN_INLINE ZyanUSize ZYAN_STRSPN(const char* s1, const char* s2) { ZyanUSize ret = 0; while (*s1 && ZYAN_STRCHR(s2, *s1++)) { ret++; } return ret; } ZYAN_INLINE char* ZYAN_STRSTR(const char* s1, const char* s2) { const ZyanUSize n = ZYAN_STRLEN(s2); while (*s1) { if (!ZYAN_MEMCMP(s1++, s2, n)) { return (char*)(s1 - 1); } } return 0; } ZYAN_INLINE char* ZYAN_STRTOK(char* str, const char* delim) { static char* p = 0; if (str) { p = str; } else if (!p) { return 0; } str = p + ZYAN_STRSPN(p, delim); p = str + ZYAN_STRCSPN(str, delim); if (p == str) { return p = 0; } p = *p ? *p = 0, p + 1 : 0; return str; } ZYAN_INLINE ZyanUSize ZYAN_STRXFRM(char* dest, const char* src, ZyanUSize n) { const ZyanUSize n2 = ZYAN_STRLEN(src); if (n > n2) { ZYAN_STRCPY(dest, src); } return n2; } /* ---------------------------------------------------------------------------------------------- */ #endif #endif /* ============================================================================================== */ #endif /* ZYCORE_LIBC_H */