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 * @brief 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 * @brief 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 * @brief 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_MALLOC malloc
103 #define ZYAN_REALLOC realloc
104
105 /* ---------------------------------------------------------------------------------------------- */
106 /* string.h */
107 /* ---------------------------------------------------------------------------------------------- */
108
109 #include <string.h>
110 #define ZYAN_MEMCHR memchr
111 #define ZYAN_MEMCMP memcmp
112 #define ZYAN_MEMCPY memcpy
113 #define ZYAN_MEMMOVE memmove
114 #define ZYAN_MEMSET memset
115 #define ZYAN_STRCAT strcat
116 #define ZYAN_STRCHR strchr
117 #define ZYAN_STRCMP strcmp
118 #define ZYAN_STRCOLL strcoll
119 #define ZYAN_STRCPY strcpy
120 #define ZYAN_STRCSPN strcspn
121 #define ZYAN_STRLEN strlen
122 #define ZYAN_STRNCAT strncat
123 #define ZYAN_STRNCMP strncmp
124 #define ZYAN_STRNCPY strncpy
125 #define ZYAN_STRPBRK strpbrk
126 #define ZYAN_STRRCHR strrchr
127 #define ZYAN_STRSPN strspn
128 #define ZYAN_STRSTR strstr
129 #define ZYAN_STRTOK strtok
130 #define ZYAN_STRXFRM strxfrm
131
132 /* ---------------------------------------------------------------------------------------------- */
133
134 #else // if ZYAN_NO_LIBC
135
136 /* ============================================================================================== */
137 /* No LibC available, use our own functions */
138 /* ============================================================================================== */
139
140 #include <Zycore/Defines.h>
141 #include <Zycore/Types.h>
142
143 /*
144 * These implementations are by no means optimized and will be outperformed by pretty much any
145 * libc implementation out there. We do not aim towards providing competetive implementations here,
146 * but towards providing a last resort fallback for environments without a working libc.
147 */
148
149 /* ---------------------------------------------------------------------------------------------- */
150 /* stdarg.h */
151 /* ---------------------------------------------------------------------------------------------- */
152
153 #if defined(ZYAN_MSVC) || defined(ZYAN_ICC)
154
155 /**
156 * @brief Defines the `ZyanVAList` datatype.
157 */
158 typedef char* ZyanVAList;
159
160 # define ZYAN_VA_START __crt_va_start
161 # define ZYAN_VA_ARG __crt_va_arg
162 # define ZYAN_VA_END __crt_va_end
163 # define ZYAN_VA_COPY(destination, source) ((destination) = (source))
164
165 #elif defined(ZYAN_GNUC)
166
167 /**
168 * @brief Defines the `ZyanVAList` datatype.
169 */
170 typedef __builtin_va_list ZyanVAList;
171
172 # define ZYAN_VA_START(v, l) __builtin_va_start(v, l)
173 # define ZYAN_VA_END(v) __builtin_va_end(v)
174 # define ZYAN_VA_ARG(v, l) __builtin_va_arg(v, l)
175 # define ZYAN_VA_COPY(d, s) __builtin_va_copy(d, s)
176
177 #else
178 # error "Unsupported compiler for no-libc mode."
179 #endif
180
181 /* ---------------------------------------------------------------------------------------------- */
182 /* stdio.h */
183 /* ---------------------------------------------------------------------------------------------- */
184
185 // ZYAN_INLINE int ZYAN_VSNPRINTF (char* const buffer, ZyanUSize const count,
186 // char const* const format, ZyanVAList args)
187 // {
188 // // We cant provide a fallback implementation for this function
189 // ZYAN_UNUSED(buffer);
190 // ZYAN_UNUSED(count);
191 // ZYAN_UNUSED(format);
192 // ZYAN_UNUSED(args);
193 // return ZYAN_NULL;
194 // }
195
196 /* ---------------------------------------------------------------------------------------------- */
197 /* stdlib.h */
198 /* ---------------------------------------------------------------------------------------------- */
199
200 // ZYAN_INLINE void* ZYAN_CALLOC(ZyanUSize nitems, ZyanUSize size)
201 // {
202 // // We cant provide a fallback implementation for this function
203 // ZYAN_UNUSED(nitems);
204 // ZYAN_UNUSED(size);
205 // return ZYAN_NULL;
206 // }
207 //
208 // ZYAN_INLINE void ZYAN_FREE(void *p)
209 // {
210 // // We cant provide a fallback implementation for this function
211 // ZYAN_UNUSED(p);
212 // }
213 //
214 // ZYAN_INLINE void* ZYAN_MALLOC(ZyanUSize n)
215 // {
216 // // We cant provide a fallback implementation for this function
217 // ZYAN_UNUSED(n);
218 // return ZYAN_NULL;
219 // }
220 //
221 // ZYAN_INLINE void* ZYAN_REALLOC(void* p, ZyanUSize n)
222 // {
223 // // We cant provide a fallback implementation for this function
224 // ZYAN_UNUSED(p);
225 // ZYAN_UNUSED(n);
226 // return ZYAN_NULL;
227 // }
228
229 /* ---------------------------------------------------------------------------------------------- */
230 /* string.h */
231 /* ---------------------------------------------------------------------------------------------- */
232
ZYAN_MEMCHR(const void * str,int c,ZyanUSize n)233 ZYAN_INLINE void* ZYAN_MEMCHR(const void* str, int c, ZyanUSize n)
234 {
235 const ZyanU8* p = (ZyanU8*)str;
236 while (n--)
237 {
238 if (*p != (ZyanU8)c)
239 {
240 p++;
241 } else
242 {
243 return (void*)p;
244 }
245 }
246 return 0;
247 }
248
ZYAN_MEMCMP(const void * s1,const void * s2,ZyanUSize n)249 ZYAN_INLINE int ZYAN_MEMCMP(const void* s1, const void* s2, ZyanUSize n)
250 {
251 const ZyanU8* p1 = s1, *p2 = s2;
252 while (n--)
253 {
254 if (*p1 != *p2)
255 {
256 return *p1 - *p2;
257 }
258 p1++, p2++;
259 }
260 return 0;
261 }
262
ZYAN_MEMCPY(void * dst,const void * src,ZyanUSize n)263 ZYAN_INLINE void* ZYAN_MEMCPY(void* dst, const void* src, ZyanUSize n)
264 {
265 volatile ZyanU8* dp = dst;
266 const ZyanU8* sp = src;
267 while (n--)
268 {
269 *dp++ = *sp++;
270 }
271 return dst;
272 }
273
ZYAN_MEMMOVE(void * dst,const void * src,ZyanUSize n)274 ZYAN_INLINE void* ZYAN_MEMMOVE(void* dst, const void* src, ZyanUSize n)
275 {
276 volatile ZyanU8* pd = dst;
277 const ZyanU8* ps = src;
278 if (ps < pd)
279 {
280 for (pd += n, ps += n; n--;)
281 {
282 *--pd = *--ps;
283 }
284 } else
285 {
286 while (n--)
287 {
288 *pd++ = *ps++;
289 }
290 }
291 return dst;
292 }
293
ZYAN_MEMSET(void * dst,int val,ZyanUSize n)294 ZYAN_INLINE void* ZYAN_MEMSET(void* dst, int val, ZyanUSize n)
295 {
296 volatile ZyanU8* p = dst;
297 while (n--)
298 {
299 *p++ = (unsigned char)val;
300 }
301 return dst;
302 }
303
ZYAN_STRCAT(char * dest,const char * src)304 ZYAN_INLINE char* ZYAN_STRCAT(char* dest, const char* src)
305 {
306 char* ret = dest;
307 while (*dest)
308 {
309 dest++;
310 }
311 while ((*dest++ = *src++));
312 return ret;
313 }
314
ZYAN_STRCHR(const char * s,int c)315 ZYAN_INLINE char* ZYAN_STRCHR(const char* s, int c)
316 {
317 while (*s != (char)c)
318 {
319 if (!*s++)
320 {
321 return 0;
322 }
323 }
324 return (char*)s;
325 }
326
ZYAN_STRCMP(const char * s1,const char * s2)327 ZYAN_INLINE int ZYAN_STRCMP(const char* s1, const char* s2)
328 {
329 while (*s1 && (*s1 == *s2))
330 {
331 s1++, s2++;
332 }
333 return *(const ZyanU8*)s1 - *(const ZyanU8*)s2;
334 }
335
ZYAN_STRCOLL(const char * s1,const char * s2)336 ZYAN_INLINE int ZYAN_STRCOLL(const char *s1, const char *s2)
337 {
338 // TODO: Implement
339
340 ZYAN_UNUSED(s1);
341 ZYAN_UNUSED(s2);
342
343 return 0;
344 }
345
ZYAN_STRCPY(char * dest,const char * src)346 ZYAN_INLINE char* ZYAN_STRCPY(char* dest, const char* src)
347 {
348 char* ret = dest;
349 while ((*dest++ = *src++));
350 return ret;
351 }
352
ZYAN_STRCSPN(const char * s1,const char * s2)353 ZYAN_INLINE ZyanUSize ZYAN_STRCSPN(const char *s1, const char *s2)
354 {
355 ZyanUSize ret = 0;
356 while (*s1)
357 {
358 if (ZYAN_STRCHR(s2, *s1))
359 {
360 return ret;
361 }
362 s1++, ret++;
363 }
364 return ret;
365 }
366
ZYAN_STRLEN(const char * str)367 ZYAN_INLINE ZyanUSize ZYAN_STRLEN(const char* str)
368 {
369 const char* p = str;
370 while (*str)
371 {
372 ++str;
373 }
374 return str - p;
375 }
376
ZYAN_STRNCAT(char * dest,const char * src,ZyanUSize n)377 ZYAN_INLINE char* ZYAN_STRNCAT(char* dest, const char* src, ZyanUSize n)
378 {
379 char* ret = dest;
380 while (*dest)
381 {
382 dest++;
383 }
384 while (n--)
385 {
386 if (!(*dest++ = *src++))
387 {
388 return ret;
389 }
390 }
391 *dest = 0;
392 return ret;
393 }
394
ZYAN_STRNCMP(const char * s1,const char * s2,ZyanUSize n)395 ZYAN_INLINE int ZYAN_STRNCMP(const char* s1, const char* s2, ZyanUSize n)
396 {
397 while (n--)
398 {
399 if (*s1++ != *s2++)
400 {
401 return *(unsigned char*)(s1 - 1) - *(unsigned char*)(s2 - 1);
402 }
403 }
404 return 0;
405 }
406
ZYAN_STRNCPY(char * dest,const char * src,ZyanUSize n)407 ZYAN_INLINE char* ZYAN_STRNCPY(char* dest, const char* src, ZyanUSize n)
408 {
409 char* ret = dest;
410 do
411 {
412 if (!n--)
413 {
414 return ret;
415 }
416 } while ((*dest++ = *src++));
417 while (n--)
418 {
419 *dest++ = 0;
420 }
421 return ret;
422 }
423
ZYAN_STRPBRK(const char * s1,const char * s2)424 ZYAN_INLINE char* ZYAN_STRPBRK(const char* s1, const char* s2)
425 {
426 while (*s1)
427 {
428 if(ZYAN_STRCHR(s2, *s1++))
429 {
430 return (char*)--s1;
431 }
432 }
433 return 0;
434 }
435
ZYAN_STRRCHR(const char * s,int c)436 ZYAN_INLINE char* ZYAN_STRRCHR(const char* s, int c)
437 {
438 char* ret = 0;
439 do
440 {
441 if (*s == (char)c)
442 {
443 ret = (char*)s;
444 }
445 } while (*s++);
446 return ret;
447 }
448
ZYAN_STRSPN(const char * s1,const char * s2)449 ZYAN_INLINE ZyanUSize ZYAN_STRSPN(const char* s1, const char* s2)
450 {
451 ZyanUSize ret = 0;
452 while (*s1 && ZYAN_STRCHR(s2, *s1++))
453 {
454 ret++;
455 }
456 return ret;
457 }
458
ZYAN_STRSTR(const char * s1,const char * s2)459 ZYAN_INLINE char* ZYAN_STRSTR(const char* s1, const char* s2)
460 {
461 const ZyanUSize n = ZYAN_STRLEN(s2);
462 while (*s1)
463 {
464 if (!ZYAN_MEMCMP(s1++, s2, n))
465 {
466 return (char*)(s1 - 1);
467 }
468 }
469 return 0;
470 }
471
ZYAN_STRTOK(char * str,const char * delim)472 ZYAN_INLINE char* ZYAN_STRTOK(char* str, const char* delim)
473 {
474 static char* p = 0;
475 if (str)
476 {
477 p = str;
478 } else
479 if (!p)
480 {
481 return 0;
482 }
483 str = p + ZYAN_STRSPN(p, delim);
484 p = str + ZYAN_STRCSPN(str, delim);
485 if (p == str)
486 {
487 return p = 0;
488 }
489 p = *p ? *p = 0, p + 1 : 0;
490 return str;
491 }
492
ZYAN_STRXFRM(char * dest,const char * src,ZyanUSize n)493 ZYAN_INLINE ZyanUSize ZYAN_STRXFRM(char* dest, const char* src, ZyanUSize n)
494 {
495 const ZyanUSize n2 = ZYAN_STRLEN(src);
496 if (n > n2)
497 {
498 ZYAN_STRCPY(dest, src);
499 }
500 return n2;
501 }
502
503 /* ---------------------------------------------------------------------------------------------- */
504
505 #endif
506
507 #endif
508
509 /* ============================================================================================== */
510
511 #endif /* ZYCORE_LIBC_H */
512