Browse Source

New classes CharPointer_UTF8, CharPointer_UTF16, CharPointer_UTF32, complete refactoring of CharacterFunctions class and updates to the internals of String methods. Removal of String::operator+= (unsigned int) because of clashes with wide-char types that use unsigned int. Made core classes compatible with Android. Minor fixes to ListBox and AudioDeviceManager.

tags/2021-05-28
Julian Storer 14 years ago
parent
commit
1b05a7d46d
42 changed files with 6825 additions and 2470 deletions
  1. +6
    -0
      Builds/MacOSX/Juce.xcodeproj/project.pbxproj
  2. +3
    -0
      Builds/VisualStudio2005/Juce.vcproj
  3. +3
    -0
      Builds/VisualStudio2008/Juce.vcproj
  4. +3
    -0
      Builds/VisualStudio2008_DLL/Juce.vcproj
  5. +3
    -0
      Builds/VisualStudio2010/Juce.vcxproj
  6. +9
    -0
      Builds/VisualStudio2010/Juce.vcxproj.filters
  7. +6
    -0
      Builds/iOS/Juce.xcodeproj/project.pbxproj
  8. +6
    -0
      Juce.jucer
  9. +6
    -6
      amalgamation/juce_amalgamated_template.cpp
  10. +1
    -1
      extras/juce demo/Source/demos/WidgetsDemo.cpp
  11. +3283
    -1129
      juce_amalgamated.cpp
  12. +1488
    -100
      juce_amalgamated.h
  13. +5
    -10
      src/audio/devices/juce_AudioDeviceManager.cpp
  14. +1
    -1
      src/audio/devices/juce_AudioDeviceManager.h
  15. +1
    -6
      src/containers/juce_SparseSet.h
  16. +6
    -1
      src/core/juce_StandardHeader.h
  17. +13
    -5
      src/core/juce_TargetPlatform.h
  18. +22
    -22
      src/gui/components/code_editor/juce_CPlusPlusCodeTokeniser.cpp
  19. +1
    -1
      src/gui/components/controls/juce_ListBox.cpp
  20. +2
    -2
      src/io/network/juce_Socket.cpp
  21. +5
    -5
      src/io/network/juce_URL.cpp
  22. +9
    -0
      src/juce_core_includes.h
  23. +2
    -4
      src/maths/juce_MathsFunctions.h
  24. +20
    -2
      src/memory/juce_Atomic.h
  25. +6
    -2
      src/memory/juce_ByteOrder.h
  26. +16
    -1
      src/native/common/juce_posix_SharedCode.h
  27. +1
    -1
      src/native/linux/juce_linux_Network.cpp
  28. +1
    -1
      src/native/windows/juce_win32_FileChooser.cpp
  29. +2
    -2
      src/native/windows/juce_win32_Misc.cpp
  30. +1
    -1
      src/native/windows/juce_win32_QuickTimeMovieComponent.cpp
  31. +343
    -0
      src/text/juce_CharPointer_UTF16.h
  32. +340
    -0
      src/text/juce_CharPointer_UTF32.h
  33. +441
    -0
      src/text/juce_CharPointer_UTF8.h
  34. +59
    -680
      src/text/juce_CharacterFunctions.cpp
  35. +374
    -82
      src/text/juce_CharacterFunctions.h
  36. +257
    -334
      src/text/juce_String.cpp
  37. +17
    -7
      src/text/juce_String.h
  38. +4
    -2
      src/text/juce_StringArray.cpp
  39. +53
    -51
      src/text/juce_XmlDocument.cpp
  40. +1
    -1
      src/text/juce_XmlDocument.h
  41. +1
    -1
      src/text/juce_XmlElement.cpp
  42. +4
    -9
      src/utilities/juce_PropertiesFile.cpp

+ 6
- 0
Builds/MacOSX/Juce.xcodeproj/project.pbxproj View File

@@ -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,


+ 3
- 0
Builds/VisualStudio2005/Juce.vcproj View File

@@ -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"/>


+ 3
- 0
Builds/VisualStudio2008/Juce.vcproj View File

