| @@ -999,6 +999,9 @@ | |||
| 8E8BE2F1C182E418BBA6903C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_win32_Windowing.cpp; path = ../../src/native/windows/juce_win32_Windowing.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 76E2084D2148068F9138A816 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_CharacterFunctions.cpp; path = ../../src/text/juce_CharacterFunctions.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 33F16EE4F38C9B76E7FAEF78 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharacterFunctions.h; path = ../../src/text/juce_CharacterFunctions.h; sourceTree = SOURCE_ROOT; }; | |||
| 4007410FACA2F865FD8EF769 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_UTF8.h; path = ../../src/text/juce_CharPointer_UTF8.h; sourceTree = SOURCE_ROOT; }; | |||
| 663746215E9BA6C761172B85 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_UTF16.h; path = ../../src/text/juce_CharPointer_UTF16.h; sourceTree = SOURCE_ROOT; }; | |||
| C3FD9D93626F80A45F9B6DDE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_UTF32.h; path = ../../src/text/juce_CharPointer_UTF32.h; sourceTree = SOURCE_ROOT; }; | |||
| 8273A206FB309671284959DD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Identifier.cpp; path = ../../src/text/juce_Identifier.cpp; sourceTree = SOURCE_ROOT; }; | |||
| BF888BC540B64D5C61E46A34 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Identifier.h; path = ../../src/text/juce_Identifier.h; sourceTree = SOURCE_ROOT; }; | |||
| 4A97C8D2FF6454DDD3AF4BE5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_LocalisedStrings.cpp; path = ../../src/text/juce_LocalisedStrings.cpp; sourceTree = SOURCE_ROOT; }; | |||
| @@ -1803,6 +1806,9 @@ | |||
| C6B52BCD0CB1B809D6DE555A = { isa = PBXGroup; children = ( | |||
| 76E2084D2148068F9138A816, | |||
| 33F16EE4F38C9B76E7FAEF78, | |||
| 4007410FACA2F865FD8EF769, | |||
| 663746215E9BA6C761172B85, | |||
| C3FD9D93626F80A45F9B6DDE, | |||
| 8273A206FB309671284959DD, | |||
| BF888BC540B64D5C61E46A34, | |||
| 4A97C8D2FF6454DDD3AF4BE5, | |||
| @@ -937,6 +937,9 @@ | |||
| <Filter Name="text"> | |||
| <File RelativePath="..\..\src\text\juce_CharacterFunctions.cpp"/> | |||
| <File RelativePath="..\..\src\text\juce_CharacterFunctions.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF8.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF16.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF32.h"/> | |||
| <File RelativePath="..\..\src\text\juce_Identifier.cpp"/> | |||
| <File RelativePath="..\..\src\text\juce_Identifier.h"/> | |||
| <File RelativePath="..\..\src\text\juce_LocalisedStrings.cpp"/> | |||
| @@ -937,6 +937,9 @@ | |||
| <Filter Name="text"> | |||
| <File RelativePath="..\..\src\text\juce_CharacterFunctions.cpp"/> | |||
| <File RelativePath="..\..\src\text\juce_CharacterFunctions.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF8.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF16.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF32.h"/> | |||
| <File RelativePath="..\..\src\text\juce_Identifier.cpp"/> | |||
| <File RelativePath="..\..\src\text\juce_Identifier.h"/> | |||
| <File RelativePath="..\..\src\text\juce_LocalisedStrings.cpp"/> | |||
| @@ -939,6 +939,9 @@ | |||
| <Filter Name="text"> | |||
| <File RelativePath="..\..\src\text\juce_CharacterFunctions.cpp"/> | |||
| <File RelativePath="..\..\src\text\juce_CharacterFunctions.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF8.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF16.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF32.h"/> | |||
| <File RelativePath="..\..\src\text\juce_Identifier.cpp"/> | |||
| <File RelativePath="..\..\src\text\juce_Identifier.h"/> | |||
| <File RelativePath="..\..\src\text\juce_LocalisedStrings.cpp"/> | |||
| @@ -757,6 +757,9 @@ | |||
| <ClInclude Include="..\..\src\native\windows\juce_win32_DynamicLibraryLoader.h"/> | |||
| <ClInclude Include="..\..\src\native\windows\juce_win32_NativeIncludes.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_CharacterFunctions.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_UTF8.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_UTF16.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_UTF32.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_Identifier.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_LocalisedStrings.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_NewLine.h"/> | |||
| @@ -2202,6 +2202,15 @@ | |||
| <ClInclude Include="..\..\src\text\juce_CharacterFunctions.h"> | |||
| <Filter>Juce\Source\text</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_UTF8.h"> | |||
| <Filter>Juce\Source\text</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_UTF16.h"> | |||
| <Filter>Juce\Source\text</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_UTF32.h"> | |||
| <Filter>Juce\Source\text</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\text\juce_Identifier.h"> | |||
| <Filter>Juce\Source\text</Filter> | |||
| </ClInclude> | |||
| @@ -999,6 +999,9 @@ | |||
| 8E8BE2F1C182E418BBA6903C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_win32_Windowing.cpp; path = ../../src/native/windows/juce_win32_Windowing.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 76E2084D2148068F9138A816 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_CharacterFunctions.cpp; path = ../../src/text/juce_CharacterFunctions.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 33F16EE4F38C9B76E7FAEF78 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharacterFunctions.h; path = ../../src/text/juce_CharacterFunctions.h; sourceTree = SOURCE_ROOT; }; | |||
| 4007410FACA2F865FD8EF769 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_UTF8.h; path = ../../src/text/juce_CharPointer_UTF8.h; sourceTree = SOURCE_ROOT; }; | |||
| 663746215E9BA6C761172B85 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_UTF16.h; path = ../../src/text/juce_CharPointer_UTF16.h; sourceTree = SOURCE_ROOT; }; | |||
| C3FD9D93626F80A45F9B6DDE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_UTF32.h; path = ../../src/text/juce_CharPointer_UTF32.h; sourceTree = SOURCE_ROOT; }; | |||
| 8273A206FB309671284959DD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Identifier.cpp; path = ../../src/text/juce_Identifier.cpp; sourceTree = SOURCE_ROOT; }; | |||
| BF888BC540B64D5C61E46A34 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Identifier.h; path = ../../src/text/juce_Identifier.h; sourceTree = SOURCE_ROOT; }; | |||
| 4A97C8D2FF6454DDD3AF4BE5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_LocalisedStrings.cpp; path = ../../src/text/juce_LocalisedStrings.cpp; sourceTree = SOURCE_ROOT; }; | |||
| @@ -1803,6 +1806,9 @@ | |||
| C6B52BCD0CB1B809D6DE555A = { isa = PBXGroup; children = ( | |||
| 76E2084D2148068F9138A816, | |||
| 33F16EE4F38C9B76E7FAEF78, | |||
| 4007410FACA2F865FD8EF769, | |||
| 663746215E9BA6C761172B85, | |||
| C3FD9D93626F80A45F9B6DDE, | |||
| 8273A206FB309671284959DD, | |||
| BF888BC540B64D5C61E46A34, | |||
| 4A97C8D2FF6454DDD3AF4BE5, | |||
| @@ -1435,6 +1435,12 @@ | |||
| resource="0" file="src/text/juce_CharacterFunctions.cpp"/> | |||
| <FILE id="McKZNzGvH" name="juce_CharacterFunctions.h" compile="0" resource="0" | |||
| file="src/text/juce_CharacterFunctions.h"/> | |||
| <FILE id="vCX7K0" name="juce_CharPointer_UTF8.h" compile="0" resource="0" | |||
| file="src/text/juce_CharPointer_UTF8.h"/> | |||
| <FILE id="KKhKRD" name="juce_CharPointer_UTF16.h" compile="0" resource="0" | |||
| file="src/text/juce_CharPointer_UTF16.h"/> | |||
| <FILE id="rE1hlF" name="juce_CharPointer_UTF32.h" compile="0" resource="0" | |||
| file="src/text/juce_CharPointer_UTF32.h"/> | |||
| <FILE id="iGtCiI8" name="juce_Identifier.cpp" compile="1" resource="0" | |||
| file="src/text/juce_Identifier.cpp"/> | |||
| <FILE id="CPlhWqs" name="juce_Identifier.h" compile="0" resource="0" | |||
| @@ -67,6 +67,8 @@ | |||
| #include "../src/native/linux/juce_linux_NativeIncludes.h" | |||
| #elif JUCE_MAC || JUCE_IOS | |||
| #include "../src/native/mac/juce_mac_NativeIncludes.h" | |||
| #elif JUCE_ANDROID | |||
| #include "../src/native/android/juce_android_NativeIncludes.h" | |||
| #else | |||
| #error "Unknown platform!" | |||
| #endif | |||
| @@ -399,13 +401,11 @@ | |||
| #if JUCE_WINDOWS | |||
| #include "../src/native/windows/juce_win32_NativeCode.cpp" | |||
| #endif | |||
| #if JUCE_LINUX | |||
| #elif JUCE_LINUX | |||
| #include "../src/native/linux/juce_linux_NativeCode.cpp" | |||
| #endif | |||
| #if JUCE_MAC || JUCE_IOS | |||
| #elif JUCE_MAC || JUCE_IOS | |||
| #include "../src/native/mac/juce_mac_NativeCode.mm" | |||
| #elif JUCE_ANDROID | |||
| #include "../src/native/android/juce_android_NativeCode.cpp" | |||
| #endif | |||
| #endif | |||
| @@ -630,7 +630,7 @@ static Component* createMiscPage() | |||
| textEditor1->setBounds (10, 25, 200, 24); | |||
| textEditor1->setText ("single-line text box"); | |||
| TextEditor* textEditor2 = new TextEditor ("password", (tchar) 0x2022); | |||
| TextEditor* textEditor2 = new TextEditor ("password", (juce_wchar) 0x2022); | |||
| page->addAndMakeVisible (textEditor2); | |||
| textEditor2->setBounds (10, 55, 200, 24); | |||
| textEditor2->setText ("password"); | |||
| @@ -798,7 +798,7 @@ void AudioDeviceManager::addMidiInputCallback (const String& name, | |||
| if (name.isEmpty()) | |||
| { | |||
| midiCallbacks.add (callbackToAdd); | |||
| midiCallbackDevices.add (0); | |||
| midiCallbackDevices.add (String::empty); | |||
| } | |||
| else | |||
| { | |||
| @@ -808,7 +808,7 @@ void AudioDeviceManager::addMidiInputCallback (const String& name, | |||
| { | |||
| const ScopedLock sl (midiCallbackLock); | |||
| midiCallbacks.add (callbackToAdd); | |||
| midiCallbackDevices.add (enabledMidiInputs[i]); | |||
| midiCallbackDevices.add (enabledMidiInputs[i]->getName()); | |||
| break; | |||
| } | |||
| } | |||
| @@ -821,12 +821,7 @@ void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputC | |||
| for (int i = midiCallbacks.size(); --i >= 0;) | |||
| { | |||
| String devName; | |||
| if (midiCallbackDevices.getUnchecked(i) != 0) | |||
| devName = midiCallbackDevices.getUnchecked(i)->getName(); | |||
| if (devName == name) | |||
| if (midiCallbackDevices[i] == name) | |||
| { | |||
| midiCallbacks.remove (i); | |||
| midiCallbackDevices.remove (i); | |||
| @@ -845,9 +840,9 @@ void AudioDeviceManager::handleIncomingMidiMessageInt (MidiInput* source, | |||
| for (int i = midiCallbackDevices.size(); --i >= 0;) | |||
| { | |||
| MidiInput* const md = midiCallbackDevices.getUnchecked(i); | |||
| const String name (midiCallbackDevices[i]); | |||
| if (md == source || (md == 0 && isDefaultSource)) | |||
| if ((isDefaultSource && name.isEmpty()) || (name.isNotEmpty() && name == source->getName())) | |||
| midiCallbacks.getUnchecked(i)->handleIncomingMidiMessage (source, message); | |||
| } | |||
| } | |||
| @@ -464,7 +464,7 @@ private: | |||
| StringArray midiInsFromXml; | |||
| OwnedArray <MidiInput> enabledMidiInputs; | |||
| Array <MidiInputCallback*> midiCallbacks; | |||
| Array <MidiInput*> midiCallbackDevices; | |||
| StringArray midiCallbackDevices; | |||
| String defaultMidiOutputName; | |||
| ScopedPointer <MidiOutput> defaultMidiOutput; | |||
| CriticalSection audioCallbackLock, midiCallbackLock; | |||
| @@ -58,11 +58,6 @@ public: | |||
| { | |||
| } | |||
| /** Destructor. */ | |||
| ~SparseSet() | |||
| { | |||
| } | |||
| //============================================================================== | |||
| /** Clears the set. */ | |||
| void clear() | |||
| @@ -113,7 +108,7 @@ public: | |||
| index -= len; | |||
| } | |||
| return Type (0); | |||
| return Type(); | |||
| } | |||
| /** Checks whether a particular value is in the set. */ | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 17 | |||
| #define JUCE_BUILDNUMBER 18 | |||
| /** Current Juce version number. | |||
| @@ -130,6 +130,11 @@ | |||
| #endif | |||
| #endif | |||
| #if JUCE_ANDROID | |||
| #include <sys/atomics.h> | |||
| #include <byteswap.h> | |||
| #endif | |||
| //============================================================================== | |||
| // DLL building settings on Win32 | |||
| #if JUCE_MSVC | |||
| @@ -45,7 +45,7 @@ | |||
| #define JUCE_WINDOWS 1 | |||
| #elif defined (LINUX) || defined (__linux__) | |||
| #define JUCE_LINUX 1 | |||
| #elif defined(__APPLE_CPP__) || defined(__APPLE_CC__) | |||
| #elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) | |||
| #include <CoreFoundation/CoreFoundation.h> // (needed to find out what platform we're using) | |||
| #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR | |||
| @@ -54,6 +54,9 @@ | |||
| #else | |||
| #define JUCE_MAC 1 | |||
| #endif | |||
| #elif defined (JUCE_ANDROID) | |||
| #undef JUCE_ANDROID | |||
| #define JUCE_ANDROID 1 | |||
| #else | |||
| #error "Unknown platform!" | |||
| #endif | |||
| @@ -124,17 +127,20 @@ | |||
| #endif | |||
| //============================================================================== | |||
| #if JUCE_LINUX | |||
| #if JUCE_LINUX || JUCE_ANDROID | |||
| #ifdef _DEBUG | |||
| #define JUCE_DEBUG 1 | |||
| #endif | |||
| // Allow override for big-endian Linux platforms | |||
| #ifndef JUCE_BIG_ENDIAN | |||
| #if defined (__LITTLE_ENDIAN__) || ! defined (JUCE_BIG_ENDIAN) | |||
| #define JUCE_LITTLE_ENDIAN 1 | |||
| #undef JUCE_BIG_ENDIAN | |||
| #else | |||
| #undef JUCE_LITTLE_ENDIAN | |||
| #define JUCE_BIG_ENDIAN 1 | |||
| #endif | |||
| #if defined (__LP64__) || defined (_LP64) | |||
| @@ -143,7 +149,9 @@ | |||
| #define JUCE_32BIT 1 | |||
| #endif | |||
| #define JUCE_INTEL 1 | |||
| #if __MMX__ || __SSE__ || __amd64__ | |||
| #define JUCE_INTEL 1 | |||
| #endif | |||
| #endif | |||
| //============================================================================== | |||
| @@ -56,33 +56,33 @@ namespace CppTokeniser | |||
| bool isReservedKeyword (const juce_wchar* const token, const int tokenLength) throw() | |||
| { | |||
| static const juce_wchar* const keywords2Char[] = | |||
| { JUCE_T("if"), JUCE_T("do"), JUCE_T("or"), JUCE_T("id"), 0 }; | |||
| static const char* const keywords2Char[] = | |||
| { "if", "do", "or", "id", 0 }; | |||
| static const juce_wchar* const keywords3Char[] = | |||
| { JUCE_T("for"), JUCE_T("int"), JUCE_T("new"), JUCE_T("try"), JUCE_T("xor"), JUCE_T("and"), JUCE_T("asm"), JUCE_T("not"), 0 }; | |||
| static const char* const keywords3Char[] = | |||
| { "for", "int", "new", "try", "xor", "and", "asm", "not", 0 }; | |||
| static const juce_wchar* const keywords4Char[] = | |||
| { JUCE_T("bool"), JUCE_T("void"), JUCE_T("this"), JUCE_T("true"), JUCE_T("long"), JUCE_T("else"), JUCE_T("char"), | |||
| JUCE_T("enum"), JUCE_T("case"), JUCE_T("goto"), JUCE_T("auto"), 0 }; | |||
| static const char* const keywords4Char[] = | |||
| { "bool", "void", "this", "true", "long", "else", "char", | |||
| "enum", "case", "goto", "auto", 0 }; | |||
| static const juce_wchar* const keywords5Char[] = | |||
| { JUCE_T("while"), JUCE_T("bitor"), JUCE_T("break"), JUCE_T("catch"), JUCE_T("class"), JUCE_T("compl"), JUCE_T("const"), JUCE_T("false"), | |||
| JUCE_T("float"), JUCE_T("short"), JUCE_T("throw"), JUCE_T("union"), JUCE_T("using"), JUCE_T("or_eq"), 0 }; | |||
| static const char* const keywords5Char[] = | |||
| { "while", "bitor", "break", "catch", "class", "compl", "const", "false", | |||
| "float", "short", "throw", "union", "using", "or_eq", 0 }; | |||
| static const juce_wchar* const keywords6Char[] = | |||
| { JUCE_T("return"), JUCE_T("struct"), JUCE_T("and_eq"), JUCE_T("bitand"), JUCE_T("delete"), JUCE_T("double"), JUCE_T("extern"), | |||
| JUCE_T("friend"), JUCE_T("inline"), JUCE_T("not_eq"), JUCE_T("public"), JUCE_T("sizeof"), JUCE_T("static"), JUCE_T("signed"), | |||
| JUCE_T("switch"), JUCE_T("typeid"), JUCE_T("wchar_t"), JUCE_T("xor_eq"), 0}; | |||
| static const char* const keywords6Char[] = | |||
| { "return", "struct", "and_eq", "bitand", "delete", "double", "extern", | |||
| "friend", "inline", "not_eq", "public", "sizeof", "static", "signed", | |||
| "switch", "typeid", "wchar_t", "xor_eq", 0}; | |||
| static const juce_wchar* const keywordsOther[] = | |||
| { JUCE_T("const_cast"), JUCE_T("continue"), JUCE_T("default"), JUCE_T("explicit"), JUCE_T("mutable"), JUCE_T("namespace"), | |||
| JUCE_T("operator"), JUCE_T("private"), JUCE_T("protected"), JUCE_T("register"), JUCE_T("reinterpret_cast"), JUCE_T("static_cast"), | |||
| JUCE_T("template"), JUCE_T("typedef"), JUCE_T("typename"), JUCE_T("unsigned"), JUCE_T("virtual"), JUCE_T("volatile"), | |||
| JUCE_T("@implementation"), JUCE_T("@interface"), JUCE_T("@end"), JUCE_T("@synthesize"), JUCE_T("@dynamic"), JUCE_T("@public"), | |||
| JUCE_T("@private"), JUCE_T("@property"), JUCE_T("@protected"), JUCE_T("@class"), 0 }; | |||
| static const char* const keywordsOther[] = | |||
| { "const_cast", "continue", "default", "explicit", "mutable", "namespace", | |||
| "operator", "private", "protected", "register", "reinterpret_cast", "static_cast", | |||
| "template", "typedef", "typename", "unsigned", "virtual", "volatile", | |||
| "@implementation", "@interface", "@end", "@synthesize", "@dynamic", "@public", | |||
| "@private", "@property", "@protected", "@class", 0 }; | |||
| const juce_wchar* const* k; | |||
| const char* const* k; | |||
| switch (tokenLength) | |||
| { | |||
| @@ -103,7 +103,7 @@ namespace CppTokeniser | |||
| int i = 0; | |||
| while (k[i] != 0) | |||
| { | |||
| if (k[i][0] == token[0] && CharacterFunctions::compare (k[i], token) == 0) | |||
| if (k[i][0] == token[0] && CharPointer_UTF8 (k[i]).compare (CharPointer_UTF32 (token)) == 0) | |||
| return true; | |||
| ++i; | |||
| @@ -434,7 +434,7 @@ void ListBox::updateContent() | |||
| bool selectionChanged = false; | |||
| if (selected [selected.size() - 1] >= totalItems) | |||
| if (selected.size() > 0 && selected [selected.size() - 1] >= totalItems) | |||
| { | |||
| selected.removeRange (Range <int> (totalItems, std::numeric_limits<int>::max())); | |||
| lastRowSelected = getSelectedRow (0); | |||
| @@ -34,7 +34,7 @@ | |||
| #endif | |||
| #else | |||
| #if JUCE_LINUX | |||
| #if JUCE_LINUX || JUCE_ANDROID | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <sys/errno.h> | |||
| @@ -58,7 +58,7 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| #include "../../threads/juce_Thread.h" | |||
| #if defined (JUCE_LINUX) || defined (JUCE_MAC) || defined (JUCE_IOS) | |||
| #if JUCE_LINUX || JUCE_MAC || JUCE_IOS || JUCE_ANDROID | |||
| typedef socklen_t juce_socklen_t; | |||
| #else | |||
| typedef int juce_socklen_t; | |||
| @@ -121,7 +121,7 @@ namespace URLHelpers | |||
| int i = 0; | |||
| while (CharacterFunctions::isLetterOrDigit (url[i]) | |||
| || CharacterFunctions::indexOfChar (L"+-.", url[i], false) >= 0) | |||
| || url[i] == '+' || url[i] == '-' || url[i] == '.') | |||
| ++i; | |||
| return url[i] == ':' ? i + 1 : 0; | |||
| @@ -179,7 +179,7 @@ namespace URLHelpers | |||
| // just a short text attachment, so use simple url encoding.. | |||
| headers << "Content-Type: application/x-www-form-urlencoded\r\nContent-length: " | |||
| << (unsigned int) postData.getSize() << "\r\n"; | |||
| << (int) postData.getSize() << "\r\n"; | |||
| } | |||
| } | |||
| } | |||
| @@ -411,8 +411,8 @@ const String URL::removeEscapeChars (const String& s) | |||
| const String URL::addEscapeChars (const String& s, const bool isParameter) | |||
| { | |||
| const char* const legalChars = isParameter ? "_-.*!'()" | |||
| : ",$_-.*!'()"; | |||
| const CharPointer_UTF8 legalChars (isParameter ? "_-.*!'()" | |||
| : ",$_-.*!'()"); | |||
| Array<char> utf8 (s.toUTF8(), s.getNumBytesAsUTF8()); | |||
| @@ -421,7 +421,7 @@ const String URL::addEscapeChars (const String& s, const bool isParameter) | |||
| const char c = utf8.getUnchecked(i); | |||
| if (! (CharacterFunctions::isLetterOrDigit (c) | |||
| || CharacterFunctions::indexOfChar (legalChars, c, false) >= 0)) | |||
| || legalChars.indexOf ((juce_wchar) c) >= 0)) | |||
| { | |||
| if (c == ' ') | |||
| { | |||
| @@ -233,6 +233,15 @@ | |||
| #ifndef __JUCE_CHARACTERFUNCTIONS_JUCEHEADER__ | |||
| #include "text/juce_CharacterFunctions.h" | |||
| #endif | |||
| #ifndef __JUCE_CHARPOINTER_UTF16_JUCEHEADER__ | |||
| #include "text/juce_CharPointer_UTF16.h" | |||
| #endif | |||
| #ifndef __JUCE_CHARPOINTER_UTF32_JUCEHEADER__ | |||
| #include "text/juce_CharPointer_UTF32.h" | |||
| #endif | |||
| #ifndef __JUCE_CHARPOINTER_UTF8_JUCEHEADER__ | |||
| #include "text/juce_CharPointer_UTF8.h" | |||
| #endif | |||
| #ifndef __JUCE_IDENTIFIER_JUCEHEADER__ | |||
| #include "text/juce_Identifier.h" | |||
| #endif | |||
| @@ -91,10 +91,6 @@ typedef unsigned int uint32; | |||
| typedef unsigned int pointer_sized_uint; | |||
| #endif | |||
| /** A platform-independent unicode character type. */ | |||
| typedef wchar_t juce_wchar; | |||
| //============================================================================== | |||
| // Some indispensible min/max functions | |||
| @@ -351,6 +347,8 @@ inline bool juce_isfinite (FloatingPointType value) | |||
| { | |||
| #if JUCE_WINDOWS | |||
| return _finite (value); | |||
| #elif JUCE_ANDROID | |||
| return isfinite (value); | |||
| #else | |||
| return std::isfinite (value); | |||
| #endif | |||
| @@ -244,6 +244,8 @@ inline Type Atomic<Type>::get() const throw() | |||
| #elif JUCE_ATOMICS_WINDOWS | |||
| return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchangeAdd ((volatile long*) &value, (long) 0)) | |||
| : castFrom64Bit ((int64) juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) 0)); | |||
| #elif JUCE_ANDROID | |||
| return castFrom32Bit (__atomic_cmpxchg (castTo32Bit (value), castTo32Bit (value), (volatile int*) &value)); | |||
| #elif JUCE_ATOMICS_GCC | |||
| return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_add_and_fetch ((volatile int32*) &value, 0)) | |||
| : castFrom64Bit ((int64) __sync_add_and_fetch ((volatile int64*) &value, 0)); | |||
| @@ -253,7 +255,9 @@ inline Type Atomic<Type>::get() const throw() | |||
| template <typename Type> | |||
| inline Type Atomic<Type>::exchange (const Type newValue) throw() | |||
| { | |||
| #if JUCE_ATOMICS_MAC || JUCE_ATOMICS_GCC | |||
| #if JUCE_ANDROID | |||
| return castFrom32Bit (__atomic_swap (castTo32Bit (newValue), (volatile int*) &value)); | |||
| #elif JUCE_ATOMICS_MAC || JUCE_ATOMICS_GCC | |||
| Type currentVal = value; | |||
| while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; } | |||
| return currentVal; | |||
| @@ -272,6 +276,14 @@ inline Type Atomic<Type>::operator+= (const Type amountToAdd) throw() | |||
| #elif JUCE_ATOMICS_WINDOWS | |||
| return sizeof (Type) == 4 ? (Type) (juce_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd) | |||
| : (Type) (juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd); | |||
| #elif JUCE_ANDROID | |||
| for (;;) | |||
| { | |||
| const Type oldValue (value); | |||
| const Type newValue (oldValue + amountToAdd); | |||
| if (compareAndSetBool (newValue, oldValue)) | |||
| return newValue; | |||
| } | |||
| #elif JUCE_ATOMICS_GCC | |||
| return (Type) __sync_add_and_fetch (&value, amountToAdd); | |||
| #endif | |||
| @@ -292,6 +304,8 @@ inline Type Atomic<Type>::operator++() throw() | |||
| #elif JUCE_ATOMICS_WINDOWS | |||
| return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) | |||
| : (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); | |||
| #elif JUCE_ANDROID | |||
| return (Type) __atomic_inc (&value); | |||
| #elif JUCE_ATOMICS_GCC | |||
| return (Type) __sync_add_and_fetch (&value, 1); | |||
| #endif | |||
| @@ -306,6 +320,8 @@ inline Type Atomic<Type>::operator--() throw() | |||
| #elif JUCE_ATOMICS_WINDOWS | |||
| return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) | |||
| : (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); | |||
| #elif JUCE_ANDROID | |||
| return (Type) __atomic_dec (&value); | |||
| #elif JUCE_ATOMICS_GCC | |||
| return (Type) __sync_add_and_fetch (&value, -1); | |||
| #endif | |||
| @@ -317,7 +333,7 @@ inline bool Atomic<Type>::compareAndSetBool (const Type newValue, const Type val | |||
| #if JUCE_ATOMICS_MAC | |||
| return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value) | |||
| : OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value); | |||
| #elif JUCE_ATOMICS_WINDOWS | |||
| #elif JUCE_ATOMICS_WINDOWS || JUCE_ANDROID | |||
| return compareAndSetValue (newValue, valueToCompare) == valueToCompare; | |||
| #elif JUCE_ATOMICS_GCC | |||
| return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)) | |||
| @@ -342,6 +358,8 @@ inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type va | |||
| #elif JUCE_ATOMICS_WINDOWS | |||
| return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedCompareExchange ((volatile long*) &value, (long) castTo32Bit (newValue), (long) castTo32Bit (valueToCompare))) | |||
| : castFrom64Bit ((int64) juce_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue), (__int64) castTo64Bit (valueToCompare))); | |||
| #elif JUCE_ANDROID | |||
| return castFrom32Bit (__atomic_cmpxchg (castTo32Bit (valueToCompare), castTo32Bit (newValue), (volatile int*) &value)); | |||
| #elif JUCE_ATOMICS_GCC | |||
| return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))) | |||
| : castFrom64Bit ((int64) __sync_val_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue))); | |||
| @@ -118,18 +118,22 @@ inline uint32 ByteOrder::swap (uint32 n) | |||
| { | |||
| #if JUCE_MAC || JUCE_IOS | |||
| return OSSwapInt32 (n); | |||
| #elif JUCE_GCC | |||
| #elif JUCE_GCC && JUCE_INTEL | |||
| asm("bswap %%eax" : "=a"(n) : "a"(n)); | |||
| return n; | |||
| #elif JUCE_USE_INTRINSICS | |||
| return _byteswap_ulong (n); | |||
| #else | |||
| #elif JUCE_MSVC | |||
| __asm { | |||
| mov eax, n | |||
| bswap eax | |||
| mov n, eax | |||
| } | |||
| return n; | |||
| #elif JUCE_ANDROID | |||
| return bswap_32 (n); | |||
| #else | |||
| return (n << 24) | (n >> 24) | ((n & 0xff00) << 8) | ((n & 0xff0000) >> 8); | |||
| #endif | |||
| } | |||
| @@ -36,7 +36,9 @@ CriticalSection::CriticalSection() throw() | |||
| pthread_mutexattr_t atts; | |||
| pthread_mutexattr_init (&atts); | |||
| pthread_mutexattr_settype (&atts, PTHREAD_MUTEX_RECURSIVE); | |||
| #if ! JUCE_ANDROID | |||
| pthread_mutexattr_setprotocol (&atts, PTHREAD_PRIO_INHERIT); | |||
| #endif | |||
| pthread_mutex_init (&internal, &atts); | |||
| } | |||
| @@ -73,7 +75,9 @@ public: | |||
| pthread_mutexattr_t atts; | |||
| pthread_mutexattr_init (&atts); | |||
| #if ! JUCE_ANDROID | |||
| pthread_mutexattr_setprotocol (&atts, PTHREAD_PRIO_INHERIT); | |||
| #endif | |||
| pthread_mutex_init (&mutex, &atts); | |||
| } | |||
| @@ -481,9 +485,14 @@ void FileOutputStream::flushInternal() | |||
| //============================================================================== | |||
| const File juce_getExecutableFile() | |||
| { | |||
| #if JUCE_ANDROID | |||
| // TODO | |||
| return File::nonexistent; | |||
| #else | |||
| Dl_info exeInfo; | |||
| dladdr ((const void*) juce_getExecutableFile, &exeInfo); | |||
| dladdr ((void*) juce_getExecutableFile, &exeInfo); // (can't be a const void* on android) | |||
| return File::getCurrentWorkingDirectory().getChildFile (String::fromUTF8 (exeInfo.dli_fname)); | |||
| #endif | |||
| } | |||
| //============================================================================== | |||
| @@ -708,7 +717,13 @@ void Thread::closeThreadHandle() | |||
| void Thread::killThread() | |||
| { | |||
| if (threadHandle_ != 0) | |||
| { | |||
| #if JUCE_ANDROID | |||
| jassertfalse; // pthread_cancel not available! | |||
| #else | |||
| pthread_cancel ((pthread_t) threadHandle_); | |||
| #endif | |||
| } | |||
| } | |||
| void Thread::setCurrentThreadName (const String& /*name*/) | |||
| @@ -358,7 +358,7 @@ private: | |||
| header << "\r\nUser-Agent: JUCE/" << JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION | |||
| << "\r\nConnection: Close\r\nContent-Length: " | |||
| << postData.getSize() << "\r\n" | |||
| << (int) postData.getSize() << "\r\n" | |||
| << headers << "\r\n"; | |||
| MemoryBlock mb; | |||
| @@ -270,7 +270,7 @@ void FileChooser::showPlatformDialog (Array<File>& results, const String& title, | |||
| while (*filename != 0) | |||
| { | |||
| results.add (File (String (files) + "\\" + String (filename))); | |||
| filename += CharacterFunctions::length (filename) + 1; | |||
| filename += wcslen (filename) + 1; | |||
| } | |||
| } | |||
| else if (files[0] != 0) | |||
| @@ -67,11 +67,11 @@ const String SystemClipboard::getTextFromClipboard() | |||
| if (bufH != 0) | |||
| { | |||
| const wchar_t* const data = (const wchar_t*) GlobalLock (bufH); | |||
| const WCHAR* const data = (const WCHAR*) GlobalLock (bufH); | |||
| if (data != 0) | |||
| { | |||
| result = String (data, (int) (GlobalSize (bufH) / sizeof (wchar_t))); | |||
| result = String (data, (int) (GlobalSize (bufH) / sizeof (WCHAR))); | |||
| GlobalUnlock (bufH); | |||
| } | |||
| @@ -308,7 +308,7 @@ static Handle createHandleDataRef (Handle dataHandle, const char* fileName) | |||
| { | |||
| Str255 suffix; | |||
| CharacterFunctions::copy ((char*) suffix, fileName, 128); | |||
| strncpy ((char*) suffix, fileName, 128); | |||
| StringPtr name = suffix; | |||
| err = PtrAndHand (name, dataRef, name[0] + 1); | |||
| @@ -0,0 +1,343 @@ | |||
| /* | |||
| ============================================================================== | |||
| 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. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_CHARPOINTER_UTF16_JUCEHEADER__ | |||
| #define __JUCE_CHARPOINTER_UTF16_JUCEHEADER__ | |||
| //============================================================================== | |||
| /** | |||
| Wraps a pointer to a null-terminated UTF-16 character string, and provides | |||
| various methods to operate on the data. | |||
| @see CharPointer_UTF8, CharPointer_UTF32 | |||
| */ | |||
| class CharPointer_UTF16 | |||
| { | |||
| public: | |||
| typedef int16 CharType; | |||
| inline CharPointer_UTF16 (const CharType* const rawPointer) throw() | |||
| : data (const_cast <CharType*> (rawPointer)) | |||
| { | |||
| } | |||
| inline CharPointer_UTF16 (const CharPointer_UTF16& other) throw() | |||
| : data (other.data) | |||
| { | |||
| } | |||
| inline CharPointer_UTF16& operator= (const CharPointer_UTF16& other) throw() | |||
| { | |||
| data = other.data; | |||
| return *this; | |||
| } | |||
| /** Returns the address that this pointer is pointing to. */ | |||
| inline CharType* getAddress() const throw() { return data; } | |||
| /** Returns true if this pointer is pointing to a null character. */ | |||
| inline bool isEmpty() const throw() { return *data == 0; } | |||
| /** Returns the unicode character that this pointer is pointing to. */ | |||
| juce_wchar operator*() const throw() | |||
| { | |||
| uint32 n = (uint32) (uint16) *data; | |||
| if (n >= 0xd800 && n <= 0xdfff) | |||
| n = 0x10000 + (((n & ~0xd800) << 10) | (data[1] & ~0xdc00)); | |||
| return (juce_wchar) n; | |||
| } | |||
| /** Moves this pointer along to the next character in the string. */ | |||
| CharPointer_UTF16& operator++() throw() | |||
| { | |||
| const juce_wchar n = *data++; | |||
| if (n >= 0xd800 && n <= 0xdfff) | |||
| ++data; | |||
| return *this; | |||
| } | |||
| /** Returns the character that this pointer is currently pointing to, and then | |||
| advances the pointer to point to the next character. */ | |||
| juce_wchar getAndAdvance() throw() | |||
| { | |||
| uint32 n = (uint32) (uint16) *data++; | |||
| if (n >= 0xd800 && n <= 0xdfff) | |||
| { | |||
| n = 0x10000 + (((n & ~0xd800) << 10) | (*data & ~0xdc00)); | |||
| ++data; | |||
| } | |||
| return (juce_wchar) n; | |||
| } | |||
| /** Moves this pointer along to the next character in the string. */ | |||
| CharPointer_UTF16 operator++ (int) throw() | |||
| { | |||
| CharPointer_UTF16 temp (*this); | |||
| ++*this; | |||
| return temp; | |||
| } | |||
| /** Moves this pointer forwards by the specified number of characters. */ | |||
| void operator+= (int numToSkip) throw() | |||
| { | |||
| jassert (numToSkip >= 0); | |||
| while (--numToSkip >= 0) | |||
| ++*this; | |||
| } | |||
| /** Returns the character at a given character index from the start of the string. */ | |||
| juce_wchar operator[] (int characterIndex) const throw() | |||
| { | |||
| CharPointer_UTF16 p (*this); | |||
| p += characterIndex; | |||
| return *p; | |||
| } | |||
| /** Returns a pointer which is moved forwards from this one by the specified number of characters. */ | |||
| CharPointer_UTF16 operator+ (int numToSkip) const throw() | |||
| { | |||
| CharPointer_UTF16 p (*this); | |||
| p += numToSkip; | |||
| return p; | |||
| } | |||
| /** Writes a unicode character to this string, and advances this pointer to point to the next position. */ | |||
| void write (const juce_wchar charToWrite) throw() | |||
| { | |||
| if (charToWrite < 0xd800 || (charToWrite > 0xdfff && charToWrite <= 0xffff)) | |||
| { | |||
| *data++ = (CharType) charToWrite; | |||
| } | |||
| else | |||
| { | |||
| *data++ = (CharType) ((0xd800 - (0x10000 >> 10)) + (charToWrite >> 10)); | |||
| *data++ = (CharType) (0xdc00 + (charToWrite & 0x3ff)); | |||
| } | |||
| } | |||
| /** Returns the number of characters in this string. */ | |||
| size_t length() const throw() | |||
| { | |||
| const CharType* d = data; | |||
| size_t count = 0; | |||
| for (;;) | |||
| { | |||
| const int n = *d++; | |||
| if (n >= 0xd800 && n <= 0xdfff) | |||
| ++d; | |||
| else if (n == 0) | |||
| break; | |||
| ++count; | |||
| } | |||
| return count; | |||
| } | |||
| /** Returns the number of bytes that are used to represent this string. | |||
| This includes the terminating null character. | |||
| */ | |||
| size_t sizeInBytes() const throw() | |||
| { | |||
| return sizeof (CharType) * (findNullIndex (data) + 1); | |||
| } | |||
| /** Returns the number of bytes that would be needed to represent the given | |||
| unicode character in this encoding format. | |||
| */ | |||
| static size_t getBytesRequiredFor (const juce_wchar charToWrite) throw() | |||
| { | |||
| return (charToWrite < 0xd800 || (charToWrite > 0xdfff && charToWrite <= 0xffff)) | |||
| ? 1 : 2; | |||
| } | |||
| /** Returns the number of bytes that would be needed to represent the given | |||
| string in this encoding format. | |||
| The value returned does NOT include the terminating null character. | |||
| */ | |||
| template <class CharPointer> | |||
| static size_t getBytesRequiredFor (CharPointer text) throw() | |||
| { | |||
| size_t count = 0; | |||
| juce_wchar n; | |||
| while ((n = text.getAndAdvance()) != 0) | |||
| count += getBytesRequiredFor (n); | |||
| return count; | |||
| } | |||
| /** Returns a pointer to the null character that terminates this string. */ | |||
| CharPointer_UTF16 findTerminatingNull() const throw() | |||
| { | |||
| const CharType* t = data; | |||
| while (*t != 0) | |||
| ++t; | |||
| return CharPointer_UTF16 (t); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. */ | |||
| template <typename CharPointer> | |||
| void copyAndAdvance (const CharPointer& src) throw() | |||
| { | |||
| CharacterFunctions::copyAndAdvance (*this, src); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. */ | |||
| void copyAndAdvance (const CharPointer_UTF16& src) throw() | |||
| { | |||
| const CharType* s = src.data; | |||
| while ((*data = *s) != 0) | |||
| { | |||
| ++data; | |||
| ++s; | |||
| } | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. | |||
| The maxBytes parameter specifies the maximum number of bytes that can be written | |||
| to the destination buffer before stopping. | |||
| */ | |||
| template <typename CharPointer> | |||
| int copyAndAdvanceUpToBytes (const CharPointer& src, int maxBytes) throw() | |||
| { | |||
| return CharacterFunctions::copyAndAdvanceUpToBytes (*this, src, maxBytes); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. | |||
| The maxChars parameter specifies the maximum number of characters that can be | |||
| written to the destination buffer before stopping (including the terminating null). | |||
| */ | |||
| template <typename CharPointer> | |||
| void copyAndAdvanceUpToNumChars (const CharPointer& src, int maxChars) throw() | |||
| { | |||
| CharacterFunctions::copyAndAdvanceUpToNumChars (*this, src, maxChars); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| template <typename CharPointer> | |||
| int compare (const CharPointer& other) const throw() | |||
| { | |||
| return CharacterFunctions::compare (*this, other); | |||
| } | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| template <typename CharPointer> | |||
| int compareUpTo (const CharPointer& other, int maxChars) const throw() | |||
| { | |||
| return CharacterFunctions::compareUpTo (*this, other, maxChars); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| template <typename CharPointer> | |||
| int compareIgnoreCase (const CharPointer& other) const throw() | |||
| { | |||
| return CharacterFunctions::compareIgnoreCase (*this, other); | |||
| } | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| template <typename CharPointer> | |||
| int compareIgnoreCaseUpTo (const CharPointer& other, int maxChars) const throw() | |||
| { | |||
| return CharacterFunctions::compareIgnoreCaseUpTo (*this, other, maxChars); | |||
| } | |||
| /** Returns the character index of a substring, or -1 if it isn't found. */ | |||
| template <typename CharPointer> | |||
| int indexOf (const CharPointer& stringToFind) const throw() | |||
| { | |||
| return CharacterFunctions::indexOf (*this, stringToFind); | |||
| } | |||
| /** Returns the character index of a unicode character, or -1 if it isn't found. */ | |||
| int indexOf (const juce_wchar charToFind) const throw() | |||
| { | |||
| return CharacterFunctions::indexOfChar (*this, charToFind); | |||
| } | |||
| /** Returns the character index of a unicode character, or -1 if it isn't found. */ | |||
| int indexOf (const juce_wchar charToFind, const bool ignoreCase) const throw() | |||
| { | |||
| return ignoreCase ? CharacterFunctions::indexOfCharIgnoreCase (*this, charToFind) | |||
| : CharacterFunctions::indexOfChar (*this, charToFind); | |||
| } | |||
| /** Returns true if the first character of this string is whitespace. */ | |||
| bool isWhitespace() const throw() { return CharacterFunctions::isWhitespace (operator*()) != 0; } | |||
| /** Returns true if the first character of this string is a digit. */ | |||
| bool isDigit() const throw() { return CharacterFunctions::isDigit (operator*()) != 0; } | |||
| /** Returns true if the first character of this string is a letter. */ | |||
| bool isLetter() const throw() { return CharacterFunctions::isLetter (operator*()) != 0; } | |||
| /** Returns true if the first character of this string is a letter or digit. */ | |||
| bool isLetterOrDigit() const throw() { return CharacterFunctions::isLetterOrDigit (operator*()) != 0; } | |||
| /** Returns true if the first character of this string is upper-case. */ | |||
| bool isUpperCase() const throw() { return CharacterFunctions::isUpperCase (operator*()) != 0; } | |||
| /** Returns true if the first character of this string is lower-case. */ | |||
| bool isLowerCase() const throw() { return CharacterFunctions::isLowerCase (operator*()) != 0; } | |||
| /** Returns an upper-case version of the first character of this string. */ | |||
| juce_wchar toUpperCase() const throw() { return CharacterFunctions::toUpperCase (operator*()); } | |||
| /** Returns a lower-case version of the first character of this string. */ | |||
| juce_wchar toLowerCase() const throw() { return CharacterFunctions::toLowerCase (operator*()); } | |||
| /** Parses this string as a 32-bit integer. */ | |||
| int getIntValue32() const throw() { return CharacterFunctions::getIntValue <int, CharPointer_UTF16> (*this); } | |||
| /** Parses this string as a 64-bit integer. */ | |||
| int64 getIntValue64() const throw() { return CharacterFunctions::getIntValue <int64, CharPointer_UTF16> (*this); } | |||
| /** Parses this string as a floating point double. */ | |||
| double getDoubleValue() const throw() { return CharacterFunctions::getDoubleValue (*this); } | |||
| /** Returns the first non-whitespace character in the string. */ | |||
| CharPointer_UTF16 findEndOfWhitespace() const throw() { return CharacterFunctions::findEndOfWhitespace (*this); } | |||
| private: | |||
| CharType* data; | |||
| static int findNullIndex (const CharType* const t) throw() | |||
| { | |||
| int n = 0; | |||
| while (t[n] != 0) | |||
| ++n; | |||
| return n; | |||
| } | |||
| }; | |||
| #endif // __JUCE_CHARPOINTER_UTF16_JUCEHEADER__ | |||
| @@ -0,0 +1,340 @@ | |||
| /* | |||
| ============================================================================== | |||
| 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. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_CHARPOINTER_UTF32_JUCEHEADER__ | |||
| #define __JUCE_CHARPOINTER_UTF32_JUCEHEADER__ | |||
| //============================================================================== | |||
| /** | |||
| Wraps a pointer to a null-terminated UTF-32 character string, and provides | |||
| various methods to operate on the data. | |||
| @see CharPointer_UTF8, CharPointer_UTF16 | |||
| */ | |||
| class CharPointer_UTF32 | |||
| { | |||
| public: | |||
| typedef juce_wchar CharType; | |||
| inline CharPointer_UTF32 (const CharType* const rawPointer) throw() | |||
| : data (const_cast <CharType*> (rawPointer)) | |||
| { | |||
| } | |||
| inline CharPointer_UTF32 (const CharPointer_UTF32& other) throw() | |||
| : data (other.data) | |||
| { | |||
| } | |||
| inline CharPointer_UTF32& operator= (const CharPointer_UTF32& other) throw() | |||
| { | |||
| data = other.data; | |||
| return *this; | |||
| } | |||
| /** Returns the address that this pointer is pointing to. */ | |||
| inline CharType* getAddress() const throw() { return data; } | |||
| /** Returns true if this pointer is pointing to a null character. */ | |||
| inline bool isEmpty() const throw() { return *data == 0; } | |||
| /** Returns the unicode character that this pointer is pointing to. */ | |||
| inline juce_wchar operator*() const throw() { return *data; } | |||
| /** Moves this pointer along to the next character in the string. */ | |||
| inline CharPointer_UTF32& operator++() throw() | |||
| { | |||
| ++data; | |||
| return *this; | |||
| } | |||
| /** Moves this pointer to the previous character in the string. */ | |||
| inline CharPointer_UTF32& operator--() throw() | |||
| { | |||
| --data; | |||
| return *this; | |||
| } | |||
| /** Returns the character that this pointer is currently pointing to, and then | |||
| advances the pointer to point to the next character. */ | |||
| inline juce_wchar getAndAdvance() throw() { return *data++; } | |||
| /** Moves this pointer along to the next character in the string. */ | |||
| CharPointer_UTF32 operator++ (int) throw() | |||
| { | |||
| CharPointer_UTF32 temp (*this); | |||
| ++*this; | |||
| return temp; | |||
| } | |||
| /** Moves this pointer forwards by the specified number of characters. */ | |||
| inline void operator+= (int numToSkip) throw() | |||
| { | |||
| data += numToSkip; | |||
| } | |||
| inline void operator-= (int numToSkip) throw() | |||
| { | |||
| data -= numToSkip; | |||
| } | |||
| /** Returns the character at a given character index from the start of the string. */ | |||
| inline juce_wchar operator[] (int characterIndex) const throw() | |||
| { | |||
| return data [characterIndex]; | |||
| } | |||
| /** Returns a pointer which is moved forwards from this one by the specified number of characters. */ | |||
| CharPointer_UTF32 operator+ (int numToSkip) const throw() | |||
| { | |||
| return CharPointer_UTF32 (data + numToSkip); | |||
| } | |||
| /** Returns a pointer which is moved backwards from this one by the specified number of characters. */ | |||
| CharPointer_UTF32 operator- (int numToSkip) const throw() | |||
| { | |||
| return CharPointer_UTF32 (data - numToSkip); | |||
| } | |||
| /** Writes a unicode character to this string, and advances this pointer to point to the next position. */ | |||
| inline void write (const juce_wchar charToWrite) throw() | |||
| { | |||
| *data++ = charToWrite; | |||
| } | |||
| /** Returns the number of characters in this string. */ | |||
| size_t length() const throw() | |||
| { | |||
| #if JUCE_ANDROID | |||
| size_t n = 0; | |||
| while (data[n] == 0) | |||
| ++n; | |||
| return n; | |||
| #else | |||
| return wcslen (data); | |||
| #endif | |||
| } | |||
| /** Returns the number of bytes that are used to represent this string. | |||
| This includes the terminating null character. | |||
| */ | |||
| size_t sizeInBytes() const throw() | |||
| { | |||
| return sizeof (CharType) * (length() + 1); | |||
| } | |||
| /** Returns the number of bytes that would be needed to represent the given | |||
| unicode character in this encoding format. | |||
| */ | |||
| static inline size_t getBytesRequiredFor (const juce_wchar) throw() | |||
| { | |||
| return sizeof (CharType); | |||
| } | |||
| /** Returns the number of bytes that would be needed to represent the given | |||
| string in this encoding format. | |||
| The value returned does NOT include the terminating null character. | |||
| */ | |||
| template <class CharPointer> | |||
| static size_t getBytesRequiredFor (const CharPointer& text) throw() | |||
| { | |||
| return sizeof (CharType) * text.length(); | |||
| } | |||
| /** Returns a pointer to the null character that terminates this string. */ | |||
| CharPointer_UTF32 findTerminatingNull() const throw() | |||
| { | |||
| return CharPointer_UTF32 (data + length()); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. */ | |||
| template <typename CharPointer> | |||
| void copyAndAdvance (const CharPointer& src) throw() | |||
| { | |||
| CharacterFunctions::copyAndAdvance (*this, src); | |||
| } | |||
| #if ! JUCE_ANDROID | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. */ | |||
| void copyAndAdvance (const CharPointer_UTF32& src) throw() | |||
| { | |||
| data = wcscpy (data, src.data); | |||
| } | |||
| #endif | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. | |||
| The maxBytes parameter specifies the maximum number of bytes that can be written | |||
| to the destination buffer before stopping. | |||
| */ | |||
| template <typename CharPointer> | |||
| int copyAndAdvanceUpToBytes (const CharPointer& src, int maxBytes) throw() | |||
| { | |||
| return CharacterFunctions::copyAndAdvanceUpToBytes (*this, src, maxBytes); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. | |||
| The maxChars parameter specifies the maximum number of characters that can be | |||
| written to the destination buffer before stopping (including the terminating null). | |||
| */ | |||
| template <typename CharPointer> | |||
| void copyAndAdvanceUpToNumChars (const CharPointer& src, int maxChars) throw() | |||
| { | |||
| CharacterFunctions::copyAndAdvanceUpToNumChars (*this, src, maxChars); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| template <typename CharPointer> | |||
| int compare (const CharPointer& other) const throw() | |||
| { | |||
| return CharacterFunctions::compare (*this, other); | |||
| } | |||
| #if ! JUCE_ANDROID | |||
| /** Compares this string with another one. */ | |||
| int compare (const CharPointer_UTF32& other) const throw() | |||
| { | |||
| return wcscmp (data, other.data); | |||
| } | |||
| #endif | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| template <typename CharPointer> | |||
| int compareUpTo (const CharPointer& other, int maxChars) const throw() | |||
| { | |||
| return CharacterFunctions::compareUpTo (*this, other, maxChars); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| template <typename CharPointer> | |||
| int compareIgnoreCase (const CharPointer& other) const | |||
| { | |||
| return CharacterFunctions::compareIgnoreCase (*this, other); | |||
| } | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| template <typename CharPointer> | |||
| int compareIgnoreCaseUpTo (const CharPointer& other, int maxChars) const throw() | |||
| { | |||
| return CharacterFunctions::compareIgnoreCaseUpTo (*this, other, maxChars); | |||
| } | |||
| /** Returns the character index of a substring, or -1 if it isn't found. */ | |||
| template <typename CharPointer> | |||
| int indexOf (const CharPointer& stringToFind) const throw() | |||
| { | |||
| return CharacterFunctions::indexOf (*this, stringToFind); | |||
| } | |||
| /** Returns the character index of a unicode character, or -1 if it isn't found. */ | |||
| int indexOf (const juce_wchar charToFind) const throw() | |||
| { | |||
| int i = 0; | |||
| while (data[i] != 0) | |||
| { | |||
| if (data[i] == charToFind) | |||
| return i; | |||
| ++i; | |||
| } | |||
| return -1; | |||
| } | |||
| /** Returns the character index of a unicode character, or -1 if it isn't found. */ | |||
| int indexOf (const juce_wchar charToFind, const bool ignoreCase) const throw() | |||
| { | |||
| return ignoreCase ? CharacterFunctions::indexOfCharIgnoreCase (*this, charToFind) | |||
| : CharacterFunctions::indexOfChar (*this, charToFind); | |||
| } | |||
| #if JUCE_WINDOWS && ! DOXYGEN | |||
| int compareIgnoreCase (const CharPointer_UTF32& other) const throw() | |||
| { | |||
| return _wcsicmp (data, other.data); | |||
| } | |||
| int compareIgnoreCaseUpTo (const CharPointer_UTF32& other, int maxChars) const throw() | |||
| { | |||
| return _wcsnicmp (data, other.data, maxChars); | |||
| } | |||
| int indexOf (const CharPointer_UTF32& stringToFind) const throw() | |||
| { | |||
| const CharType* const t = wcsstr (data, stringToFind.getAddress()); | |||
| return t == 0 ? -1 : (t - data); | |||
| } | |||
| #endif | |||
| /** Returns true if the first character of this string is whitespace. */ | |||
| bool isWhitespace() const { return CharacterFunctions::isWhitespace (*data) != 0; } | |||
| /** Returns true if the first character of this string is a digit. */ | |||
| bool isDigit() const { return CharacterFunctions::isDigit (*data) != 0; } | |||
| /** Returns true if the first character of this string is a letter. */ | |||
| bool isLetter() const { return CharacterFunctions::isLetter (*data) != 0; } | |||
| /** Returns true if the first character of this string is a letter or digit. */ | |||
| bool isLetterOrDigit() const { return CharacterFunctions::isLetterOrDigit (*data) != 0; } | |||
| /** Returns true if the first character of this string is upper-case. */ | |||
| bool isUpperCase() const { return CharacterFunctions::isUpperCase (*data) != 0; } | |||
| /** Returns true if the first character of this string is lower-case. */ | |||
| bool isLowerCase() const { return CharacterFunctions::isLowerCase (*data) != 0; } | |||
| /** Returns an upper-case version of the first character of this string. */ | |||
| juce_wchar toUpperCase() const throw() { return CharacterFunctions::toUpperCase (*data); } | |||
| /** Returns a lower-case version of the first character of this string. */ | |||
| juce_wchar toLowerCase() const throw() { return CharacterFunctions::toLowerCase (*data); } | |||
| /** Parses this string as a 32-bit integer. */ | |||
| int getIntValue32() const throw() | |||
| { | |||
| #if JUCE_WINDOWS | |||
| return _wtoi (data); | |||
| #else | |||
| return CharacterFunctions::getIntValue <int, CharPointer_UTF32> (*this); | |||
| #endif | |||
| } | |||
| /** Parses this string as a 64-bit integer. */ | |||
| int64 getIntValue64() const throw() | |||
| { | |||
| #if JUCE_WINDOWS | |||
| return _wtoi64 (data); | |||
| #else | |||
| return CharacterFunctions::getIntValue <int64, CharPointer_UTF32> (*this); | |||
| #endif | |||
| } | |||
| /** Parses this string as a floating point double. */ | |||
| double getDoubleValue() const throw() { return CharacterFunctions::getDoubleValue (*this); } | |||
| /** Returns the first non-whitespace character in the string. */ | |||
| CharPointer_UTF32 findEndOfWhitespace() const throw() { return CharacterFunctions::findEndOfWhitespace (*this); } | |||
| private: | |||
| CharType* data; | |||
| }; | |||
| #endif // __JUCE_CHARPOINTER_UTF32_JUCEHEADER__ | |||
| @@ -0,0 +1,441 @@ | |||
| /* | |||
| ============================================================================== | |||
| 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. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_CHARPOINTER_UTF8_JUCEHEADER__ | |||
| #define __JUCE_CHARPOINTER_UTF8_JUCEHEADER__ | |||
| //============================================================================== | |||
| /** | |||
| Wraps a pointer to a null-terminated UTF-8 character string, and provides | |||
| various methods to operate on the data. | |||
| @see CharPointer_UTF16, CharPointer_UTF32 | |||
| */ | |||
| class CharPointer_UTF8 | |||
| { | |||
| public: | |||
| typedef char CharType; | |||
| inline CharPointer_UTF8 (const CharType* const rawPointer) throw() | |||
| : data (const_cast <CharType*> (rawPointer)) | |||
| { | |||
| } | |||
| inline CharPointer_UTF8 (const CharPointer_UTF8& other) throw() | |||
| : data (other.data) | |||
| { | |||
| } | |||
| inline CharPointer_UTF8& operator= (const CharPointer_UTF8& other) throw() | |||
| { | |||
| data = other.data; | |||
| return *this; | |||
| } | |||
| /** Returns the address that this pointer is pointing to. */ | |||
| inline CharType* getAddress() const throw() { return data; } | |||
| /** Returns true if this pointer is pointing to a null character. */ | |||
| inline bool isEmpty() const throw() { return *data == 0; } | |||
| /** Returns the unicode character that this pointer is pointing to. */ | |||
| juce_wchar operator*() const throw() | |||
| { | |||
| const char byte = *data; | |||
| if (byte >= 0) | |||
| return byte; | |||
| juce_wchar n = byte; | |||
| juce_wchar mask = 0x7f; | |||
| juce_wchar bit = 0x40; | |||
| size_t numExtraValues = 0; | |||
| while ((n & bit) != 0 && bit > 0x10) | |||
| { | |||
| mask >>= 1; | |||
| ++numExtraValues; | |||
| bit >>= 1; | |||
| } | |||
| n &= mask; | |||
| for (size_t i = 1; i <= numExtraValues; ++i) | |||
| { | |||
| const juce_wchar nextByte = data [i]; | |||
| if ((nextByte & 0xc0) != 0x80) | |||
| break; | |||
| n <<= 6; | |||
| n |= (nextByte & 0x3f); | |||
| } | |||
| return n; | |||
| } | |||
| /** Moves this pointer along to the next character in the string. */ | |||
| CharPointer_UTF8& operator++() throw() | |||
| { | |||
| const char n = *data++; | |||
| if (n < 0) | |||
| { | |||
| juce_wchar bit = 0x40; | |||
| while ((n & bit) != 0 && bit > 0x10) | |||
| { | |||
| ++data; | |||
| bit >>= 1; | |||
| } | |||
| } | |||
| return *this; | |||
| } | |||
| /** Returns the character that this pointer is currently pointing to, and then | |||
| advances the pointer to point to the next character. */ | |||
| juce_wchar getAndAdvance() throw() | |||
| { | |||
| const char byte = *data++; | |||
| if (byte >= 0) | |||
| return byte; | |||
| uint32 n = (uint32) (uint8) byte; | |||
| uint32 mask = 0x7f; | |||
| uint32 bit = 0x40; | |||
| int numExtraValues = 0; | |||
| while ((n & bit) != 0 && bit > 0x10) | |||
| { | |||
| mask >>= 1; | |||
| ++numExtraValues; | |||
| bit >>= 1; | |||
| } | |||
| n &= mask; | |||
| while (--numExtraValues >= 0) | |||
| { | |||
| const uint32 nextByte = (uint32) (uint8) *data++; | |||
| if ((nextByte & 0xc0) != 0x80) | |||
| break; | |||
| n <<= 6; | |||
| n |= (nextByte & 0x3f); | |||
| } | |||
| return (juce_wchar) n; | |||
| } | |||
| /** Moves this pointer along to the next character in the string. */ | |||
| CharPointer_UTF8 operator++ (int) throw() | |||
| { | |||
| CharPointer_UTF8 temp (*this); | |||
| ++*this; | |||
| return temp; | |||
| } | |||
| /** Moves this pointer forwards by the specified number of characters. */ | |||
| void operator+= (int numToSkip) throw() | |||
| { | |||
| jassert (numToSkip >= 0); | |||
| while (--numToSkip >= 0) | |||
| ++*this; | |||
| } | |||
| /** Returns the character at a given character index from the start of the string. */ | |||
| juce_wchar operator[] (int characterIndex) const throw() | |||
| { | |||
| CharPointer_UTF8 p (*this); | |||
| p += characterIndex; | |||
| return *p; | |||
| } | |||
| /** Returns a pointer which is moved forwards from this one by the specified number of characters. */ | |||
| CharPointer_UTF8 operator+ (int numToSkip) const throw() | |||
| { | |||
| CharPointer_UTF8 p (*this); | |||
| p += numToSkip; | |||
| return p; | |||
| } | |||
| /** Writes a unicode character to this string, and advances this pointer to point to the next position. */ | |||
| void write (const juce_wchar charToWrite) throw() | |||
| { | |||
| const uint32 c = (uint32) charToWrite; | |||
| if (c >= 0x80) | |||
| { | |||
| int numExtraBytes = 1; | |||
| if (c >= 0x800) | |||
| { | |||
| ++numExtraBytes; | |||
| if (c >= 0x10000) | |||
| ++numExtraBytes; | |||
| } | |||
| *data++ = (CharType) ((0xff << (7 - numExtraBytes)) | (c >> (numExtraBytes * 6))); | |||
| while (--numExtraBytes >= 0) | |||
| *data++ = (CharType) (0x80 | (0x3f & (c >> (numExtraBytes * 6)))); | |||
| } | |||
| else | |||
| { | |||
| *data++ = (CharType) c; | |||
| } | |||
| } | |||
| /** Returns the number of characters in this string. */ | |||
| size_t length() const throw() | |||
| { | |||
| const CharType* d = data; | |||
| size_t count = 0; | |||
| for (;;) | |||
| { | |||
| const int n = *d++; | |||
| if ((n & 0x80) != 0) | |||
| { | |||
| int bit = 0x40; | |||
| while ((n & bit) != 0) | |||
| { | |||
| ++d; | |||
| bit >>= 1; | |||
| if (bit == 0) | |||
| break; // illegal utf-8 sequence | |||
| } | |||
| } | |||
| else if (n == 0) | |||
| break; | |||
| ++count; | |||
| } | |||
| return count; | |||
| } | |||
| /** Returns the number of bytes that are used to represent this string. | |||
| This includes the terminating null character. | |||
| */ | |||
| size_t sizeInBytes() const throw() | |||
| { | |||
| return strlen (data) + 1; | |||
| } | |||
| /** Returns the number of bytes that would be needed to represent the given | |||
| unicode character in this encoding format. | |||
| */ | |||
| static size_t getBytesRequiredFor (const juce_wchar charToWrite) throw() | |||
| { | |||
| size_t num = 1; | |||
| const uint32 c = (uint32) charToWrite; | |||
| if (c >= 0x80) | |||
| { | |||
| ++num; | |||
| if (c >= 0x800) | |||
| { | |||
| ++num; | |||
| if (c >= 0x10000) | |||
| ++num; | |||
| } | |||
| } | |||
| return num; | |||
| } | |||
| /** Returns the number of bytes that would be needed to represent the given | |||
| string in this encoding format. | |||
| The value returned does NOT include the terminating null character. | |||
| */ | |||
| template <class CharPointer> | |||
| static size_t getBytesRequiredFor (CharPointer text) throw() | |||
| { | |||
| size_t count = 0; | |||
| juce_wchar n; | |||
| while ((n = text.getAndAdvance()) != 0) | |||
| count += getBytesRequiredFor (n); | |||
| return count; | |||
| } | |||
| /** Returns a pointer to the null character that terminates this string. */ | |||
| CharPointer_UTF8 findTerminatingNull() const throw() | |||
| { | |||
| return CharPointer_UTF8 (data + strlen (data)); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. */ | |||
| template <typename CharPointer> | |||
| void copyAndAdvance (const CharPointer& src) throw() | |||
| { | |||
| CharacterFunctions::copyAndAdvance (*this, src); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. */ | |||
| void copyAndAdvance (const CharPointer_UTF8& src) throw() | |||
| { | |||
| data = (CharType*) strcpy ((char*) data, src.data); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. | |||
| The maxBytes parameter specifies the maximum number of bytes that can be written | |||
| to the destination buffer before stopping. | |||
| */ | |||
| template <typename CharPointer> | |||
| int copyAndAdvanceUpToBytes (const CharPointer& src, int maxBytes) throw() | |||
| { | |||
| return CharacterFunctions::copyAndAdvanceUpToBytes (*this, src, maxBytes); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. | |||
| The maxChars parameter specifies the maximum number of characters that can be | |||
| written to the destination buffer before stopping (including the terminating null). | |||
| */ | |||
| template <typename CharPointer> | |||
| void copyAndAdvanceUpToNumChars (const CharPointer& src, int maxChars) throw() | |||
| { | |||
| CharacterFunctions::copyAndAdvanceUpToNumChars (*this, src, maxChars); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| template <typename CharPointer> | |||
| int compare (const CharPointer& other) const throw() | |||
| { | |||
| return CharacterFunctions::compare (*this, other); | |||
| } | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| template <typename CharPointer> | |||
| int compareUpTo (const CharPointer& other, int maxChars) const throw() | |||
| { | |||
| return CharacterFunctions::compareUpTo (*this, other, maxChars); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| template <typename CharPointer> | |||
| int compareIgnoreCase (const CharPointer& other) const throw() | |||
| { | |||
| return CharacterFunctions::compareIgnoreCase (*this, other); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| int compareIgnoreCase (const CharPointer_UTF8& other) const throw() | |||
| { | |||
| #if JUCE_WINDOWS | |||
| return stricmp (data, other.data); | |||
| #else | |||
| return strcasecmp (data, other.data); | |||
| #endif | |||
| } | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| template <typename CharPointer> | |||
| int compareIgnoreCaseUpTo (const CharPointer& other, int maxChars) const throw() | |||
| { | |||
| return CharacterFunctions::compareIgnoreCaseUpTo (*this, other, maxChars); | |||
| } | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| int compareIgnoreCaseUpTo (const CharPointer_UTF8& other, int maxChars) const throw() | |||
| { | |||
| #if JUCE_WINDOWS | |||
| return strnicmp (data, other.data, maxChars); | |||
| #else | |||
| return strncasecmp (data, other.data, maxChars); | |||
| #endif | |||
| } | |||
| /** Returns the character index of a substring, or -1 if it isn't found. */ | |||
| template <typename CharPointer> | |||
| int indexOf (const CharPointer& stringToFind) const throw() | |||
| { | |||
| return CharacterFunctions::indexOf (*this, stringToFind); | |||
| } | |||
| /** Returns the character index of a unicode character, or -1 if it isn't found. */ | |||
| int indexOf (const juce_wchar charToFind) const throw() | |||
| { | |||
| return CharacterFunctions::indexOfChar (*this, charToFind); | |||
| } | |||
| /** Returns the character index of a unicode character, or -1 if it isn't found. */ | |||
| int indexOf (const juce_wchar charToFind, const bool ignoreCase) const throw() | |||
| { | |||
| return ignoreCase ? CharacterFunctions::indexOfCharIgnoreCase (*this, charToFind) | |||
| : CharacterFunctions::indexOfChar (*this, charToFind); | |||
| } | |||
| /** Returns true if the first character of this string is whitespace. */ | |||
| bool isWhitespace() const throw() { return *data == ' ' || (*data <= 13 && *data >= 9); } | |||
| /** Returns true if the first character of this string is a digit. */ | |||
| bool isDigit() const throw() { return *data >= '0' && *data <= '9'; } | |||
| /** Returns true if the first character of this string is a letter. */ | |||
| bool isLetter() const throw() { return CharacterFunctions::isLetter (operator*()) != 0; } | |||
| /** Returns true if the first character of this string is a letter or digit. */ | |||
| bool isLetterOrDigit() const throw() { return CharacterFunctions::isLetterOrDigit (operator*()) != 0; } | |||
| /** Returns true if the first character of this string is upper-case. */ | |||
| bool isUpperCase() const throw() { return CharacterFunctions::isUpperCase (operator*()) != 0; } | |||
| /** Returns true if the first character of this string is lower-case. */ | |||
| bool isLowerCase() const throw() { return CharacterFunctions::isLowerCase (operator*()) != 0; } | |||
| /** Returns an upper-case version of the first character of this string. */ | |||
| juce_wchar toUpperCase() const throw() { return CharacterFunctions::toUpperCase (operator*()); } | |||
| /** Returns a lower-case version of the first character of this string. */ | |||
| juce_wchar toLowerCase() const throw() { return CharacterFunctions::toLowerCase (operator*()); } | |||
| /** Parses this string as a 32-bit integer. */ | |||
| int getIntValue32() const throw() { return atoi (data); } | |||
| /** Parses this string as a 64-bit integer. */ | |||
| int64 getIntValue64() const throw() | |||
| { | |||
| #if JUCE_LINUX || JUCE_ANDROID | |||
| return atoll (data); | |||
| #elif JUCE_WINDOWS | |||
| return _atoi64 (data); | |||
| #else | |||
| return CharacterFunctions::getIntValue <int64, CharPointer_UTF8> (*this); | |||
| #endif | |||
| } | |||
| /** Parses this string as a floating point double. */ | |||
| double getDoubleValue() const throw() { return CharacterFunctions::getDoubleValue (*this); } | |||
| /** Returns the first non-whitespace character in the string. */ | |||
| CharPointer_UTF8 findEndOfWhitespace() const throw() { return CharacterFunctions::findEndOfWhitespace (*this); } | |||
| private: | |||
| CharType* data; | |||
| }; | |||
| #endif // __JUCE_CHARPOINTER_UTF8_JUCEHEADER__ | |||
| @@ -30,712 +30,44 @@ | |||
| #pragma warning (disable: 4514 4996) | |||
| #endif | |||
| #include <cwctype> | |||
| #if ! JUCE_ANDROID | |||
| #include <cwctype> | |||
| #endif | |||
| #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 | |||
| } | |||
| //============================================================================== | |||
| namespace | |||
| { | |||
| 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() | |||
| juce_wchar CharacterFunctions::toLowerCase (const juce_wchar character) throw() | |||
| { | |||
| return isupper (character) != 0; | |||
| return towlower (character); | |||
| } | |||
| bool CharacterFunctions::isUpperCase (const juce_wchar character) throw() | |||
| { | |||
| #if JUCE_WINDOWS | |||
| #if JUCE_WINDOWS | |||
| return iswupper (character) != 0; | |||
| #else | |||
| #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; | |||
| #endif | |||
| } | |||
| bool CharacterFunctions::isLowerCase (const juce_wchar character) throw() | |||
| { | |||
| #if JUCE_WINDOWS | |||
| #if JUCE_WINDOWS | |||
| return iswlower (character) != 0; | |||
| #else | |||
| #else | |||
| return toUpperCase (character) != character; | |||
| #endif | |||
| #endif | |||
| } | |||
| //============================================================================== | |||
| @@ -799,8 +131,55 @@ int CharacterFunctions::getHexDigitValue (const juce_wchar digit) throw() | |||
| return -1; | |||
| } | |||
| 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() | |||
| { | |||
| #if JUCE_ANDROID | |||
| HeapBlock <char> tempDest; | |||
| tempDest.calloc (maxChars + 2); | |||
| int result = ftime (tempDest.getData(), maxChars, String (format).toUTF8(), tm); | |||
| CharPointer_UTF32 (dest).copyAndAdvance (CharPointer_UTF8 (tempDest.getData())); | |||
| return result; | |||
| #else | |||
| return (int) wcsftime (dest, maxChars, format, tm); | |||
| #endif | |||
| } | |||
| #if JUCE_MSVC | |||
| #pragma warning (pop) | |||
| #endif | |||
| double CharacterFunctions::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); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -28,30 +28,35 @@ | |||
| //============================================================================== | |||
| #define JUCE_T(stringLiteral) (L##stringLiteral) | |||
| typedef juce_wchar tchar; | |||
| #if JUCE_ANDROID && ! DOXYGEN | |||
| typedef uint32 juce_wchar; | |||
| #define JUCE_T(stringLiteral) CharPointer_UTF8 (stringLiteral) | |||
| #else | |||
| /** A platform-independent unicode character type. */ | |||
| typedef wchar_t juce_wchar; | |||
| #define JUCE_T(stringLiteral) (L##stringLiteral) | |||
| #endif | |||
| #if ! JUCE_DONT_DEFINE_MACROS | |||
| /** The 'T' macro allows a literal string to be compiled as unicode. | |||
| /** The 'T' macro allows a literal string to be compiled as unicode. | |||
| If you write your string literals in the form T("xyz"), it will be compiled as L"xyz" | |||
| or "xyz", depending on which representation is best for the String class to work with. | |||
| Because the 'T' symbol is occasionally used inside 3rd-party library headers which you | |||
| may need to include after juce.h, you can use the juce_withoutMacros.h file (in | |||
| the juce/src directory) to avoid defining this macro. See the comments in | |||
| juce_withoutMacros.h for more info. | |||
| */ | |||
| #define T(stringLiteral) JUCE_T(stringLiteral) | |||
| If you write your string literals in the form T("xyz"), it will be compiled as L"xyz" | |||
| or "xyz", depending on which representation is best for the String class to work with. | |||
| Because the 'T' symbol is occasionally used inside 3rd-party library headers which you | |||
| may need to include after juce.h, you can use the juce_withoutMacros.h file (in | |||
| the juce/src directory) to avoid defining this macro. See the comments in | |||
| juce_withoutMacros.h for more info. | |||
| */ | |||
| #define T(stringLiteral) JUCE_T(stringLiteral) | |||
| #endif | |||
| #undef max | |||
| #undef min | |||
| //============================================================================== | |||
| /** | |||
| A set of methods for manipulating characters and character strings, with | |||
| duplicate methods to handle 8-bit and unicode characters. | |||
| A set of methods for manipulating characters and character strings. | |||
| These are defined as wrappers around the basic C string handlers, to provide | |||
| a clean, cross-platform layer, (because various platforms differ in the | |||
| @@ -62,75 +67,13 @@ typedef juce_wchar tchar; | |||
| class JUCE_API CharacterFunctions | |||
| { | |||
| public: | |||
| static int length (const char* s) throw(); | |||
| static int length (const juce_wchar* s) throw(); | |||
| static void copy (char* dest, const char* src, int maxBytes) throw(); | |||
| static void copy (juce_wchar* dest, const juce_wchar* src, int maxChars) throw(); | |||
| static void copy (juce_wchar* dest, const char* src, int maxChars) throw(); | |||
| static void copy (char* dest, const juce_wchar* src, int maxBytes) throw(); | |||
| static int bytesRequiredForCopy (const juce_wchar* src) throw(); | |||
| static void append (char* dest, const char* src) throw(); | |||
| static void append (juce_wchar* dest, const juce_wchar* src) throw(); | |||
| static int compare (const char* s1, const char* s2) throw(); | |||
| static int compare (const juce_wchar* s1, const juce_wchar* s2) throw(); | |||
| static int compare (const juce_wchar* s1, const char* s2) throw(); | |||
| static int compare (const char* s1, const juce_wchar* s2) throw(); | |||
| static int compare (const char* s1, const char* s2, int maxChars) throw(); | |||
| static int compare (const juce_wchar* s1, const juce_wchar* s2, int maxChars) throw(); | |||
| static int compareIgnoreCase (const char* s1, const char* s2) throw(); | |||
| static int compareIgnoreCase (const juce_wchar* s1, const juce_wchar* s2) throw(); | |||
| static int compareIgnoreCase (const juce_wchar* s1, const char* s2) throw(); | |||
| static int compareIgnoreCase (const char* s1, const char* s2, int maxChars) throw(); | |||
| static int compareIgnoreCase (const juce_wchar* s1, const juce_wchar* s2, int maxChars) throw(); | |||
| static const char* find (const char* haystack, const char* needle) throw(); | |||
| static const juce_wchar* find (const juce_wchar* haystack, const juce_wchar* needle) throw(); | |||
| static int indexOfChar (const char* haystack, char needle, bool ignoreCase) throw(); | |||
| static int indexOfChar (const juce_wchar* haystack, juce_wchar needle, bool ignoreCase) throw(); | |||
| static int indexOfCharFast (const char* haystack, char needle) throw(); | |||
| static int indexOfCharFast (const juce_wchar* haystack, juce_wchar needle) throw(); | |||
| static int getIntialSectionContainingOnly (const char* text, const char* allowedChars) throw(); | |||
| static int getIntialSectionContainingOnly (const juce_wchar* text, const juce_wchar* allowedChars) throw(); | |||
| static int ftime (char* dest, int maxChars, const char* format, const struct tm* tm) throw(); | |||
| static int ftime (juce_wchar* dest, int maxChars, const juce_wchar* format, const struct tm* tm) throw(); | |||
| static int getIntValue (const char* s) throw(); | |||
| static int getIntValue (const juce_wchar* s) throw(); | |||
| static int64 getInt64Value (const char* s) throw(); | |||
| static int64 getInt64Value (const juce_wchar* s) throw(); | |||
| static double getDoubleValue (const char* s) throw(); | |||
| static double getDoubleValue (const juce_wchar* s) throw(); | |||
| //============================================================================== | |||
| static char toUpperCase (char character) throw(); | |||
| static juce_wchar toUpperCase (juce_wchar character) throw(); | |||
| static void toUpperCase (char* s) throw(); | |||
| static juce_wchar toLowerCase (juce_wchar character) throw(); | |||
| static void toUpperCase (juce_wchar* s) throw(); | |||
| static bool isUpperCase (char character) throw(); | |||
| static bool isUpperCase (juce_wchar character) throw(); | |||
| static char toLowerCase (char character) throw(); | |||
| static juce_wchar toLowerCase (juce_wchar character) throw(); | |||
| static void toLowerCase (char* s) throw(); | |||
| static void toLowerCase (juce_wchar* s) throw(); | |||
| static bool isLowerCase (char character) throw(); | |||
| static bool isLowerCase (juce_wchar character) throw(); | |||
| //============================================================================== | |||
| static bool isWhitespace (char character) throw(); | |||
| static bool isWhitespace (juce_wchar character) throw(); | |||
| @@ -143,10 +86,359 @@ public: | |||
| static bool isLetterOrDigit (char character) throw(); | |||
| static bool isLetterOrDigit (juce_wchar character) throw(); | |||
| /** Returns 0 to 16 for '0' to 'F", or -1 for characters that aren't a legel | |||
| hex digit. | |||
| */ | |||
| /** Returns 0 to 16 for '0' to 'F", or -1 for characters that aren't a legal hex digit. */ | |||
| static int getHexDigitValue (juce_wchar digit) throw(); | |||
| //============================================================================== | |||
| template <typename CharPointerType> | |||
| static double getDoubleValue (const CharPointerType& text) 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; | |||
| CharPointerType s (text.findEndOfWhitespace()); | |||
| juce_wchar c = *s; | |||
| switch (c) | |||
| { | |||
| case '-': isNegative = true; // fall-through.. | |||
| case '+': c = *++s; | |||
| } | |||
| switch (c) | |||
| { | |||
| case 'n': | |||
| case 'N': | |||
| if ((s[1] == 'a' || s[1] == 'A') && (s[2] == 'n' || s[2] == 'N')) | |||
| return std::numeric_limits<double>::quiet_NaN(); | |||
| break; | |||
| case 'i': | |||
| case 'I': | |||
| if ((s[1] == 'n' || s[1] == 'N') && (s[2] == 'f' || s[2] == 'F')) | |||
| return std::numeric_limits<double>::infinity(); | |||
| break; | |||
| } | |||
| for (;;) | |||
| { | |||
| if (s.isDigit()) | |||
| { | |||
| lastDigit = digit; | |||
| digit = s.getAndAdvance() - '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 (s.isDigit()) | |||
| { | |||
| ++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] = 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 (s.isDigit()) | |||
| ++s; | |||
| break; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| break; | |||
| } | |||
| } | |||
| result[0] = mulexp10 (result[0], exponentAccumulator[0]) + accumulator[0]; | |||
| if (decPointIndex != 0) | |||
| result[1] = mulexp10 (result[1], exponentAccumulator[1]) + accumulator[1]; | |||
| c = *s; | |||
| if ((c == 'e' || c == 'E') && digitsFound) | |||
| { | |||
| bool negativeExponent = false; | |||
| switch (*++s) | |||
| { | |||
| case '-': negativeExponent = true; // fall-through.. | |||
| case '+': ++s; | |||
| } | |||
| while (s.isDigit()) | |||
| exponent = (exponent * 10) + (s.getAndAdvance() - '0'); | |||
| if (negativeExponent) | |||
| exponent = -exponent; | |||
| } | |||
| double r = mulexp10 (result[0], exponent + exponentAdjustment[0]); | |||
| if (decPointIndex != 0) | |||
| r += mulexp10 (result[1], exponent - exponentAdjustment[1]); | |||
| return isNegative ? -r : r; | |||
| } | |||
| //============================================================================== | |||
| template <typename IntType, typename CharPointerType> | |||
| static IntType getIntValue (const CharPointerType& text) throw() | |||
| { | |||
| IntType v = 0; | |||
| CharPointerType s (text.findEndOfWhitespace()); | |||
| const bool isNeg = *s == '-'; | |||
| if (isNeg) | |||
| ++s; | |||
| for (;;) | |||
| { | |||
| const juce_wchar c = s.getAndAdvance(); | |||
| if (c >= '0' && c <= '9') | |||
| v = v * 10 + (IntType) (c - '0'); | |||
| else | |||
| break; | |||
| } | |||
| return isNeg ? -v : v; | |||
| } | |||
| //============================================================================== | |||
| static int ftime (char* dest, int maxChars, const char* format, const struct tm* tm) throw(); | |||
| static int ftime (juce_wchar* dest, int maxChars, const juce_wchar* format, const struct tm* tm) throw(); | |||
| //============================================================================== | |||
| template <typename DestCharPointerType, typename SrcCharPointerType> | |||
| static void copyAndAdvance (DestCharPointerType& dest, SrcCharPointerType src) throw() | |||
| { | |||
| juce_wchar c; | |||
| do | |||
| { | |||
| c = src.getAndAdvance(); | |||
| dest.write (c); | |||
| } | |||
| while (c != 0); | |||
| } | |||
| template <typename DestCharPointerType, typename SrcCharPointerType> | |||
| static int copyAndAdvanceUpToBytes (DestCharPointerType& dest, SrcCharPointerType src, int maxBytes) throw() | |||
| { | |||
| int numBytesDone = 0; | |||
| for (;;) | |||
| { | |||
| const juce_wchar c = src.getAndAdvance(); | |||
| const size_t bytesNeeded = DestCharPointerType::getBytesRequiredFor (c); | |||
| maxBytes -= bytesNeeded; | |||
| if (maxBytes < 0) | |||
| break; | |||
| numBytesDone += bytesNeeded; | |||
| dest.write (c); | |||
| if (c == 0) | |||
| break; | |||
| } | |||
| return numBytesDone; | |||
| } | |||
| template <typename DestCharPointerType, typename SrcCharPointerType> | |||
| static void copyAndAdvanceUpToNumChars (DestCharPointerType& dest, SrcCharPointerType src, int maxChars) throw() | |||
| { | |||
| while (--maxChars >= 0) | |||
| { | |||
| const juce_wchar c = src.getAndAdvance(); | |||
| dest.write (c); | |||
| if (c == 0) | |||
| break; | |||
| } | |||
| } | |||
| template <typename CharPointerType1, typename CharPointerType2> | |||
| static int compare (CharPointerType1 s1, CharPointerType2 s2) throw() | |||
| { | |||
| for (;;) | |||
| { | |||
| const int c1 = (int) s1.getAndAdvance(); | |||
| const int c2 = (int) s2.getAndAdvance(); | |||
| const int diff = c1 - c2; | |||
| if (diff != 0) | |||
| return diff < 0 ? -1 : 1; | |||
| else if (c1 == 0) | |||
| break; | |||
| } | |||
| return 0; | |||
| } | |||
| template <typename CharPointerType1, typename CharPointerType2> | |||
| static int compareUpTo (CharPointerType1 s1, CharPointerType2 s2, int maxChars) throw() | |||
| { | |||
| while (--maxChars >= 0) | |||
| { | |||
| const int c1 = (int) s1.getAndAdvance(); | |||
| const int c2 = (int) s2.getAndAdvance(); | |||
| const int diff = c1 - c2; | |||
| if (diff != 0) | |||
| return diff < 0 ? -1 : 1; | |||
| else if (c1 == 0) | |||
| break; | |||
| } | |||
| return 0; | |||
| } | |||
| template <typename CharPointerType1, typename CharPointerType2> | |||
| static int compareIgnoreCase (CharPointerType1 s1, CharPointerType2 s2) throw() | |||
| { | |||
| for (;;) | |||
| { | |||
| int c1 = s1.toUpperCase(); | |||
| int c2 = s2.toUpperCase(); | |||
| ++s1; | |||
| ++s2; | |||
| const int diff = c1 - c2; | |||
| if (diff != 0) | |||
| return diff < 0 ? -1 : 1; | |||
| else if (c1 == 0) | |||
| break; | |||
| } | |||
| return 0; | |||
| } | |||
| template <typename CharPointerType1, typename CharPointerType2> | |||
| static int compareIgnoreCaseUpTo (CharPointerType1 s1, CharPointerType2 s2, int maxChars) throw() | |||
| { | |||
| while (--maxChars >= 0) | |||
| { | |||
| int c1 = s1.toUpperCase(); | |||
| int c2 = s2.toUpperCase(); | |||
| ++s1; | |||
| ++s2; | |||
| const int diff = c1 - c2; | |||
| if (diff != 0) | |||
| return diff < 0 ? -1 : 1; | |||
| else if (c1 == 0) | |||
| break; | |||
| } | |||
| return 0; | |||
| } | |||
| template <typename CharPointerType1, typename CharPointerType2> | |||
| static int indexOf (CharPointerType1 haystack, const CharPointerType2& needle) throw() | |||
| { | |||
| int index = 0; | |||
| const int needleLength = needle.length(); | |||
| for (;;) | |||
| { | |||
| if (haystack.compareUpTo (needle, needleLength) == 0) | |||
| return index; | |||
| if (haystack.getAndAdvance() == 0) | |||
| return -1; | |||
| ++index; | |||
| } | |||
| } | |||
| template <typename Type> | |||
| static int indexOfChar (Type text, const juce_wchar charToFind) throw() | |||
| { | |||
| int i = 0; | |||
| while (! text.isEmpty()) | |||
| { | |||
| if (text.getAndAdvance() == charToFind) | |||
| return i; | |||
| ++i; | |||
| } | |||
| return -1; | |||
| } | |||
| template <typename Type> | |||
| static int indexOfCharIgnoreCase (Type text, juce_wchar charToFind) throw() | |||
| { | |||
| charToFind = CharacterFunctions::toLowerCase (charToFind); | |||
| int i = 0; | |||
| while (! text.isEmpty()) | |||
| { | |||
| if (text.toLowerCase() == charToFind) | |||
| return i; | |||
| ++text; | |||
| ++i; | |||
| } | |||
| return -1; | |||
| } | |||
| template <typename Type> | |||
| static Type findEndOfWhitespace (const Type& text) throw() | |||
| { | |||
| Type p (text); | |||
| while (p.isWhitespace()) | |||
| ++p; | |||
| return p; | |||
| } | |||
| private: | |||
| static double mulexp10 (const double value, int exponent) throw(); | |||
| }; | |||
| #endif // __JUCE_CHARACTERFUNCTIONS_JUCEHEADER__ | |||
| @@ -27,6 +27,20 @@ | |||
| #define __JUCE_STRING_JUCEHEADER__ | |||
| #include "juce_CharacterFunctions.h" | |||
| #if JUCE_MSVC | |||
| #pragma warning (push) | |||
| #pragma warning (disable: 4514 4996) | |||
| #endif | |||
| #include "juce_CharPointer_UTF8.h" | |||
| #include "juce_CharPointer_UTF16.h" | |||
| #include "juce_CharPointer_UTF32.h" | |||
| #if JUCE_MSVC | |||
| #pragma warning (pop) | |||
| #endif | |||
| class OutputStream; | |||
| @@ -115,8 +129,6 @@ public: | |||
| String& operator+= (juce_wchar characterToAppend); | |||
| /** Appends a decimal number at the end of this string. */ | |||
| String& operator+= (int numberToAppend); | |||
| /** Appends a decimal number at the end of this string. */ | |||
| String& operator+= (unsigned int numberToAppend); | |||
| /** Appends a string at the end of this one. | |||
| @@ -963,7 +975,8 @@ public: | |||
| */ | |||
| const char* toCString() const; | |||
| /** Returns the number of bytes | |||
| /** Returns the number of bytes required to represent this string as C-string. | |||
| The number returned does NOT include the trailing zero. | |||
| */ | |||
| int getNumBytesAsCString() const throw(); | |||
| @@ -1054,6 +1067,7 @@ private: | |||
| void createInternal (const juce_wchar* text, size_t numChars); | |||
| void appendInternal (const juce_wchar* text, int numExtraChars); | |||
| void* createSpaceAtEndOfBuffer (size_t numExtraBytes) const; | |||
| // This private cast operator should prevent strings being accidentally cast | |||
| // to bools (this is possible because the compiler can add an implicit cast | |||
| @@ -1099,12 +1113,8 @@ JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, short number); | |||
| /** Appends a decimal number at the end of a string. */ | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, int number); | |||
| /** Appends a decimal number at the end of a string. */ | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, unsigned int number); | |||
| /** Appends a decimal number at the end of a string. */ | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, long number); | |||
| /** Appends a decimal number at the end of a string. */ | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, unsigned long number); | |||
| /** Appends a decimal number at the end of a string. */ | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, float number); | |||
| /** Appends a decimal number at the end of a string. */ | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, double number); | |||
| @@ -470,11 +470,13 @@ void StringArray::appendNumbersToDuplicates (const bool ignoreCase, | |||
| const juce_wchar* preNumberString, | |||
| const juce_wchar* postNumberString) | |||
| { | |||
| String defaultPre (" ("), defaultPost (")"); // (these aren't literals because of non-unicode literals on Android) | |||
| if (preNumberString == 0) | |||
| preNumberString = L" ("; | |||
| preNumberString = defaultPre; | |||
| if (postNumberString == 0) | |||
| postNumberString = L")"; | |||
| postNumberString = defaultPost; | |||
| for (int i = 0; i < size() - 1; ++i) | |||
| { | |||
| @@ -35,12 +35,14 @@ BEGIN_JUCE_NAMESPACE | |||
| //============================================================================== | |||
| XmlDocument::XmlDocument (const String& documentText) | |||
| : originalText (documentText), | |||
| input (0), | |||
| ignoreEmptyTextElements (true) | |||
| { | |||
| } | |||
| XmlDocument::XmlDocument (const File& file) | |||
| : ignoreEmptyTextElements (true), | |||
| : input (0), | |||
| ignoreEmptyTextElements (true), | |||
| inputSource (new FileInputSource (file)) | |||
| { | |||
| } | |||
| @@ -122,7 +124,7 @@ XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentEle | |||
| } | |||
| } | |||
| input = textToParse; | |||
| input = static_cast <const juce_wchar*> (textToParse); | |||
| lastError = String::empty; | |||
| errorOccurred = false; | |||
| outOfData = false; | |||
| @@ -136,7 +138,7 @@ XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentEle | |||
| { | |||
| skipHeader(); | |||
| if (input != 0) | |||
| if (input.getAddress() != 0) | |||
| { | |||
| ScopedPointer <XmlElement> result (readNextElement (! onlyReadOuterDocumentElement)); | |||
| @@ -198,18 +200,16 @@ int XmlDocument::findNextTokenLength() throw() | |||
| void XmlDocument::skipHeader() | |||
| { | |||
| const juce_wchar* const found = CharacterFunctions::find (input, JUCE_T("<?xml")); | |||
| const int headerStart = input.indexOf (CharPointer_UTF8 ("<?xml")); | |||
| if (found != 0) | |||
| if (headerStart >= 0) | |||
| { | |||
| input = found; | |||
| input = CharacterFunctions::find (input, JUCE_T("?>")); | |||
| if (input == 0) | |||
| const int headerEnd = (input + headerStart).indexOf (CharPointer_UTF8 ("?>")); | |||
| if (headerEnd < 0) | |||
| return; | |||
| #if JUCE_DEBUG | |||
| const String header (found, input - found); | |||
| const String header ((input + headerStart).getAddress(), headerEnd - headerStart); | |||
| const String encoding (header.fromFirstOccurrenceOf ("encoding", false, true) | |||
| .fromFirstOccurrenceOf ("=", false, false) | |||
| .fromFirstOccurrenceOf ("\"", false, false) | |||
| @@ -225,16 +225,17 @@ void XmlDocument::skipHeader() | |||
| jassert (encoding.isEmpty() || encoding.startsWithIgnoreCase ("utf-")); | |||
| #endif | |||
| input += 2; | |||
| input += headerEnd + 2; | |||
| } | |||
| skipNextWhiteSpace(); | |||
| const juce_wchar* docType = CharacterFunctions::find (input, JUCE_T("<!DOCTYPE")); | |||
| if (docType == 0) | |||
| const int docTypeIndex = input.indexOf (CharPointer_UTF8 ("<!DOCTYPE")); | |||
| if (docTypeIndex < 0) | |||
| return; | |||
| input = docType + 9; | |||
| input += docTypeIndex + 9; | |||
| const CharPointer_UTF32 docType (input); | |||
| int n = 1; | |||
| @@ -251,8 +252,7 @@ void XmlDocument::skipHeader() | |||
| --n; | |||
| } | |||
| docType += 9; | |||
| dtdText = String (docType, (int) (input - (docType + 1))).trim(); | |||
| dtdText = String (docType.getAddress(), (int) (input.getAddress() - (docType.getAddress() + 1))).trim(); | |||
| } | |||
| void XmlDocument::skipNextWhiteSpace() | |||
| @@ -275,28 +275,28 @@ void XmlDocument::skipNextWhiteSpace() | |||
| && input[2] == '-' | |||
| && input[3] == '-') | |||
| { | |||
| const juce_wchar* const closeComment = CharacterFunctions::find (input, JUCE_T("-->")); | |||
| const int closeComment = input.indexOf (CharPointer_UTF8 ("-->")); | |||
| if (closeComment == 0) | |||
| if (closeComment < 0) | |||
| { | |||
| outOfData = true; | |||
| break; | |||
| } | |||
| input = closeComment + 3; | |||
| input += closeComment + 3; | |||
| continue; | |||
| } | |||
| else if (input[1] == '?') | |||
| { | |||
| const juce_wchar* const closeBracket = CharacterFunctions::find (input, JUCE_T("?>")); | |||
| const int closeBracket = input.indexOf (CharPointer_UTF8 ("?>")); | |||
| if (closeBracket == 0) | |||
| if (closeBracket < 0) | |||
| { | |||
| outOfData = true; | |||
| break; | |||
| } | |||
| input = closeBracket + 2; | |||
| input += closeBracket + 2; | |||
| continue; | |||
| } | |||
| } | |||
| @@ -324,7 +324,7 @@ void XmlDocument::readQuotedString (String& result) | |||
| else | |||
| { | |||
| --input; | |||
| const juce_wchar* const start = input; | |||
| const CharPointer_UTF32 start (input); | |||
| for (;;) | |||
| { | |||
| @@ -332,14 +332,14 @@ void XmlDocument::readQuotedString (String& result) | |||
| if (character == quote) | |||
| { | |||
| result.append (start, (int) (input - start)); | |||
| result.append (start.getAddress(), (int) (input.getAddress() - start.getAddress())); | |||
| ++input; | |||
| return; | |||
| } | |||
| else if (character == '&') | |||
| { | |||
| result.append (start, (int) (input - start)); | |||
| result.append (start.getAddress(), (int) (input.getAddress() - start.getAddress())); | |||
| break; | |||
| } | |||
| else if (character == 0) | |||
| @@ -363,11 +363,11 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||
| if (outOfData) | |||
| return 0; | |||
| input = CharacterFunctions::find (input, JUCE_T("<")); | |||
| const int openBracket = input.indexOf ((juce_wchar) '<'); | |||
| if (input != 0) | |||
| if (openBracket >= 0) | |||
| { | |||
| ++input; | |||
| input += openBracket + 1; | |||
| int tagLen = findNextTokenLength(); | |||
| if (tagLen == 0) | |||
| @@ -383,7 +383,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||
| } | |||
| } | |||
| node = new XmlElement (String (input, tagLen)); | |||
| node = new XmlElement (String (input.getAddress(), tagLen)); | |||
| input += tagLen; | |||
| LinkedListPointer<XmlElement::XmlAttributeNode>::Appender attributeAppender (node->attributes); | |||
| @@ -419,7 +419,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||
| if (attNameLen > 0) | |||
| { | |||
| const juce_wchar* attNameStart = input; | |||
| const CharPointer_UTF32 attNameStart (input); | |||
| input += attNameLen; | |||
| skipNextWhiteSpace(); | |||
| @@ -433,7 +433,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||
| if (nextChar == '"' || nextChar == '\'') | |||
| { | |||
| XmlElement::XmlAttributeNode* const newAtt | |||
| = new XmlElement::XmlAttributeNode (String (attNameStart, attNameLen), | |||
| = new XmlElement::XmlAttributeNode (String (attNameStart.getAddress(), attNameLen), | |||
| String::empty); | |||
| readQuotedString (newAtt->value); | |||
| @@ -462,7 +462,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| for (;;) | |||
| { | |||
| const juce_wchar* const preWhitespaceInput = input; | |||
| const CharPointer_UTF32 preWhitespaceInput (input); | |||
| skipNextWhiteSpace(); | |||
| if (outOfData) | |||
| @@ -476,8 +476,11 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| if (input[1] == '/') | |||
| { | |||
| // our close tag.. | |||
| input = CharacterFunctions::find (input, JUCE_T(">")); | |||
| ++input; | |||
| const int closeTag = input.indexOf ((juce_wchar) '>'); | |||
| if (closeTag >= 0) | |||
| input += closeTag + 1; | |||
| break; | |||
| } | |||
| else if (input[1] == '!' | |||
| @@ -490,7 +493,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| && input[8] == '[') | |||
| { | |||
| input += 9; | |||
| const juce_wchar* const inputStart = input; | |||
| const CharPointer_UTF32 inputStart (input); | |||
| int len = 0; | |||
| @@ -514,7 +517,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| ++len; | |||
| } | |||
| childAppender.append (XmlElement::createTextElement (String (inputStart, len))); | |||
| childAppender.append (XmlElement::createTextElement (String (inputStart.getAddress(), len))); | |||
| } | |||
| else | |||
| { | |||
| @@ -553,10 +556,10 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| if (entity.startsWithChar ('<') && entity [1] != 0) | |||
| { | |||
| const juce_wchar* const oldInput = input; | |||
| const CharPointer_UTF32 oldInput (input); | |||
| const bool oldOutOfData = outOfData; | |||
| input = entity; | |||
| input = static_cast <const juce_wchar*> (entity); | |||
| outOfData = false; | |||
| for (;;) | |||
| @@ -579,7 +582,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| } | |||
| else | |||
| { | |||
| const juce_wchar* start = input; | |||
| const CharPointer_UTF32 start (input); | |||
| int len = 0; | |||
| for (;;) | |||
| @@ -601,7 +604,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| ++len; | |||
| } | |||
| textElementContent.append (start, len); | |||
| textElementContent.append (start.getAddress(), len); | |||
| } | |||
| } | |||
| @@ -618,27 +621,27 @@ void XmlDocument::readEntity (String& result) | |||
| // skip over the ampersand | |||
| ++input; | |||
| if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("amp;"), 4) == 0) | |||
| if (input.compareIgnoreCaseUpTo (CharPointer_UTF8 ("amp;"), 4) == 0) | |||
| { | |||
| input += 4; | |||
| result += '&'; | |||
| } | |||
| else if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("quot;"), 5) == 0) | |||
| else if (input.compareIgnoreCaseUpTo (CharPointer_UTF8 ("quot;"), 5) == 0) | |||
| { | |||
| input += 5; | |||
| result += '"'; | |||
| } | |||
| else if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("apos;"), 5) == 0) | |||
| else if (input.compareIgnoreCaseUpTo (CharPointer_UTF8 ("apos;"), 5) == 0) | |||
| { | |||
| input += 5; | |||
| result += '\''; | |||
| } | |||
| else if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("lt;"), 3) == 0) | |||
| else if (input.compareIgnoreCaseUpTo (CharPointer_UTF8 ("lt;"), 3) == 0) | |||
| { | |||
| input += 3; | |||
| result += '<'; | |||
| } | |||
| else if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("gt;"), 3) == 0) | |||
| else if (input.compareIgnoreCaseUpTo (CharPointer_UTF8 ("gt;"), 3) == 0) | |||
| { | |||
| input += 3; | |||
| result += '>'; | |||
| @@ -698,20 +701,19 @@ void XmlDocument::readEntity (String& result) | |||
| } | |||
| else | |||
| { | |||
| const juce_wchar* const entityNameStart = input; | |||
| const juce_wchar* const closingSemiColon = CharacterFunctions::find (input, JUCE_T(";")); | |||
| const CharPointer_UTF32 entityNameStart (input); | |||
| const int closingSemiColon = input.indexOf ((juce_wchar) ';'); | |||
| if (closingSemiColon == 0) | |||
| if (closingSemiColon < 0) | |||
| { | |||
| outOfData = true; | |||
| result += '&'; | |||
| } | |||
| else | |||
| { | |||
| input = closingSemiColon + 1; | |||
| input += closingSemiColon + 1; | |||
| result += expandExternalEntity (String (entityNameStart, | |||
| (int) (closingSemiColon - entityNameStart))); | |||
| result += expandExternalEntity (String (entityNameStart.getAddress(), closingSemiColon)); | |||
| } | |||
| } | |||
| } | |||
| @@ -153,7 +153,7 @@ public: | |||
| //============================================================================== | |||
| private: | |||
| String originalText; | |||
| const juce_wchar* input; | |||
| CharPointer_UTF32 input; | |||
| bool outOfData, errorOccurred; | |||
| String lastError, dtdText; | |||
| @@ -779,7 +779,7 @@ bool XmlElement::isTextElement() const throw() | |||
| return tagName.isEmpty(); | |||
| } | |||
| static const juce_wchar* const juce_xmltextContentAttributeName = L"text"; | |||
| static const String juce_xmltextContentAttributeName ("text"); | |||
| const String& XmlElement::getText() const throw() | |||
| { | |||
| @@ -295,21 +295,17 @@ const File PropertiesFile::getDefaultAppSettingsFile (const String& applicationN | |||
| // mustn't have illegal characters in this name.. | |||
| jassert (applicationName == File::createLegalFileName (applicationName)); | |||
| #if JUCE_MAC || JUCE_IOS | |||
| #if JUCE_MAC || JUCE_IOS | |||
| File dir (commonToAllUsers ? "/Library/Preferences" | |||
| : "~/Library/Preferences"); | |||
| if (folderName.isNotEmpty()) | |||
| dir = dir.getChildFile (folderName); | |||
| #endif | |||
| #ifdef JUCE_LINUX | |||
| #elif JUCE_LINUX || JUCE_ANDROID | |||
| const File dir ((commonToAllUsers ? "/var/" : "~/") | |||
| + (folderName.isNotEmpty() ? folderName | |||
| : ("." + applicationName))); | |||
| #endif | |||
| #if JUCE_WINDOWS | |||
| #elif JUCE_WINDOWS | |||
| File dir (File::getSpecialLocation (commonToAllUsers ? File::commonApplicationDataDirectory | |||
| : File::userApplicationDataDirectory)); | |||
| @@ -318,8 +314,7 @@ const File PropertiesFile::getDefaultAppSettingsFile (const String& applicationN | |||
| dir = dir.getChildFile (folderName.isNotEmpty() ? folderName | |||
| : applicationName); | |||
| #endif | |||
| #endif | |||
| return dir.getChildFile (applicationName) | |||
| .withFileExtension (fileNameSuffix); | |||