nuclear@0: /* nuclear@0: Open Asset Import Library (assimp) nuclear@0: ---------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the nuclear@0: following conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: nuclear@0: ---------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: /** @file Definition of platform independent string workers: nuclear@0: nuclear@0: ASSIMP_itoa10 nuclear@0: ASSIMP_stricmp nuclear@0: ASSIMP_strincmp nuclear@0: nuclear@0: These functions are not consistently available on all platforms, nuclear@0: or the provided implementations behave too differently. nuclear@0: */ nuclear@0: #ifndef INCLUDED_AI_STRING_WORKERS_H nuclear@0: #define INCLUDED_AI_STRING_WORKERS_H nuclear@0: nuclear@0: #include "assimp/ai_assert.h" nuclear@0: nuclear@0: namespace Assimp { nuclear@0: nuclear@0: // ------------------------------------------------------------------------------- nuclear@0: /** @brief itoa with a fixed base 10 nuclear@0: * 'itoa' is not consistently available on all platforms so it is quite useful nuclear@0: * to have a small replacement function here. No need to use a full sprintf() nuclear@0: * if we just want to print a number ... nuclear@0: * @param out Output buffer nuclear@0: * @param max Maximum number of characters to be written, including '\0'. nuclear@0: * This parameter may not be 0. nuclear@0: * @param number Number to be written nuclear@0: * @return Length of the output string, excluding the '\0' nuclear@0: */ nuclear@0: inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) nuclear@0: { nuclear@0: ai_assert(NULL != out); nuclear@0: nuclear@0: // write the unary minus to indicate we have a negative number nuclear@0: unsigned int written = 1u; nuclear@0: if (number < 0 && written < max) { nuclear@0: *out++ = '-'; nuclear@0: ++written; nuclear@0: number = -number; nuclear@0: } nuclear@0: nuclear@0: // We begin with the largest number that is not zero. nuclear@0: int32_t cur = 1000000000; // 2147483648 nuclear@0: bool mustPrint = false; nuclear@0: while (written < max) { nuclear@0: nuclear@0: const unsigned int digit = number / cur; nuclear@0: if (mustPrint || digit > 0 || 1 == cur) { nuclear@0: // print all future zeroes from now nuclear@0: mustPrint = true; nuclear@0: nuclear@0: *out++ = '0'+static_cast(digit); nuclear@0: nuclear@0: ++written; nuclear@0: number -= digit*cur; nuclear@0: if (1 == cur) { nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: cur /= 10; nuclear@0: } nuclear@0: nuclear@0: // append a terminal zero nuclear@0: *out++ = '\0'; nuclear@0: return written-1; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------- nuclear@0: /** @brief itoa with a fixed base 10 (Secure template overload) nuclear@0: * The compiler should choose this function if he or she is able to determine the nuclear@0: * size of the array automatically. nuclear@0: */ nuclear@0: template nuclear@0: inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) nuclear@0: { nuclear@0: return ASSIMP_itoa10(out,length,number); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------- nuclear@0: /** @brief Helper function to do platform independent string comparison. nuclear@0: * nuclear@0: * This is required since stricmp() is not consistently available on nuclear@0: * all platforms. Some platforms use the '_' prefix, others don't even nuclear@0: * have such a function. nuclear@0: * nuclear@0: * @param s1 First input string nuclear@0: * @param s2 Second input string nuclear@0: * @return 0 if the given strings are identical nuclear@0: */ nuclear@0: inline int ASSIMP_stricmp(const char *s1, const char *s2) nuclear@0: { nuclear@0: ai_assert(NULL != s1 && NULL != s2); nuclear@0: nuclear@0: #if (defined _MSC_VER) nuclear@0: nuclear@0: return ::_stricmp(s1,s2); nuclear@0: #elif defined( __GNUC__ ) nuclear@0: nuclear@0: return ::strcasecmp(s1,s2); nuclear@0: #else nuclear@0: nuclear@0: register char c1, c2; nuclear@0: do { nuclear@0: c1 = tolower(*s1++); nuclear@0: c2 = tolower(*s2++); nuclear@0: } nuclear@0: while ( c1 && (c1 == c2) ); nuclear@0: return c1 - c2; nuclear@0: #endif nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------- nuclear@0: /** @brief Case independent comparison of two std::strings nuclear@0: * nuclear@0: * @param a First string nuclear@0: * @param b Second string nuclear@0: * @return 0 if a == b nuclear@0: */ nuclear@0: inline int ASSIMP_stricmp(const std::string& a, const std::string& b) nuclear@0: { nuclear@0: register int i = (int)b.length()-(int)a.length(); nuclear@0: return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str())); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------- nuclear@0: /** @brief Helper function to do platform independent string comparison. nuclear@0: * nuclear@0: * This is required since strincmp() is not consistently available on nuclear@0: * all platforms. Some platforms use the '_' prefix, others don't even nuclear@0: * have such a function. nuclear@0: * nuclear@0: * @param s1 First input string nuclear@0: * @param s2 Second input string nuclear@0: * @param n Macimum number of characters to compare nuclear@0: * @return 0 if the given strings are identical nuclear@0: */ nuclear@0: inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) nuclear@0: { nuclear@0: ai_assert(NULL != s1 && NULL != s2); nuclear@0: if (!n)return 0; nuclear@0: nuclear@0: #if (defined _MSC_VER) nuclear@0: nuclear@0: return ::_strnicmp(s1,s2,n); nuclear@0: nuclear@0: #elif defined( __GNUC__ ) nuclear@0: nuclear@0: return ::strncasecmp(s1,s2, n); nuclear@0: nuclear@0: #else nuclear@0: register char c1, c2; nuclear@0: unsigned int p = 0; nuclear@0: do nuclear@0: { nuclear@0: if (p++ >= n)return 0; nuclear@0: c1 = tolower(*s1++); nuclear@0: c2 = tolower(*s2++); nuclear@0: } nuclear@0: while ( c1 && (c1 == c2) ); nuclear@0: nuclear@0: return c1 - c2; nuclear@0: #endif nuclear@0: } nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------------------- nuclear@0: /** @brief Evaluates an integer power nuclear@0: * nuclear@0: * todo: move somewhere where it fits better in than here nuclear@0: */ nuclear@0: inline unsigned int integer_pow (unsigned int base, unsigned int power) nuclear@0: { nuclear@0: unsigned int res = 1; nuclear@0: for (unsigned int i = 0; i < power;++i) nuclear@0: res *= base; nuclear@0: nuclear@0: return res; nuclear@0: } nuclear@0: } // end of namespace nuclear@0: nuclear@0: #endif // ! AI_STRINGCOMPARISON_H_INC