@@ -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"/>


+ 3
- 0
Builds/VisualStudio2008_DLL/Juce.vcproj View File

@@ -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"/>


+ 3
- 0
Builds/VisualStudio2010/Juce.vcxproj View File

@@ -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"/>


+ 9
- 0
Builds/VisualStudio2010/Juce.vcxproj.filters View File

@@ -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>


+ 6
- 0
Builds/iOS/Juce.xcodeproj/project.pbxproj View File

@@ -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,


+ 6
- 0
Juce.jucer View File

@@ -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"


+ 6
- 6
amalgamation/juce_amalgamated_template.cpp View File

@@ -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

+ 1
- 1
extras/juce demo/Source/demos/WidgetsDemo.cpp View File

@@ -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");


+ 3283
- 1129
juce_amalgamated.cpp
File diff suppressed because it is too large
View File


+ 1488
- 100
juce_amalgamated.h
File diff suppressed because it is too large
View File


+ 5
- 10
src/audio/devices/juce_AudioDeviceManager.cpp View File

@@ -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);
}
}


+ 1
- 1
src/audio/devices/juce_AudioDeviceManager.h View File

@@ -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;


+ 1
- 6
src/containers/juce_SparseSet.h View File

@@ -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. */


+ 6
- 1
src/core/juce_StandardHeader.h View File

@@ -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


+ 13
- 5
src/core/juce_TargetPlatform.h View File

@@ -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
//==============================================================================


+ 22
- 22
src/gui/components/code_editor/juce_CPlusPlusCodeTokeniser.cpp View File

@@ -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;


+ 1
- 1
src/gui/components/controls/juce_ListBox.cpp View File

@@ -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);


+ 2
- 2
src/io/network/juce_Socket.cpp View File

@@ -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;


+ 5
- 5
src/io/network/juce_URL.cpp View File

@@ -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 == ' ')
{


+ 9
- 0
src/juce_core_includes.h View File

@@ -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


+ 2
- 4
src/maths/juce_MathsFunctions.h View File

@@ -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


+ 20
- 2
src/memory/juce_Atomic.h View File

@@ -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)));


+ 6
- 2
src/memory/juce_ByteOrder.h View File

@@ -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
}


+ 16
- 1
src/native/common/juce_posix_SharedCode.h View File

@@ -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*/)


+ 1
- 1
src/native/linux/juce_linux_Network.cpp View File

@@ -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;


+ 1
- 1
src/native/windows/juce_win32_FileChooser.cpp View File

@@ -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)


+ 2
- 2
src/native/windows/juce_win32_Misc.cpp View File

@@ -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);
}


+ 1
- 1
src/native/windows/juce_win32_QuickTimeMovieComponent.cpp View File

@@ -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);


+ 343
- 0
src/text/juce_CharPointer_UTF16.h View File

@@ -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__

+ 340
- 0
src/text/juce_CharPointer_UTF32.h View File

@@ -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__

+ 441
- 0
src/text/juce_CharPointer_UTF8.h View File

@@ -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__

+ 59
- 680
src/text/juce_CharacterFunctions.cpp View File

@@ -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

+ 374
- 82
src/text/juce_CharacterFunctions.h View File

@@ -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__

+ 257
- 334
src/text/juce_String.cpp
File diff suppressed because it is too large
View File


+ 17
- 7
src/text/juce_String.h View File

@@ -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);


+ 4
- 2
src/text/juce_StringArray.cpp View File

@@ -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)
{


+ 53
- 51
src/text/juce_XmlDocument.cpp View File

@@ -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));
}
}
}


+ 1
- 1
src/text/juce_XmlDocument.h View File

@@ -153,7 +153,7 @@ public:
//==============================================================================
private:
String originalText;
const juce_wchar* input;
CharPointer_UTF32 input;
bool outOfData, errorOccurred;
String lastError, dtdText;


+ 1
- 1
src/text/juce_XmlElement.cpp View File

@@ -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()
{


+ 4
- 9
src/utilities/juce_PropertiesFile.cpp View File

@@ -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);


Loading…
Cancel
Save