| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- /*
- * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
- * License: http://www.opensource.org/licenses/BSD-2-Clause
- */
- #ifndef BX_PRINTF_H_HEADER_GUARD
- #define BX_PRINTF_H_HEADER_GUARD
- #include "bx.h"
- #include <alloca.h>
- #include <ctype.h> // tolower
- #include <stdarg.h> // va_list
- #include <stdio.h> // vsnprintf, vsnwprintf
- #include <string.h>
- #include <wchar.h> // wchar_t
- namespace bx
- {
- ///
- inline bool toBool(const char* _str)
- {
- char ch = (char)tolower(_str[0]);
- return ch == 't' || ch == '1';
- }
- /// Case insensitive string compare.
- inline int32_t stricmp(const char* _a, const char* _b)
- {
- #if BX_COMPILER_MSVC
- return _stricmp(_a, _b);
- #else
- return strcasecmp(_a, _b);
- #endif // BX_COMPILER_
- }
- ///
- inline size_t strnlen(const char* _str, size_t _max)
- {
- const char* end = _str + _max;
- const char* ptr;
- for (ptr = _str; ptr < end && *ptr != '\0'; ++ptr) {};
- return ptr - _str;
- }
- /// Find substring in string. Limit search to _size.
- inline const char* strnstr(const char* _str, const char* _find, size_t _size)
- {
- char first = *_find;
- if ('\0' == first)
- {
- return _str;
- }
- const char* cmp = _find + 1;
- size_t len = strlen(cmp);
- do
- {
- for (char match = *_str++; match != first && 0 < _size; match = *_str++, --_size)
- {
- if ('\0' == match)
- {
- return NULL;
- }
- }
- if (0 == _size)
- {
- return NULL;
- }
- } while (0 != strncmp(_str, cmp, len) );
- return --_str;
- }
- /// Find new line. Returns pointer after new line terminator.
- inline const char* strnl(const char* _str)
- {
- for (; '\0' != *_str; _str += strnlen(_str, 1024) )
- {
- const char* eol = strnstr(_str, "\r\n", 1024);
- if (NULL != eol)
- {
- return eol + 2;
- }
- eol = strnstr(_str, "\n", 1024);
- if (NULL != eol)
- {
- return eol + 1;
- }
- }
- return _str;
- }
- /// Find end of line. Retuns pointer to new line terminator.
- inline const char* streol(const char* _str)
- {
- for (; '\0' != *_str; _str += strnlen(_str, 1024) )
- {
- const char* eol = strnstr(_str, "\r\n", 1024);
- if (NULL != eol)
- {
- return eol;
- }
- eol = strnstr(_str, "\n", 1024);
- if (NULL != eol)
- {
- return eol;
- }
- }
- return _str;
- }
- /// Skip whitespace.
- inline const char* strws(const char* _str)
- {
- for (; isspace(*_str); ++_str) {};
- return _str;
- }
- /// Skip non-whitespace.
- inline const char* strnws(const char* _str)
- {
- for (; !isspace(*_str); ++_str) {};
- return _str;
- }
- /// Skip word.
- inline const char* strword(const char* _str)
- {
- for (char ch = *_str++; isalnum(ch) || '_' == ch; ch = *_str++) {};
- return _str-1;
- }
- /// Find matching block.
- inline const char* strmb(const char* _str, char _open, char _close)
- {
- int count = 0;
- for (char ch = *_str++; ch != '\0' && count >= 0; ch = *_str++)
- {
- if (ch == _open)
- {
- count++;
- }
- else if (ch == _close)
- {
- count--;
- if (0 == count)
- {
- return _str-1;
- }
- }
- }
- return NULL;
- }
- // Normalize string to sane line endings.
- inline void eolLF(char* _out, size_t _size, const char* _str)
- {
- if (0 < _size)
- {
- char* end = _out + _size - 1;
- for (char ch = *_str++; ch != '\0' && _out < end; ch = *_str++)
- {
- if ('\r' != ch)
- {
- *_out++ = ch;
- }
- }
- *_out = '\0';
- }
- }
- // Finds identifier.
- inline const char* findIdentifierMatch(const char* _str, const char* _word)
- {
- size_t len = strlen(_word);
- const char* ptr = strstr(_str, _word);
- for (; NULL != ptr; ptr = strstr(ptr + len, _word) )
- {
- if (ptr != _str)
- {
- char ch = *(ptr - 1);
- if (isalnum(ch) || '_' == ch)
- {
- continue;
- }
- }
- char ch = ptr[len];
- if (isalnum(ch) || '_' == ch)
- {
- continue;
- }
- return ptr;
- }
- return ptr;
- }
- // Finds any identifier from NULL terminated array of identifiers.
- inline const char* findIdentifierMatch(const char* _str, const char* _words[])
- {
- for (const char* word = *_words; NULL != word; ++_words, word = *_words)
- {
- const char* match = findIdentifierMatch(_str, word);
- if (NULL != match)
- {
- return match;
- }
- }
- return NULL;
- }
- /// Cross platform implementation of vsnprintf that returns number of
- /// characters which would have been written to the final string if
- /// enough space had been available.
- inline int32_t vsnprintf(char* _str, size_t _count, const char* _format, va_list _argList)
- {
- #if BX_COMPILER_MSVC
- int32_t len = ::vsnprintf_s(_str, _count, size_t(-1), _format, _argList);
- return -1 == len ? ::_vscprintf(_format, _argList) : len;
- #else
- return ::vsnprintf(_str, _count, _format, _argList);
- #endif // BX_COMPILER_MSVC
- }
- /// Cross platform implementation of vsnwprintf that returns number of
- /// characters which would have been written to the final string if
- /// enough space had been available.
- inline int32_t vsnwprintf(wchar_t* _str, size_t _count, const wchar_t* _format, va_list _argList)
- {
- #if BX_COMPILER_MSVC
- int32_t len = ::_vsnwprintf_s(_str, _count, size_t(-1), _format, _argList);
- return -1 == len ? ::_vscwprintf(_format, _argList) : len;
- #elif defined(__MINGW32__)
- return ::vsnwprintf(_str, _count, _format, _argList);
- #else
- return ::vswprintf(_str, _count, _format, _argList);
- #endif // BX_COMPILER_MSVC
- }
- ///
- inline int32_t snprintf(char* _str, size_t _count, const char* _format, ...) // BX_PRINTF_ARGS(3, 4)
- {
- va_list argList;
- va_start(argList, _format);
- int32_t len = vsnprintf(_str, _count, _format, argList);
- va_end(argList);
- return len;
- }
- ///
- inline int32_t swnprintf(wchar_t* _out, size_t _count, const wchar_t* _format, ...)
- {
- va_list argList;
- va_start(argList, _format);
- int32_t len = vsnwprintf(_out, _count, _format, argList);
- va_end(argList);
- return len;
- }
- ///
- template <typename Ty>
- inline void stringPrintfVargs(Ty& _out, const char* _format, va_list _argList)
- {
- char temp[2048];
- char* out = temp;
- int32_t len = bx::vsnprintf(out, sizeof(temp), _format, _argList);
- if ( (int32_t)sizeof(temp) < len)
- {
- out = (char*)alloca(len+1);
- len = bx::vsnprintf(out, len, _format, _argList);
- }
- out[len] = '\0';
- _out.append(out);
- }
- ///
- template <typename Ty>
- inline void stringPrintf(Ty& _out, const char* _format, ...)
- {
- va_list argList;
- va_start(argList, _format);
- stringPrintfVargs(_out, _format, argList);
- va_end(argList);
- }
- /// Extract base file name from file path.
- inline const char* baseName(const char* _filePath)
- {
- const char* bs = strrchr(_filePath, '\\');
- const char* fs = strrchr(_filePath, '/');
- const char* slash = (bs > fs ? bs : fs);
- const char* colon = strrchr(_filePath, ':');
- const char* basename = slash > colon ? slash : colon;
- if (NULL != basename)
- {
- return basename+1;
- }
- return _filePath;
- }
- /*
- * Copyright (c) 1998 Todd C. Miller <[email protected]>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- /// Copy src to string dst of size siz. At most siz-1 characters
- /// will be copied. Always NUL terminates (unless siz == 0).
- /// Returns strlen(src); if retval >= siz, truncation occurred.
- inline size_t strlcpy(char* _dst, const char* _src, size_t _siz)
- {
- char* dd = _dst;
- const char* ss = _src;
- size_t nn = _siz;
- /* Copy as many bytes as will fit */
- if (nn != 0)
- {
- while (--nn != 0)
- {
- if ( (*dd++ = *ss++) == '\0')
- {
- break;
- }
- }
- }
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (nn == 0)
- {
- if (_siz != 0)
- {
- *dd = '\0'; /* NUL-terminate dst */
- }
- while (*ss++)
- {
- }
- }
- return(ss - _src - 1); /* count does not include NUL */
- }
- /// Appends src to string dst of size siz (unlike strncat, siz is the
- /// full size of dst, not space left). At most siz-1 characters
- /// will be copied. Always NUL terminates (unless siz <= strlen(dst)).
- /// Returns strlen(src) + MIN(siz, strlen(initial dst)).
- /// If retval >= siz, truncation occurred.
- inline size_t strlcat(char* _dst, const char* _src, size_t _siz)
- {
- char* dd = _dst;
- const char *s = _src;
- size_t nn = _siz;
- size_t dlen;
- /* Find the end of dst and adjust bytes left but don't go past end */
- while (nn-- != 0 && *dd != '\0')
- {
- dd++;
- }
- dlen = dd - _dst;
- nn = _siz - dlen;
- if (nn == 0)
- {
- return(dlen + strlen(s));
- }
- while (*s != '\0')
- {
- if (nn != 1)
- {
- *dd++ = *s;
- nn--;
- }
- s++;
- }
- *dd = '\0';
- return(dlen + (s - _src)); /* count does not include NUL */
- }
- } // namespace bx
- #endif // BX_PRINTF_H_HEADER_GUARD
|