|
- /*
- ==============================================================================
-
- This file is part of the JUCE library - "Jules' Utility Class Extensions"
- Copyright 2004-10 by Raw Material Software Ltd.
-
- ------------------------------------------------------------------------------
-
- JUCE can be redistributed and/or modified under the terms of the GNU General
- Public License (Version 2), as published by the Free Software Foundation.
- A copy of the license is included in the JUCE distribution, or can be found
- online at www.gnu.org/licenses.
-
- JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- ------------------------------------------------------------------------------
-
- To release a closed-source product which uses JUCE, commercial licenses are
- available: visit www.rawmaterialsoftware.com/juce for more information.
-
- ==============================================================================
- */
-
- #include "../core/juce_StandardHeader.h"
-
- #if JUCE_MSVC
- #pragma warning (push)
- #pragma warning (disable: 4514 4996)
- #endif
-
- #include <cwctype>
- #include <cctype>
- #include <ctime>
-
- BEGIN_JUCE_NAMESPACE
-
- #include "juce_CharacterFunctions.h"
- #include "juce_String.h"
-
- //==============================================================================
- int CharacterFunctions::length (const char* const s) throw()
- {
- return (int) strlen (s);
- }
-
- int CharacterFunctions::length (const juce_wchar* const s) throw()
- {
- return (int) wcslen (s);
- }
-
- void CharacterFunctions::copy (char* dest, const char* src, const int maxChars) throw()
- {
- strncpy (dest, src, maxChars);
- }
-
- void CharacterFunctions::copy (juce_wchar* dest, const juce_wchar* src, int maxChars) throw()
- {
- wcsncpy (dest, src, maxChars);
- }
-
- void CharacterFunctions::copy (juce_wchar* dest, const char* src, const int maxChars) throw()
- {
- mbstowcs (dest, src, maxChars);
- }
-
- void CharacterFunctions::copy (char* dest, const juce_wchar* src, const int maxChars) throw()
- {
- wcstombs (dest, src, maxChars);
- }
-
- int CharacterFunctions::bytesRequiredForCopy (const juce_wchar* src) throw()
- {
- return (int) wcstombs (0, src, 0);
- }
-
- void CharacterFunctions::append (char* dest, const char* src) throw()
- {
- strcat (dest, src);
- }
-
- void CharacterFunctions::append (juce_wchar* dest, const juce_wchar* src) throw()
- {
- wcscat (dest, src);
- }
-
- int CharacterFunctions::compare (const char* const s1, const char* const s2) throw()
- {
- return strcmp (s1, s2);
- }
-
- int CharacterFunctions::compare (const juce_wchar* s1, const juce_wchar* s2) throw()
- {
- jassert (s1 != 0 && s2 != 0);
- return wcscmp (s1, s2);
- }
-
- int CharacterFunctions::compare (const char* const s1, const char* const s2, const int maxChars) throw()
- {
- jassert (s1 != 0 && s2 != 0);
- return strncmp (s1, s2, maxChars);
- }
-
- int CharacterFunctions::compare (const juce_wchar* s1, const juce_wchar* s2, int maxChars) throw()
- {
- jassert (s1 != 0 && s2 != 0);
- return wcsncmp (s1, s2, maxChars);
- }
-
- int CharacterFunctions::compare (const juce_wchar* s1, const char* s2) throw()
- {
- jassert (s1 != 0 && s2 != 0);
-
- for (;;)
- {
- const int diff = (int) (*s1 - (juce_wchar) (unsigned char) *s2);
-
- if (diff != 0)
- return diff;
- else if (*s1 == 0)
- break;
-
- ++s1;
- ++s2;
- }
-
- return 0;
- }
-
- int CharacterFunctions::compare (const char* s1, const juce_wchar* s2) throw()
- {
- return -compare (s2, s1);
- }
-
- int CharacterFunctions::compareIgnoreCase (const char* const s1, const char* const s2) throw()
- {
- jassert (s1 != 0 && s2 != 0);
-
- #if JUCE_WINDOWS
- return stricmp (s1, s2);
- #else
- return strcasecmp (s1, s2);
- #endif
- }
-
- int CharacterFunctions::compareIgnoreCase (const juce_wchar* s1, const juce_wchar* s2) throw()
- {
- jassert (s1 != 0 && s2 != 0);
-
- #if JUCE_WINDOWS
- return _wcsicmp (s1, s2);
- #else
- for (;;)
- {
- if (*s1 != *s2)
- {
- const int diff = toUpperCase (*s1) - toUpperCase (*s2);
-
- if (diff != 0)
- return diff < 0 ? -1 : 1;
- }
- else if (*s1 == 0)
- break;
-
- ++s1;
- ++s2;
- }
-
- return 0;
- #endif
- }
-
- int CharacterFunctions::compareIgnoreCase (const juce_wchar* s1, const char* s2) throw()
- {
- jassert (s1 != 0 && s2 != 0);
-
- for (;;)
- {
- if (*s1 != *s2)
- {
- const int diff = toUpperCase (*s1) - toUpperCase (*s2);
-
- if (diff != 0)
- return diff < 0 ? -1 : 1;
- }
- else if (*s1 == 0)
- break;
-
- ++s1;
- ++s2;
- }
-
- return 0;
- }
-
- int CharacterFunctions::compareIgnoreCase (const char* const s1, const char* const s2, const int maxChars) throw()
- {
- jassert (s1 != 0 && s2 != 0);
-
- #if JUCE_WINDOWS
- return strnicmp (s1, s2, maxChars);
- #else
- return strncasecmp (s1, s2, maxChars);
- #endif
- }
-
- int CharacterFunctions::compareIgnoreCase (const juce_wchar* s1, const juce_wchar* s2, int maxChars) throw()
- {
- jassert (s1 != 0 && s2 != 0);
-
- #if JUCE_WINDOWS
- return _wcsnicmp (s1, s2, maxChars);
- #else
- while (--maxChars >= 0)
- {
- if (*s1 != *s2)
- {
- const int diff = toUpperCase (*s1) - toUpperCase (*s2);
-
- if (diff != 0)
- return diff < 0 ? -1 : 1;
- }
- else if (*s1 == 0)
- break;
-
- ++s1;
- ++s2;
- }
-
- return 0;
- #endif
- }
-
- const char* CharacterFunctions::find (const char* const haystack, const char* const needle) throw()
- {
- return strstr (haystack, needle);
- }
-
- const juce_wchar* CharacterFunctions::find (const juce_wchar* haystack, const juce_wchar* const needle) throw()
- {
- return wcsstr (haystack, needle);
- }
-
- int CharacterFunctions::indexOfChar (const char* const haystack, const char needle, const bool ignoreCase) throw()
- {
- if (haystack != 0)
- {
- int i = 0;
-
- if (ignoreCase)
- {
- const char n1 = toLowerCase (needle);
- const char n2 = toUpperCase (needle);
-
- if (n1 != n2) // if the char is the same in upper/lower case, fall through to the normal search
- {
- while (haystack[i] != 0)
- {
- if (haystack[i] == n1 || haystack[i] == n2)
- return i;
-
- ++i;
- }
-
- return -1;
- }
-
- jassert (n1 == needle);
- }
-
- while (haystack[i] != 0)
- {
- if (haystack[i] == needle)
- return i;
-
- ++i;
- }
- }
-
- return -1;
- }
-
- int CharacterFunctions::indexOfChar (const juce_wchar* const haystack, const juce_wchar needle, const bool ignoreCase) throw()
- {
- if (haystack != 0)
- {
- int i = 0;
-
- if (ignoreCase)
- {
- const juce_wchar n1 = toLowerCase (needle);
- const juce_wchar n2 = toUpperCase (needle);
-
- if (n1 != n2) // if the char is the same in upper/lower case, fall through to the normal search
- {
- while (haystack[i] != 0)
- {
- if (haystack[i] == n1 || haystack[i] == n2)
- return i;
-
- ++i;
- }
-
- return -1;
- }
-
- jassert (n1 == needle);
- }
-
- while (haystack[i] != 0)
- {
- if (haystack[i] == needle)
- return i;
-
- ++i;
- }
- }
-
- return -1;
- }
-
- int CharacterFunctions::indexOfCharFast (const char* const haystack, const char needle) throw()
- {
- jassert (haystack != 0);
-
- int i = 0;
- while (haystack[i] != 0)
- {
- if (haystack[i] == needle)
- return i;
-
- ++i;
- }
-
- return -1;
- }
-
- int CharacterFunctions::indexOfCharFast (const juce_wchar* const haystack, const juce_wchar needle) throw()
- {
- jassert (haystack != 0);
-
- int i = 0;
- while (haystack[i] != 0)
- {
- if (haystack[i] == needle)
- return i;
-
- ++i;
- }
-
- return -1;
- }
-
- int CharacterFunctions::getIntialSectionContainingOnly (const char* const text, const char* const allowedChars) throw()
- {
- return allowedChars == 0 ? 0 : (int) strspn (text, allowedChars);
- }
-
- int CharacterFunctions::getIntialSectionContainingOnly (const juce_wchar* const text, const juce_wchar* const allowedChars) throw()
- {
- if (allowedChars == 0)
- return 0;
-
- int i = 0;
-
- for (;;)
- {
- if (indexOfCharFast (allowedChars, text[i]) < 0)
- break;
-
- ++i;
- }
-
- return i;
- }
-
- int CharacterFunctions::ftime (char* const dest, const int maxChars, const char* const format, const struct tm* const tm) throw()
- {
- return (int) strftime (dest, maxChars, format, tm);
- }
-
- int CharacterFunctions::ftime (juce_wchar* const dest, const int maxChars, const juce_wchar* const format, const struct tm* const tm) throw()
- {
- return (int) wcsftime (dest, maxChars, format, tm);
- }
-
- int CharacterFunctions::getIntValue (const char* const s) throw()
- {
- return atoi (s);
- }
-
- int CharacterFunctions::getIntValue (const juce_wchar* s) throw()
- {
- #if JUCE_WINDOWS
- return _wtoi (s);
- #else
- int v = 0;
-
- while (isWhitespace (*s))
- ++s;
-
- const bool isNeg = *s == '-';
- if (isNeg)
- ++s;
-
- for (;;)
- {
- const wchar_t c = *s++;
-
- if (c >= '0' && c <= '9')
- v = v * 10 + (int) (c - '0');
- else
- break;
- }
-
- return isNeg ? -v : v;
- #endif
- }
-
- int64 CharacterFunctions::getInt64Value (const char* s) throw()
- {
- #if JUCE_LINUX
- return atoll (s);
- #elif JUCE_WINDOWS
- return _atoi64 (s);
- #else
- int64 v = 0;
-
- while (isWhitespace (*s))
- ++s;
-
- const bool isNeg = *s == '-';
- if (isNeg)
- ++s;
-
- for (;;)
- {
- const char c = *s++;
-
- if (c >= '0' && c <= '9')
- v = v * 10 + (int64) (c - '0');
- else
- break;
- }
-
- return isNeg ? -v : v;
- #endif
- }
-
- int64 CharacterFunctions::getInt64Value (const juce_wchar* s) throw()
- {
- #if JUCE_WINDOWS
- return _wtoi64 (s);
- #else
- int64 v = 0;
-
- while (isWhitespace (*s))
- ++s;
-
- const bool isNeg = *s == '-';
- if (isNeg)
- ++s;
-
- for (;;)
- {
- const juce_wchar c = *s++;
-
- if (c >= '0' && c <= '9')
- v = v * 10 + (int64) (c - '0');
- else
- break;
- }
-
- return isNeg ? -v : v;
- #endif
- }
-
- //==============================================================================
- static double juce_mulexp10 (const double value, int exponent) throw()
- {
- if (exponent == 0)
- return value;
-
- if (value == 0)
- return 0;
-
- const bool negative = (exponent < 0);
- if (negative)
- exponent = -exponent;
-
- double result = 1.0, power = 10.0;
- for (int bit = 1; exponent != 0; bit <<= 1)
- {
- if ((exponent & bit) != 0)
- {
- exponent ^= bit;
- result *= power;
- if (exponent == 0)
- break;
- }
- power *= power;
- }
-
- return negative ? (value / result) : (value * result);
- }
-
- template <class CharType>
- double juce_atof (const CharType* const original) throw()
- {
- double result[3] = { 0, 0, 0 }, accumulator[2] = { 0, 0 };
- int exponentAdjustment[2] = { 0, 0 }, exponentAccumulator[2] = { -1, -1 };
- int exponent = 0, decPointIndex = 0, digit = 0;
- int lastDigit = 0, numSignificantDigits = 0;
- bool isNegative = false, digitsFound = false;
- const int maxSignificantDigits = 15 + 2;
-
- const CharType* s = original;
- while (CharacterFunctions::isWhitespace (*s))
- ++s;
-
- switch (*s)
- {
- case '-': isNegative = true; // fall-through..
- case '+': ++s;
- }
-
- if (*s == 'n' || *s == 'N' || *s == 'i' || *s == 'I')
- return atof (String (original).toUTF8()); // Let the c library deal with NAN and INF
-
- for (;;)
- {
- if (CharacterFunctions::isDigit (*s))
- {
- lastDigit = digit;
- digit = *s++ - '0';
- digitsFound = true;
-
- if (decPointIndex != 0)
- exponentAdjustment[1]++;
-
- if (numSignificantDigits == 0 && digit == 0)
- continue;
-
- if (++numSignificantDigits > maxSignificantDigits)
- {
- if (digit > 5)
- ++accumulator [decPointIndex];
- else if (digit == 5 && (lastDigit & 1) != 0)
- ++accumulator [decPointIndex];
-
- if (decPointIndex > 0)
- exponentAdjustment[1]--;
- else
- exponentAdjustment[0]++;
-
- while (CharacterFunctions::isDigit (*s))
- {
- ++s;
- if (decPointIndex == 0)
- exponentAdjustment[0]++;
- }
- }
- else
- {
- const double maxAccumulatorValue = (double) ((std::numeric_limits<unsigned int>::max() - 9) / 10);
- if (accumulator [decPointIndex] > maxAccumulatorValue)
- {
- result [decPointIndex] = juce_mulexp10 (result [decPointIndex], exponentAccumulator [decPointIndex])
- + accumulator [decPointIndex];
- accumulator [decPointIndex] = 0;
- exponentAccumulator [decPointIndex] = 0;
- }
-
- accumulator [decPointIndex] = accumulator[decPointIndex] * 10 + digit;
- exponentAccumulator [decPointIndex]++;
- }
- }
- else if (decPointIndex == 0 && *s == '.')
- {
- ++s;
- decPointIndex = 1;
-
- if (numSignificantDigits > maxSignificantDigits)
- {
- while (CharacterFunctions::isDigit (*s))
- ++s;
- break;
- }
- }
- else
- {
- break;
- }
- }
-
- result[0] = juce_mulexp10 (result[0], exponentAccumulator[0]) + accumulator[0];
-
- if (decPointIndex != 0)
- result[1] = juce_mulexp10 (result[1], exponentAccumulator[1]) + accumulator[1];
-
- if ((*s == 'e' || *s == 'E') && digitsFound)
- {
- bool negativeExponent = false;
-
- switch (*++s)
- {
- case '-': negativeExponent = true; // fall-through..
- case '+': ++s;
- }
-
- while (CharacterFunctions::isDigit (*s))
- exponent = (exponent * 10) + (*s++ - '0');
-
- if (negativeExponent)
- exponent = -exponent;
- }
-
- double r = juce_mulexp10 (result[0], exponent + exponentAdjustment[0]);
- if (decPointIndex != 0)
- r += juce_mulexp10 (result[1], exponent - exponentAdjustment[1]);
-
- return isNegative ? -r : r;
- }
-
- double CharacterFunctions::getDoubleValue (const char* const s) throw()
- {
- return juce_atof <char> (s);
- }
-
- double CharacterFunctions::getDoubleValue (const juce_wchar* const s) throw()
- {
- return juce_atof <juce_wchar> (s);
- }
-
- //==============================================================================
- char CharacterFunctions::toUpperCase (const char character) throw()
- {
- return (char) toupper (character);
- }
-
- juce_wchar CharacterFunctions::toUpperCase (const juce_wchar character) throw()
- {
- return towupper (character);
- }
-
- void CharacterFunctions::toUpperCase (char* s) throw()
- {
- #if JUCE_WINDOWS
- strupr (s);
- #else
- while (*s != 0)
- {
- *s = toUpperCase (*s);
- ++s;
- }
- #endif
- }
-
- void CharacterFunctions::toUpperCase (juce_wchar* s) throw()
- {
- #if JUCE_WINDOWS
- _wcsupr (s);
- #else
- while (*s != 0)
- {
- *s = toUpperCase (*s);
- ++s;
- }
- #endif
- }
-
- bool CharacterFunctions::isUpperCase (const char character) throw()
- {
- return isupper (character) != 0;
- }
-
- bool CharacterFunctions::isUpperCase (const juce_wchar character) throw()
- {
- #if JUCE_WINDOWS
- return iswupper (character) != 0;
- #else
- return toLowerCase (character) != character;
- #endif
- }
-
- //==============================================================================
- char CharacterFunctions::toLowerCase (const char character) throw()
- {
- return (char) tolower (character);
- }
-
- juce_wchar CharacterFunctions::toLowerCase (const juce_wchar character) throw()
- {
- return towlower (character);
- }
-
- void CharacterFunctions::toLowerCase (char* s) throw()
- {
- #if JUCE_WINDOWS
- strlwr (s);
- #else
- while (*s != 0)
- {
- *s = toLowerCase (*s);
- ++s;
- }
- #endif
- }
-
- void CharacterFunctions::toLowerCase (juce_wchar* s) throw()
- {
- #if JUCE_WINDOWS
- _wcslwr (s);
- #else
- while (*s != 0)
- {
- *s = toLowerCase (*s);
- ++s;
- }
- #endif
- }
-
- bool CharacterFunctions::isLowerCase (const char character) throw()
- {
- return islower (character) != 0;
- }
-
- bool CharacterFunctions::isLowerCase (const juce_wchar character) throw()
- {
- #if JUCE_WINDOWS
- return iswlower (character) != 0;
- #else
- return toUpperCase (character) != character;
- #endif
- }
-
- //==============================================================================
- bool CharacterFunctions::isWhitespace (const char character) throw()
- {
- return character == ' ' || (character <= 13 && character >= 9);
- }
-
- bool CharacterFunctions::isWhitespace (const juce_wchar character) throw()
- {
- return iswspace (character) != 0;
- }
-
- bool CharacterFunctions::isDigit (const char character) throw()
- {
- return (character >= '0' && character <= '9');
- }
-
- bool CharacterFunctions::isDigit (const juce_wchar character) throw()
- {
- return iswdigit (character) != 0;
- }
-
- bool CharacterFunctions::isLetter (const char character) throw()
- {
- return (character >= 'a' && character <= 'z')
- || (character >= 'A' && character <= 'Z');
- }
-
- bool CharacterFunctions::isLetter (const juce_wchar character) throw()
- {
- return iswalpha (character) != 0;
- }
-
- bool CharacterFunctions::isLetterOrDigit (const char character) throw()
- {
- return (character >= 'a' && character <= 'z')
- || (character >= 'A' && character <= 'Z')
- || (character >= '0' && character <= '9');
- }
-
- bool CharacterFunctions::isLetterOrDigit (const juce_wchar character) throw()
- {
- return iswalnum (character) != 0;
- }
-
- int CharacterFunctions::getHexDigitValue (const juce_wchar digit) throw()
- {
- unsigned int d = digit - '0';
- if (d < (unsigned int) 10)
- return (int) d;
-
- d += '0' - 'a';
- if (d < (unsigned int) 6)
- return (int) d + 10;
-
- d += 'a' - 'A';
- if (d < (unsigned int) 6)
- return (int) d + 10;
-
- return -1;
- }
-
- #if JUCE_MSVC
- #pragma warning (pop)
- #endif
-
- END_JUCE_NAMESPACE
|