ovr_sdk

view LibOVR/Src/Kernel/OVR_Std.h @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children
line source
1 /************************************************************************************
3 PublicHeader: OVR_Kernel.h
4 Filename : OVR_Std.h
5 Content : Standard C function interface
6 Created : September 19, 2012
7 Notes :
9 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
11 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
12 you may not use the Oculus VR Rift SDK except in compliance with the License,
13 which is provided at the time of installation or download, or which
14 otherwise accompanies this software in either electronic or hard copy form.
16 You may obtain a copy of the License at
18 http://www.oculusvr.com/licenses/LICENSE-3.2
20 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
21 distributed under the License is distributed on an "AS IS" BASIS,
22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 See the License for the specific language governing permissions and
24 limitations under the License.
26 ************************************************************************************/
28 #ifndef OVR_Std_h
29 #define OVR_Std_h
31 #include "OVR_Types.h"
32 #include <stdarg.h> // for va_list args
33 #include <string.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <ctype.h>
38 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
39 #define OVR_MSVC_SAFESTRING
40 #include <errno.h>
41 #endif
43 // Wide-char funcs
44 #include <wchar.h>
45 #include <wctype.h>
47 namespace OVR {
49 // Has the same behavior as itoa aside from also having a dest size argument.
50 // Return value: Pointer to the resulting null-terminated string, same as parameter str.
51 #if defined(OVR_OS_MS)
52 inline char* OVR_CDECL OVR_itoa(int val, char *dest, size_t destsize, int radix)
53 {
54 #if defined(OVR_MSVC_SAFESTRING)
55 _itoa_s(val, dest, destsize, radix);
56 return dest;
57 #else
58 OVR_UNUSED(destsize);
59 return itoa(val, dest, radix);
60 #endif
61 }
62 #else // OVR_OS_MS
63 inline char* OVR_itoa(int val, char* dest, size_t len, int radix)
64 {
65 if (val == 0)
66 {
67 if (len > 1)
68 {
69 dest[0] = '0';
70 dest[1] = '\0';
71 }
72 else if(len > 0)
73 dest[0] = '\0';
74 return dest;
75 }
77 // FIXME: Fix the following code to avoid memory write overruns when len is in sufficient.
78 int cur = val;
79 size_t i = 0;
80 size_t sign = 0;
82 if (val < 0)
83 {
84 val = -val;
85 sign = 1;
86 }
88 while ((val != 0) && (i < (len - 1 - sign)))
89 {
90 cur = val % radix;
91 val /= radix;
93 if (radix == 16)
94 {
95 switch(cur)
96 {
97 case 10:
98 dest[i] = 'a';
99 break;
100 case 11:
101 dest[i] = 'b';
102 break;
103 case 12:
104 dest[i] = 'c';
105 break;
106 case 13:
107 dest[i] = 'd';
108 break;
109 case 14:
110 dest[i] = 'e';
111 break;
112 case 15:
113 dest[i] = 'f';
114 break;
115 default:
116 dest[i] = (char)('0' + cur);
117 break;
118 }
119 }
120 else
121 {
122 dest[i] = (char)('0' + cur);
123 }
124 ++i;
125 }
127 if (sign)
128 {
129 dest[i++] = '-';
130 }
132 for (size_t j = 0; j < i / 2; ++j)
133 {
134 char tmp = dest[j];
135 dest[j] = dest[i - 1 - j];
136 dest[i - 1 - j] = tmp;
137 }
138 dest[i] = '\0';
140 return dest;
141 }
143 #endif
146 // String functions
148 inline size_t OVR_CDECL OVR_strlen(const char* str)
149 {
150 return strlen(str);
151 }
153 inline char* OVR_CDECL OVR_strcpy(char* dest, size_t destsize, const char* src)
154 {
155 #if defined(OVR_MSVC_SAFESTRING)
156 strcpy_s(dest, destsize, src);
157 return dest;
158 #else
159 // FIXME: This should be a safer implementation
160 OVR_UNUSED(destsize);
161 return strcpy(dest, src);
162 #endif
163 }
166 // Acts the same as the strlcpy function.
167 // Copies src to dest, 0-terminating even if it involves truncating the write.
168 // Returns the required strlen of dest (which is one less than the required size of dest).
169 // strlcpy is a safer alternative to strcpy and strncpy and provides size information.
170 // However, it still may result in an incomplete copy.
171 //
172 // Example usage:
173 // char buffer[256];
174 // if(OVR_strlcpy(buffer, "hello world", sizeof(buffer)) < sizeof(buffer))
175 // { there was enough space }
176 // else
177 // { need a larger buffer }
178 //
179 size_t OVR_CDECL OVR_strlcpy(char* dest, const char* src, size_t destsize);
181 // Acts the same as the strlcat function.
182 // Appends src to dest, 0-terminating even if it involves an incomplete write.
183 // Doesn't 0-terminate in the case that destsize is 0.
184 // Returns the required strlen of dest (which is one less than the required size of dest).
185 // The terminating 0 char of dest is overwritten by the first
186 // character of src, and a new 0 char is appended to dest. The required capacity
187 // of the destination is (strlen(src) + strlen(dest) + 1).
188 // strlcat is a safer alternative to strcat and provides size information.
189 // However, it still may result in an incomplete copy.
190 //
191 // Example usage:
192 // char buffer[256] = "hello ";
193 // if(OVR_strlcat(buffer, "world", sizeof(buffer)) < sizeof(buffer))
194 // { there was enough space }
195 // else
196 // { need a larger buffer }
197 //
198 size_t OVR_CDECL OVR_strlcat(char* dest, const char* src, size_t destsize);
201 inline char* OVR_CDECL OVR_strncpy(char* dest, size_t destsize, const char* src, size_t count)
202 {
203 #if defined(OVR_MSVC_SAFESTRING)
204 strncpy_s(dest, destsize, src, count);
205 return dest;
206 #else
207 // FIXME: This should be a safer implementation
208 OVR_UNUSED(destsize);
209 return strncpy(dest, src, count);
210 #endif
211 }
213 inline char * OVR_CDECL OVR_strcat(char* dest, size_t destsize, const char* src)
214 {
215 #if defined(OVR_MSVC_SAFESTRING)
216 strcat_s(dest, destsize, src);
217 return dest;
218 #else
219 // FIXME: This should be a safer implementation
220 OVR_UNUSED(destsize);
221 return strcat(dest, src);
222 #endif
223 }
225 inline int OVR_CDECL OVR_strcmp(const char* dest, const char* src)
226 {
227 return strcmp(dest, src);
228 }
230 inline const char* OVR_CDECL OVR_strchr(const char* str, char c)
231 {
232 return strchr(str, c);
233 }
235 inline char* OVR_CDECL OVR_strchr(char* str, char c)
236 {
237 return strchr(str, c);
238 }
240 inline const char* OVR_strrchr(const char* str, char c)
241 {
242 size_t len = OVR_strlen(str);
243 for (size_t i=len; i>0; i--)
244 if (str[i]==c)
245 return str+i;
246 return 0;
247 }
249 inline const uint8_t* OVR_CDECL OVR_memrchr(const uint8_t* str, size_t size, uint8_t c)
250 {
251 for (intptr_t i = (intptr_t)size - 1; i >= 0; i--)
252 {
253 if (str[i] == c)
254 return str + i;
255 }
256 return 0;
257 }
259 inline char* OVR_CDECL OVR_strrchr(char* str, char c)
260 {
261 size_t len = OVR_strlen(str);
262 for (size_t i=len; i>0; i--)
263 if (str[i]==c)
264 return str+i;
265 return 0;
266 }
269 double OVR_CDECL OVR_strtod(const char* string, char** tailptr);
271 inline long OVR_CDECL OVR_strtol(const char* string, char** tailptr, int radix)
272 {
273 return strtol(string, tailptr, radix);
274 }
276 inline long OVR_CDECL OVR_strtoul(const char* string, char** tailptr, int radix)
277 {
278 return strtoul(string, tailptr, radix);
279 }
281 inline int OVR_CDECL OVR_strncmp(const char* ws1, const char* ws2, size_t size)
282 {
283 return strncmp(ws1, ws2, size);
284 }
286 inline uint64_t OVR_CDECL OVR_strtouq(const char *nptr, char **endptr, int base)
287 {
288 #if defined(OVR_CC_MSVC)
289 return _strtoui64(nptr, endptr, base);
290 #else
291 return strtoull(nptr, endptr, base);
292 #endif
293 }
295 inline int64_t OVR_CDECL OVR_strtoq(const char *nptr, char **endptr, int base)
296 {
297 #if defined(OVR_CC_MSVC)
298 return _strtoi64(nptr, endptr, base);
299 #else
300 return strtoll(nptr, endptr, base);
301 #endif
302 }
305 inline int64_t OVR_CDECL OVR_atoq(const char* string)
306 {
307 #if defined(OVR_CC_MSVC)
308 return _atoi64(string);
309 #else
310 return atoll(string);
311 #endif
312 }
314 inline uint64_t OVR_CDECL OVR_atouq(const char* string)
315 {
316 return OVR_strtouq(string, NULL, 10);
317 }
320 // Implemented in OVR_Std.cpp in platform-specific manner.
321 int OVR_CDECL OVR_stricmp(const char* dest, const char* src);
322 int OVR_CDECL OVR_strnicmp(const char* dest, const char* src, size_t count);
325 // This is like sprintf but with a destination buffer size argument. However, the behavior is different
326 // from vsnprintf in that the return value semantics are like sprintf (which returns -1 on capacity overflow) and
327 // not like snprintf (which returns intended strlen on capacity overflow).
328 inline size_t OVR_CDECL OVR_sprintf(char *dest, size_t destsize, const char* format, ...)
329 {
330 va_list argList;
331 va_start(argList,format);
332 size_t ret;
333 #if defined(OVR_CC_MSVC)
334 #if defined(OVR_MSVC_SAFESTRING)
335 ret = _vsnprintf_s(dest, destsize, _TRUNCATE, format, argList);
336 OVR_ASSERT(ret != -1);
337 #else
338 OVR_UNUSED(destsize);
339 ret = _vsnprintf(dest, destsize - 1, format, argList); // -1 for space for the null character
340 OVR_ASSERT(ret != -1);
341 dest[destsize-1] = 0;
342 #endif
343 #else
344 OVR_UNUSED(destsize);
345 ret = vsprintf(dest, format, argList);
346 OVR_ASSERT(ret < destsize);
347 #endif
348 va_end(argList);
349 return ret;
350 }
353 // This is like vsprintf but with a destination buffer size argument. However, the behavior is different
354 // from vsnprintf in that the return value semantics are like vsprintf (which returns -1 on capacity overflow) and
355 // not like vsnprintf (which returns intended strlen on capacity overflow).
356 // Return value:
357 // On success, the total number of characters written is returned.
358 // On failure, a negative number is returned.
359 inline size_t OVR_CDECL OVR_vsprintf(char *dest, size_t destsize, const char * format, va_list argList)
360 {
361 size_t ret;
362 #if defined(OVR_CC_MSVC)
363 #if defined(OVR_MSVC_SAFESTRING)
364 dest[0] = '\0';
365 int rv = vsnprintf_s(dest, destsize, _TRUNCATE, format, argList);
366 if (rv == -1)
367 {
368 dest[destsize - 1] = '\0';
369 ret = destsize - 1;
370 }
371 else
372 ret = (size_t)rv;
373 #else
374 OVR_UNUSED(destsize);
375 int rv = _vsnprintf(dest, destsize - 1, format, argList);
376 OVR_ASSERT(rv != -1);
377 ret = (size_t)rv;
378 dest[destsize-1] = 0;
379 #endif
380 #else
381 // FIXME: This should be a safer implementation
382 OVR_UNUSED(destsize);
383 ret = (size_t)vsprintf(dest, format, argList);
384 OVR_ASSERT(ret < destsize);
385 #endif
386 return ret;
387 }
389 // Same behavior as ISO C99 vsnprintf.
390 // Returns the strlen of the resulting formatted string, or a negative value if the format is invalid.
391 // destsize specifies the capacity of the input buffer.
392 //
393 // Example usage:
394 // void Log(char *dest, size_t destsize, const char * format, ...)
395 // {
396 // char buffer[1024];
397 // va_list argList;
398 // va_start(argList,format);
399 // int result = OVR_vsnprintf(dest, destsize, format, argList);
400 // assert(result < destsize); // Else we'd have to retry with a dynamically allocated buffer (of size=result+1) and new argList copy.
401 // va_end(argList);
402 // }
404 inline int OVR_CDECL OVR_vsnprintf(char *dest, size_t destsize, const char * format, va_list argList)
405 {
406 int ret;
407 #if defined(OVR_CC_MSVC)
408 OVR_DISABLE_MSVC_WARNING(4996) // 'vsnprintf': This function or variable may be unsafe.
409 ret = vsnprintf(dest, destsize, format, argList); // Microsoft vsnprintf is non-conforming; it returns -1 if destsize is insufficient.
410 if (ret < 0) // If there was a format error or if destsize was insufficient...
411 {
412 ret = _vscprintf(format, argList); // Get the expected dest strlen. If the return value is still -1 then there was a format error.
414 if (destsize) // If we can 0-terminate the output...
415 {
416 if (ret < 0)
417 dest[0] = 0;
418 else
419 dest[destsize-1] = 0;
420 }
421 }
422 // Else the string was written OK and ret is its strlen.
423 OVR_RESTORE_MSVC_WARNING()
424 #else
425 ret = vsnprintf(dest, destsize, format, argList);
426 #endif
427 return ret;
428 }
431 // Same behavior as ISO C99 snprintf.
432 // Returns the strlen of the resulting formatted string, or a negative value if the format is invalid.
433 // destsize specifies the capacity of the input buffer.
434 //
435 // Example usage:
436 // char buffer[16];
437 // int result = OVR_snprintf(buffer, sizeof(buffer), "%d", 37);
438 // if (result >= sizeof(buffer)) // If there was insufficient capacity...
439 // {
440 // char* p = new char[result + 1]; // Or char* p = (char*)OVR_ALLOC(result + 1);
441 // OVR_snprintf(p, (size_t)result, "%d", 37);
442 // delete[] p;
443 // }
444 //
445 inline int OVR_CDECL OVR_snprintf(char *dest, size_t destsize, const char * format, ...)
446 {
447 va_list argList;
448 va_start(argList,format);
449 int ret = OVR_vsnprintf(dest, destsize, format, argList);
450 va_end(argList);
451 return ret;
452 }
455 // Returns the strlen of the resulting formatted string, or a negative value if the format is invalid.
456 // Note: If you are planning on printing a string then it's more efficient to just use OVR_vsnprintf and
457 // look at the return value and handle the uncommon case that there wasn't enough space.
458 inline int OVR_CDECL OVR_vscprintf(const char * format, va_list argList)
459 {
460 int ret;
461 #if defined(OVR_CC_MSVC)
462 ret = _vscprintf(format, argList);
463 #else
464 ret = vsnprintf(NULL, 0, format, argList);
465 #endif
466 return ret;
467 }
470 wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, size_t destsize, const wchar_t* src);
471 wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, size_t destsize, const wchar_t* src, size_t count);
472 wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, size_t destsize, const wchar_t* src);
473 size_t OVR_CDECL OVR_wcslen(const wchar_t* str);
474 int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b);
475 int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b);
477 inline int OVR_CDECL OVR_wcsicoll(const wchar_t* a, const wchar_t* b)
478 {
479 #if defined(OVR_OS_MS)
480 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
481 return ::_wcsicoll(a, b);
482 #else
483 return ::wcsicoll(a, b);
484 #endif
485 #else
486 // not supported, use regular wcsicmp
487 return OVR_wcsicmp(a, b);
488 #endif
489 }
491 inline int OVR_CDECL OVR_wcscoll(const wchar_t* a, const wchar_t* b)
492 {
493 #if defined(OVR_OS_MS) || defined(OVR_OS_LINUX)
494 return wcscoll(a, b);
495 #else
496 // not supported, use regular wcscmp
497 return OVR_wcscmp(a, b);
498 #endif
499 }
501 #ifndef OVR_NO_WCTYPE
503 inline int OVR_CDECL UnicodeCharIs(const uint16_t* table, wchar_t charCode)
504 {
505 unsigned offset = table[charCode >> 8];
506 if (offset == 0) return 0;
507 if (offset == 1) return 1;
508 return (table[offset + ((charCode >> 4) & 15)] & (1 << (charCode & 15))) != 0;
509 }
511 extern const uint16_t UnicodeAlnumBits[];
512 extern const uint16_t UnicodeAlphaBits[];
513 extern const uint16_t UnicodeDigitBits[];
514 extern const uint16_t UnicodeSpaceBits[];
515 extern const uint16_t UnicodeXDigitBits[];
517 // Uncomment if necessary
518 //extern const uint16_t UnicodeCntrlBits[];
519 //extern const uint16_t UnicodeGraphBits[];
520 //extern const uint16_t UnicodeLowerBits[];
521 //extern const uint16_t UnicodePrintBits[];
522 //extern const uint16_t UnicodePunctBits[];
523 //extern const uint16_t UnicodeUpperBits[];
525 inline int OVR_CDECL OVR_iswalnum (wchar_t charCode) { return UnicodeCharIs(UnicodeAlnumBits, charCode); }
526 inline int OVR_CDECL OVR_iswalpha (wchar_t charCode) { return UnicodeCharIs(UnicodeAlphaBits, charCode); }
527 inline int OVR_CDECL OVR_iswdigit (wchar_t charCode) { return UnicodeCharIs(UnicodeDigitBits, charCode); }
528 inline int OVR_CDECL OVR_iswspace (wchar_t charCode) { return UnicodeCharIs(UnicodeSpaceBits, charCode); }
529 inline int OVR_CDECL OVR_iswxdigit(wchar_t charCode) { return UnicodeCharIs(UnicodeXDigitBits, charCode); }
531 // Uncomment if necessary
532 //inline int OVR_CDECL OVR_iswcntrl (wchar_t charCode) { return UnicodeCharIs(UnicodeCntrlBits, charCode); }
533 //inline int OVR_CDECL OVR_iswgraph (wchar_t charCode) { return UnicodeCharIs(UnicodeGraphBits, charCode); }
534 //inline int OVR_CDECL OVR_iswlower (wchar_t charCode) { return UnicodeCharIs(UnicodeLowerBits, charCode); }
535 //inline int OVR_CDECL OVR_iswprint (wchar_t charCode) { return UnicodeCharIs(UnicodePrintBits, charCode); }
536 //inline int OVR_CDECL OVR_iswpunct (wchar_t charCode) { return UnicodeCharIs(UnicodePunctBits, charCode); }
537 //inline int OVR_CDECL OVR_iswupper (wchar_t charCode) { return UnicodeCharIs(UnicodeUpperBits, charCode); }
539 int OVR_CDECL OVR_towupper(wchar_t charCode);
540 int OVR_CDECL OVR_towlower(wchar_t charCode);
542 #else // OVR_NO_WCTYPE
544 inline int OVR_CDECL OVR_iswspace(wchar_t c)
545 {
546 return iswspace(c);
547 }
549 inline int OVR_CDECL OVR_iswdigit(wchar_t c)
550 {
551 return iswdigit(c);
552 }
554 inline int OVR_CDECL OVR_iswxdigit(wchar_t c)
555 {
556 return iswxdigit(c);
557 }
559 inline int OVR_CDECL OVR_iswalpha(wchar_t c)
560 {
561 return iswalpha(c);
562 }
564 inline int OVR_CDECL OVR_iswalnum(wchar_t c)
565 {
566 return iswalnum(c);
567 }
569 inline wchar_t OVR_CDECL OVR_towlower(wchar_t c)
570 {
571 return (wchar_t)towlower(c);
572 }
574 inline wchar_t OVR_towupper(wchar_t c)
575 {
576 return (wchar_t)towupper(c);
577 }
579 #endif // OVR_NO_WCTYPE
581 // ASCII versions of tolower and toupper. Don't use "char"
582 inline int OVR_CDECL OVR_tolower(int c)
583 {
584 return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c;
585 }
587 inline int OVR_CDECL OVR_toupper(int c)
588 {
589 return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
590 }
594 inline double OVR_CDECL OVR_wcstod(const wchar_t* string, wchar_t** tailptr)
595 {
596 #if defined(OVR_OS_OTHER)
597 OVR_UNUSED(tailptr);
598 char buffer[64];
599 char* tp = NULL;
600 size_t max = OVR_wcslen(string);
601 if (max > 63) max = 63;
602 unsigned char c = 0;
603 for (size_t i=0; i < max; i++)
604 {
605 c = (unsigned char)string[i];
606 buffer[i] = ((c) < 128 ? (char)c : '!');
607 }
608 buffer[max] = 0;
609 return OVR_strtod(buffer, &tp);
610 #else
611 return wcstod(string, tailptr);
612 #endif
613 }
615 inline long OVR_CDECL OVR_wcstol(const wchar_t* string, wchar_t** tailptr, int radix)
616 {
617 #if defined(OVR_OS_OTHER)
618 OVR_UNUSED(tailptr);
619 char buffer[64];
620 char* tp = NULL;
621 size_t max = OVR_wcslen(string);
622 if (max > 63) max = 63;
623 unsigned char c = 0;
624 for (size_t i=0; i < max; i++)
625 {
626 c = (unsigned char)string[i];
627 buffer[i] = ((c) < 128 ? (char)c : '!');
628 }
629 buffer[max] = 0;
630 return strtol(buffer, &tp, radix);
631 #else
632 return wcstol(string, tailptr, radix);
633 #endif
634 }
636 } // OVR
638 #endif // OVR_Std_h