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
ZYAN_MEMCHR(const void * str,int c,ZyanUSize n)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
ZYAN_MEMCMP(const void * s1,const void * s2,ZyanUSize n)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
ZYAN_MEMCPY(void * dst,const void * src,ZyanUSize n)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
ZYAN_MEMMOVE(void * dst,const void * src,ZyanUSize n)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
ZYAN_MEMSET(void * dst,int val,ZyanUSize n)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
ZYAN_STRCAT(char * dest,const char * src)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
ZYAN_STRCHR(const char * s,int c)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
ZYAN_STRCMP(const char * s1,const char * s2)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
ZYAN_STRCOLL(const char * s1,const char * s2)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
ZYAN_STRCPY(char * dest,const char * src)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
ZYAN_STRCSPN(const char * s1,const char * s2)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
ZYAN_STRLEN(const char * str)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
ZYAN_STRNCAT(char * dest,const char * src,ZyanUSize n)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
ZYAN_STRNCMP(const char * s1,const char * s2,ZyanUSize n)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
ZYAN_STRNCPY(char * dest,const char * src,ZyanUSize n)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
ZYAN_STRPBRK(const char * s1,const char * s2)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
ZYAN_STRRCHR(const char * s,int c)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
ZYAN_STRSPN(const char * s1,const char * s2)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
ZYAN_STRSTR(const char * s1,const char * s2)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
ZYAN_STRTOK(char * str,const char * delim)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
ZYAN_STRXFRM(char * dest,const char * src,ZyanUSize n)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