Browse Source

Added a JSON parser/formatter class. Extended the var class to hold arrays, to make it compatible with the structure of JSON data.

tags/2021-05-28
Julian Storer 14 years ago
parent
commit
796247483a
24 changed files with 1917 additions and 180 deletions
  1. +6
    -0
      Builds/Linux/Makefile
  2. +10
    -4
      Builds/MacOSX/Juce.xcodeproj/project.pbxproj
  3. +4
    -2
      Builds/VisualStudio2005/Juce.vcproj
  4. +4
    -2
      Builds/VisualStudio2008/Juce.vcproj
  5. +4
    -2
      Builds/VisualStudio2008_DLL/Juce.vcproj
  6. +4
    -2
      Builds/VisualStudio2010/Juce.vcxproj
  7. +8
    -2
      Builds/VisualStudio2010/Juce.vcxproj.filters
  8. +10
    -4
      Builds/iOS/Juce.xcodeproj/project.pbxproj
  9. +6
    -4
      Juce.jucer
  10. +1
    -0
      amalgamation/juce_amalgamated_template.cpp
  11. +718
    -67
      juce_amalgamated.cpp
  12. +191
    -19
      juce_amalgamated.h
  13. +5
    -0
      src/containers/juce_NamedValueSet.h
  14. +169
    -33
      src/containers/juce_Variant.cpp
  15. +86
    -18
      src/containers/juce_Variant.h
  16. +1
    -1
      src/core/juce_StandardHeader.h
  17. +15
    -0
      src/io/files/juce_FileOutputStream.cpp
  18. +1
    -0
      src/io/files/juce_FileOutputStream.h
  19. +20
    -5
      src/io/streams/juce_MemoryOutputStream.cpp
  20. +2
    -1
      src/io/streams/juce_MemoryOutputStream.h
  21. +3
    -0
      src/juce_core_includes.h
  22. +532
    -0
      src/text/juce_JSON.cpp
  23. +115
    -0
      src/text/juce_JSON.h
  24. +2
    -14
      src/text/juce_XmlElement.cpp

+ 6
- 0
Builds/Linux/Makefile View File

@@ -353,6 +353,7 @@ OBJECTS := \
$(OBJDIR)/juce_android_Windowing_2a620a72.o \
$(OBJDIR)/juce_CharacterFunctions_b1a5ac62.o \
$(OBJDIR)/juce_Identifier_e99ee619.o \
$(OBJDIR)/juce_JSON_bbf64af8.o \
$(OBJDIR)/juce_LocalisedStrings_3ddfa55e.o \
$(OBJDIR)/juce_String_80587b01.o \
$(OBJDIR)/juce_StringArray_4aaa67a2.o \
@@ -1956,6 +1957,11 @@ $(OBJDIR)/juce_Identifier_e99ee619.o: ../../src/text/juce_Identifier.cpp
@echo "Compiling juce_Identifier.cpp"
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
$(OBJDIR)/juce_JSON_bbf64af8.o: ../../src/text/juce_JSON.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling juce_JSON.cpp"
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
$(OBJDIR)/juce_LocalisedStrings_3ddfa55e.o: ../../src/text/juce_LocalisedStrings.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling juce_LocalisedStrings.cpp"


+ 10
- 4
Builds/MacOSX/Juce.xcodeproj/project.pbxproj View File

@@ -348,6 +348,7 @@
CE9A64287FCEF00DD2BA6AEE = { isa = PBXBuildFile; fileRef = FCD02A40985242A8A6648311; };
2AC6F3BFAAA21E21076A9F8D = { isa = PBXBuildFile; fileRef = 76E2084D2148068F9138A816; };
B8DD4DB0BD1A6B38BBF92413 = { isa = PBXBuildFile; fileRef = 8273A206FB309671284959DD; };
1C0B1362E81C8B073BF0DCEC = { isa = PBXBuildFile; fileRef = 644FD6155385BC3AA270FB5D; };
63BEC07A51CB8E516B38ECD4 = { isa = PBXBuildFile; fileRef = 4A97C8D2FF6454DDD3AF4BE5; };
C8F81E843F446868FAD88197 = { isa = PBXBuildFile; fileRef = B507B4A8712A54D7A8C03223; };
50D91A2EC0ABF894E612D936 = { isa = PBXBuildFile; fileRef = 23252E4C97AEFAE0C5EEAA77; };
@@ -1052,12 +1053,14 @@
FCD02A40985242A8A6648311 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_android_Windowing.cpp; path = ../../src/native/android/juce_android_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; };
72F5ED2E8B945988C37EA9CF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_ASCII.h; path = ../../src/text/juce_CharPointer_ASCII.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; };
72F5ED2E8B945988C37EA9CF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_ASCII.h; path = ../../src/text/juce_CharPointer_ASCII.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; };
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; };
644FD6155385BC3AA270FB5D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_JSON.cpp; path = ../../src/text/juce_JSON.cpp; sourceTree = SOURCE_ROOT; };
CB092FB152F43900272F8E43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_JSON.h; path = ../../src/text/juce_JSON.h; sourceTree = SOURCE_ROOT; };
4A97C8D2FF6454DDD3AF4BE5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_LocalisedStrings.cpp; path = ../../src/text/juce_LocalisedStrings.cpp; sourceTree = SOURCE_ROOT; };
2AA21CDC91EA122266EBD780 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_LocalisedStrings.h; path = ../../src/text/juce_LocalisedStrings.h; sourceTree = SOURCE_ROOT; };
35DA3E75DDB03BB35794289B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_NewLine.h; path = ../../src/text/juce_NewLine.h; sourceTree = SOURCE_ROOT; };
@@ -1894,12 +1897,14 @@
C6B52BCD0CB1B809D6DE555A = { isa = PBXGroup; children = (
76E2084D2148068F9138A816,
33F16EE4F38C9B76E7FAEF78,
4007410FACA2F865FD8EF769,
72F5ED2E8B945988C37EA9CF,
663746215E9BA6C761172B85,
C3FD9D93626F80A45F9B6DDE,
72F5ED2E8B945988C37EA9CF,
4007410FACA2F865FD8EF769,
8273A206FB309671284959DD,
BF888BC540B64D5C61E46A34,
644FD6155385BC3AA270FB5D,
CB092FB152F43900272F8E43,
4A97C8D2FF6454DDD3AF4BE5,
2AA21CDC91EA122266EBD780,
35DA3E75DDB03BB35794289B,
@@ -2391,6 +2396,7 @@
CE9A64287FCEF00DD2BA6AEE,
2AC6F3BFAAA21E21076A9F8D,
B8DD4DB0BD1A6B38BBF92413,
1C0B1362E81C8B073BF0DCEC,
63BEC07A51CB8E516B38ECD4,
C8F81E843F446868FAD88197,
50D91A2EC0ABF894E612D936,


+ 4
- 2
Builds/VisualStudio2005/Juce.vcproj View File

@@ -962,12 +962,14 @@
<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_ASCII.h"/>
<File RelativePath="..\..\src\text\juce_CharPointer_UTF16.h"/>
<File RelativePath="..\..\src\text\juce_CharPointer_UTF32.h"/>
<File RelativePath="..\..\src\text\juce_CharPointer_ASCII.h"/>
<File RelativePath="..\..\src\text\juce_CharPointer_UTF8.h"/>
<File RelativePath="..\..\src\text\juce_Identifier.cpp"/>
<File RelativePath="..\..\src\text\juce_Identifier.h"/>
<File RelativePath="..\..\src\text\juce_JSON.cpp"/>
<File RelativePath="..\..\src\text\juce_JSON.h"/>
<File RelativePath="..\..\src\text\juce_LocalisedStrings.cpp"/>
<File RelativePath="..\..\src\text\juce_LocalisedStrings.h"/>
<File RelativePath="..\..\src\text\juce_NewLine.h"/>


+ 4
- 2
Builds/VisualStudio2008/Juce.vcproj View File

@@ -962,12 +962,14 @@
<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_ASCII.h"/>
<File RelativePath="..\..\src\text\juce_CharPointer_UTF16.h"/>
<File RelativePath="..\..\src\text\juce_CharPointer_UTF32.h"/>
<File RelativePath="..\..\src\text\juce_CharPointer_ASCII.h"/>
<File RelativePath="..\..\src\text\juce_CharPointer_UTF8.h"/>
<File RelativePath="..\..\src\text\juce_Identifier.cpp"/>
<File RelativePath="..\..\src\text\juce_Identifier.h"/>
<File RelativePath="..\..\src\text\juce_JSON.cpp"/>
<File RelativePath="..\..\src\text\juce_JSON.h"/>
<File RelativePath="..\..\src\text\juce_LocalisedStrings.cpp"/>
<File RelativePath="..\..\src\text\juce_LocalisedStrings.h"/>
<File RelativePath="..\..\src\text\juce_NewLine.h"/>


+ 4
- 2
Builds/VisualStudio2008_DLL/Juce.vcproj View File

@@ -964,12 +964,14 @@
<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_ASCII.h"/>
<File RelativePath="..\..\src\text\juce_CharPointer_UTF16.h"/>
<File RelativePath="..\..\src\text\juce_CharPointer_UTF32.h"/>
<File RelativePath="..\..\src\text\juce_CharPointer_ASCII.h"/>
<File RelativePath="..\..\src\text\juce_CharPointer_UTF8.h"/>
<File RelativePath="..\..\src\text\juce_Identifier.cpp"/>
<File RelativePath="..\..\src\text\juce_Identifier.h"/>
<File RelativePath="..\..\src\text\juce_JSON.cpp"/>
<File RelativePath="..\..\src\text\juce_JSON.h"/>
<File RelativePath="..\..\src\text\juce_LocalisedStrings.cpp"/>
<File RelativePath="..\..\src\text\juce_LocalisedStrings.h"/>
<File RelativePath="..\..\src\text\juce_NewLine.h"/>


+ 4
- 2
Builds/VisualStudio2010/Juce.vcxproj View File

@@ -436,6 +436,7 @@
<ClCompile Include="..\..\src\native\android\juce_android_Windowing.cpp"/>
<ClCompile Include="..\..\src\text\juce_CharacterFunctions.cpp"/>
<ClCompile Include="..\..\src\text\juce_Identifier.cpp"/>
<ClCompile Include="..\..\src\text\juce_JSON.cpp"/>
<ClCompile Include="..\..\src\text\juce_LocalisedStrings.cpp"/>
<ClCompile Include="..\..\src\text\juce_String.cpp"/>
<ClCompile Include="..\..\src\text\juce_StringArray.cpp"/>
@@ -790,11 +791,12 @@
<ClInclude Include="..\..\src\native\windows\juce_win32_NativeIncludes.h"/>
<ClInclude Include="..\..\src\native\android\juce_android_NativeIncludes.h"/>
<ClInclude Include="..\..\src\text\juce_CharacterFunctions.h"/>
<ClInclude Include="..\..\src\text\juce_CharPointer_UTF8.h"/>
<ClInclude Include="..\..\src\text\juce_CharPointer_ASCII.h"/>
<ClInclude Include="..\..\src\text\juce_CharPointer_UTF16.h"/>
<ClInclude Include="..\..\src\text\juce_CharPointer_UTF32.h"/>
<ClInclude Include="..\..\src\text\juce_CharPointer_ASCII.h"/>
<ClInclude Include="..\..\src\text\juce_CharPointer_UTF8.h"/>
<ClInclude Include="..\..\src\text\juce_Identifier.h"/>
<ClInclude Include="..\..\src\text\juce_JSON.h"/>
<ClInclude Include="..\..\src\text\juce_LocalisedStrings.h"/>
<ClInclude Include="..\..\src\text\juce_NewLine.h"/>
<ClInclude Include="..\..\src\text\juce_String.h"/>


+ 8
- 2
Builds/VisualStudio2010/Juce.vcxproj.filters View File

@@ -1243,6 +1243,9 @@
<ClCompile Include="..\..\src\text\juce_Identifier.cpp">
<Filter>Juce\Source\text</Filter>
</ClCompile>
<ClCompile Include="..\..\src\text\juce_JSON.cpp">
<Filter>Juce\Source\text</Filter>
</ClCompile>
<ClCompile Include="..\..\src\text\juce_LocalisedStrings.cpp">
<Filter>Juce\Source\text</Filter>
</ClCompile>
@@ -2301,7 +2304,7 @@
<ClInclude Include="..\..\src\text\juce_CharacterFunctions.h">
<Filter>Juce\Source\text</Filter>
</ClInclude>
<ClInclude Include="..\..\src\text\juce_CharPointer_UTF8.h">
<ClInclude Include="..\..\src\text\juce_CharPointer_ASCII.h">
<Filter>Juce\Source\text</Filter>
</ClInclude>
<ClInclude Include="..\..\src\text\juce_CharPointer_UTF16.h">
@@ -2310,12 +2313,15 @@
<ClInclude Include="..\..\src\text\juce_CharPointer_UTF32.h">
<Filter>Juce\Source\text</Filter>
</ClInclude>
<ClInclude Include="..\..\src\text\juce_CharPointer_ASCII.h">
<ClInclude Include="..\..\src\text\juce_CharPointer_UTF8.h">
<Filter>Juce\Source\text</Filter>
</ClInclude>
<ClInclude Include="..\..\src\text\juce_Identifier.h">
<Filter>Juce\Source\text</Filter>
</ClInclude>
<ClInclude Include="..\..\src\text\juce_JSON.h">
<Filter>Juce\Source\text</Filter>
</ClInclude>
<ClInclude Include="..\..\src\text\juce_LocalisedStrings.h">
<Filter>Juce\Source\text</Filter>
</ClInclude>


+ 10
- 4
Builds/iOS/Juce.xcodeproj/project.pbxproj View File

@@ -348,6 +348,7 @@
CE9A64287FCEF00DD2BA6AEE = { isa = PBXBuildFile; fileRef = FCD02A40985242A8A6648311; };
2AC6F3BFAAA21E21076A9F8D = { isa = PBXBuildFile; fileRef = 76E2084D2148068F9138A816; };
B8DD4DB0BD1A6B38BBF92413 = { isa = PBXBuildFile; fileRef = 8273A206FB309671284959DD; };
1C0B1362E81C8B073BF0DCEC = { isa = PBXBuildFile; fileRef = 644FD6155385BC3AA270FB5D; };
63BEC07A51CB8E516B38ECD4 = { isa = PBXBuildFile; fileRef = 4A97C8D2FF6454DDD3AF4BE5; };
C8F81E843F446868FAD88197 = { isa = PBXBuildFile; fileRef = B507B4A8712A54D7A8C03223; };
50D91A2EC0ABF894E612D936 = { isa = PBXBuildFile; fileRef = 23252E4C97AEFAE0C5EEAA77; };
@@ -1052,12 +1053,14 @@
FCD02A40985242A8A6648311 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_android_Windowing.cpp; path = ../../src/native/android/juce_android_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; };
72F5ED2E8B945988C37EA9CF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_ASCII.h; path = ../../src/text/juce_CharPointer_ASCII.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; };
72F5ED2E8B945988C37EA9CF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_ASCII.h; path = ../../src/text/juce_CharPointer_ASCII.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; };
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; };
644FD6155385BC3AA270FB5D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_JSON.cpp; path = ../../src/text/juce_JSON.cpp; sourceTree = SOURCE_ROOT; };
CB092FB152F43900272F8E43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_JSON.h; path = ../../src/text/juce_JSON.h; sourceTree = SOURCE_ROOT; };
4A97C8D2FF6454DDD3AF4BE5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_LocalisedStrings.cpp; path = ../../src/text/juce_LocalisedStrings.cpp; sourceTree = SOURCE_ROOT; };
2AA21CDC91EA122266EBD780 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_LocalisedStrings.h; path = ../../src/text/juce_LocalisedStrings.h; sourceTree = SOURCE_ROOT; };
35DA3E75DDB03BB35794289B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_NewLine.h; path = ../../src/text/juce_NewLine.h; sourceTree = SOURCE_ROOT; };
@@ -1894,12 +1897,14 @@
C6B52BCD0CB1B809D6DE555A = { isa = PBXGroup; children = (
76E2084D2148068F9138A816,
33F16EE4F38C9B76E7FAEF78,
4007410FACA2F865FD8EF769,
72F5ED2E8B945988C37EA9CF,
663746215E9BA6C761172B85,
C3FD9D93626F80A45F9B6DDE,
72F5ED2E8B945988C37EA9CF,
4007410FACA2F865FD8EF769,
8273A206FB309671284959DD,
BF888BC540B64D5C61E46A34,
644FD6155385BC3AA270FB5D,
CB092FB152F43900272F8E43,
4A97C8D2FF6454DDD3AF4BE5,
2AA21CDC91EA122266EBD780,
35DA3E75DDB03BB35794289B,
@@ -2395,6 +2400,7 @@
CE9A64287FCEF00DD2BA6AEE,
2AC6F3BFAAA21E21076A9F8D,
B8DD4DB0BD1A6B38BBF92413,
1C0B1362E81C8B073BF0DCEC,
63BEC07A51CB8E516B38ECD4,
C8F81E843F446868FAD88197,
50D91A2EC0ABF894E612D936,


+ 6
- 4
Juce.jucer View File

@@ -1497,18 +1497,20 @@
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="rdfOEc" name="juce_CharPointer_ASCII.h" compile="0" resource="0"
file="src/text/juce_CharPointer_ASCII.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="rdfOEc" name="juce_CharPointer_ASCII.h" compile="0" resource="0"
file="src/text/juce_CharPointer_ASCII.h"/>
<FILE id="vCX7K0" name="juce_CharPointer_UTF8.h" compile="0" resource="0"
file="src/text/juce_CharPointer_UTF8.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"
file="src/text/juce_Identifier.h"/>
<FILE id="dkmz9Q" name="juce_JSON.cpp" compile="1" resource="0" file="src/text/juce_JSON.cpp"/>
<FILE id="Thklwk" name="juce_JSON.h" compile="0" resource="0" file="src/text/juce_JSON.h"/>
<FILE id="HCYu323Km" name="juce_LocalisedStrings.cpp" compile="1" resource="0"
file="src/text/juce_LocalisedStrings.cpp"/>
<FILE id="omEQRDHD" name="juce_LocalisedStrings.h" compile="0" resource="0"


+ 1
- 0
amalgamation/juce_amalgamated_template.cpp View File

@@ -147,6 +147,7 @@
#include "../src/text/juce_StringPool.cpp"
#include "../src/text/juce_XmlDocument.cpp"
#include "../src/text/juce_XmlElement.cpp"
#include "../src/text/juce_JSON.cpp"
#include "../src/threads/juce_ReadWriteLock.cpp"
#include "../src/threads/juce_Thread.cpp"
#include "../src/threads/juce_ThreadPool.cpp"


+ 718
- 67
juce_amalgamated.cpp View File

@@ -4177,7 +4177,7 @@ Identifier::~Identifier()
bool Identifier::isValidIdentifier (const String& possibleIdentifier) noexcept
{
return possibleIdentifier.isNotEmpty()
&& possibleIdentifier.containsOnly ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
&& possibleIdentifier.containsOnly ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-:");
}

END_JUCE_NAMESPACE
@@ -4195,7 +4195,8 @@ enum VariantStreamMarkers
varMarker_BoolFalse = 3,
varMarker_Double = 4,
varMarker_String = 5,
varMarker_Int64 = 6
varMarker_Int64 = 6,
varMarker_Array = 7
};

class var::VariantType
@@ -4210,6 +4211,7 @@ public:
virtual String toString (const ValueUnion&) const { return String::empty; }
virtual bool toBool (const ValueUnion&) const noexcept { return false; }
virtual ReferenceCountedObject* toObject (const ValueUnion&) const noexcept { return nullptr; }
virtual Array<var>* toArray (const ValueUnion&) const noexcept { return 0; }

virtual bool isVoid() const noexcept { return false; }
virtual bool isInt() const noexcept { return false; }
@@ -4218,6 +4220,7 @@ public:
virtual bool isDouble() const noexcept { return false; }
virtual bool isString() const noexcept { return false; }
virtual bool isObject() const noexcept { return false; }
virtual bool isArray() const noexcept { return false; }
virtual bool isMethod() const noexcept { return false; }

virtual void cleanUp (ValueUnion&) const noexcept {}
@@ -4405,6 +4408,40 @@ public:
}
};

class var::VariantType_Array : public var::VariantType
{
public:
VariantType_Array() noexcept {}
static const VariantType_Array instance;

void cleanUp (ValueUnion& data) const noexcept { delete data.arrayValue; }
void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.arrayValue = new Array<var> (*(source.arrayValue)); }

String toString (const ValueUnion&) const { return "[Array]"; }
bool isArray() const noexcept { return true; }
Array<var>* toArray (const ValueUnion& data) const noexcept { return data.arrayValue; }

bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
{
const Array<var>* const otherArray = otherType.toArray (otherData);
return otherArray != nullptr && *otherArray == *(data.arrayValue);
}

void writeToStream (const ValueUnion& data, OutputStream& output) const
{
MemoryOutputStream buffer (512);
const int numItems = data.arrayValue->size();
buffer.writeCompressedInt (numItems);

for (int i = 0; i < numItems; ++i)
data.arrayValue->getReference(i).writeToStream (buffer);

output.writeCompressedInt (1 + buffer.getDataSize());
output.writeByte (varMarker_Array);
output << buffer;
}
};

class var::VariantType_Method : public var::VariantType
{
public:
@@ -4434,6 +4471,7 @@ const var::VariantType_Bool var::VariantType_Bool::instance;
const var::VariantType_Double var::VariantType_Double::instance;
const var::VariantType_String var::VariantType_String::instance;
const var::VariantType_Object var::VariantType_Object::instance;
const var::VariantType_Array var::VariantType_Array::instance;
const var::VariantType_Method var::VariantType_Method::instance;

var::var() noexcept : type (&VariantType_Void::instance)
@@ -4487,6 +4525,11 @@ var::var (const wchar_t* const value_) : type (&VariantType_String::instance)
new (value.stringValue) String (value_);
}

var::var (const Array<var>& value_) : type (&VariantType_Array::instance)
{
value.arrayValue = new Array<var> (value_);
}

var::var (ReferenceCountedObject* const object) : type (&VariantType_Object::instance)
{
value.objectValue = object;
@@ -4507,6 +4550,7 @@ bool var::isBool() const noexcept { return type->isBool(); }
bool var::isDouble() const noexcept { return type->isDouble(); }
bool var::isString() const noexcept { return type->isString(); }
bool var::isObject() const noexcept { return type->isObject(); }
bool var::isArray() const noexcept { return type->isArray(); }
bool var::isMethod() const noexcept { return type->isMethod(); }

var::operator int() const noexcept { return type->toInt (value); }
@@ -4517,6 +4561,7 @@ var::operator double() const noexcept { return type->toDouble (value); }
String var::toString() const { return type->toString (value); }
var::operator String() const { return type->toString (value); }
ReferenceCountedObject* var::getObject() const noexcept { return type->toObject (value); }
Array<var>* var::getArray() const noexcept { return type->toArray (value); }
DynamicObject* var::getDynamicObject() const noexcept { return dynamic_cast <DynamicObject*> (getObject()); }

void var::swapWith (var& other) noexcept
@@ -4533,6 +4578,7 @@ const var& var::operator= (const double newValue) { type->cleanUp (value); typ
const var& var::operator= (const char* const newValue) { var v (newValue); swapWith (v); return *this; }
const var& var::operator= (const wchar_t* const newValue) { var v (newValue); swapWith (v); return *this; }
const var& var::operator= (const String& newValue) { var v (newValue); swapWith (v); return *this; }
const var& var::operator= (const Array<var>& newValue) { var v (newValue); swapWith (v); return *this; }
const var& var::operator= (ReferenceCountedObject* newValue) { var v (newValue); swapWith (v); return *this; }
const var& var::operator= (MethodFunction newValue) { var v (newValue); swapWith (v); return *this; }

@@ -4553,38 +4599,6 @@ bool operator!= (const var& v1, const String& v2) { return v1.toString() != v
bool operator== (const var& v1, const char* const v2) { return v1.toString() == v2; }
bool operator!= (const var& v1, const char* const v2) { return v1.toString() != v2; }

void var::writeToStream (OutputStream& output) const
{
type->writeToStream (value, output);
}

var var::readFromStream (InputStream& input)
{
const int numBytes = input.readCompressedInt();

if (numBytes > 0)
{
switch (input.readByte())
{
case varMarker_Int: return var (input.readInt());
case varMarker_Int64: return var (input.readInt64());
case varMarker_BoolTrue: return var (true);
case varMarker_BoolFalse: return var (false);
case varMarker_Double: return var (input.readDouble());
case varMarker_String:
{
MemoryOutputStream mo;
mo.writeFromInputStream (input, numBytes - 1);
return var (mo.toUTF8());
}

default: input.skipNextBytes (numBytes - 1); break;
}
}

return var::null;
}

var var::operator[] (const Identifier& propertyName) const
{
DynamicObject* const o = getDynamicObject();
@@ -4641,6 +4655,125 @@ var var::call (const Identifier& method, const var& arg1, const var& arg2, const
return invoke (method, args, 5);
}

int var::size() const
{
const Array<var>* const array = getArray();
return array != nullptr ? array->size() : 0;
}

const var& var::operator[] (int arrayIndex) const
{
const Array<var>* const array = getArray();

// When using this method, the var must actually be an array, and the index
// must be in-range!
jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));

return array->getReference (arrayIndex);
}

var& var::operator[] (int arrayIndex)
{
const Array<var>* const array = getArray();

// When using this method, the var must actually be an array, and the index
// must be in-range!
jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));

return array->getReference (arrayIndex);
}

Array<var>* var::convertToArray()
{
Array<var>* array = getArray();

if (array == nullptr)
{
const Array<var> tempVar;
var v (tempVar);
array = v.value.arrayValue;

if (! isVoid())
array->add (*this);

swapWith (v);
}

return array;
}

void var::append (const var& value)
{
convertToArray()->add (value);
}

void var::remove (const int index)
{
Array<var>* const array = getArray();

if (array != nullptr)
array->remove (index);
}

void var::insert (const int index, const var& value)
{
convertToArray()->insert (index, value);
}

void var::resize (const int numArrayElementsWanted)
{
convertToArray()->resize (numArrayElementsWanted);
}

int var::indexOf (const var& value) const
{
const Array<var>* const array = getArray();
return array != nullptr ? array->indexOf (value) : -1;
}

void var::writeToStream (OutputStream& output) const
{
type->writeToStream (value, output);
}

var var::readFromStream (InputStream& input)
{
const int numBytes = input.readCompressedInt();

if (numBytes > 0)
{
switch (input.readByte())
{
case varMarker_Int: return var (input.readInt());
case varMarker_Int64: return var (input.readInt64());
case varMarker_BoolTrue: return var (true);
case varMarker_BoolFalse: return var (false);
case varMarker_Double: return var (input.readDouble());
case varMarker_String:
{
MemoryOutputStream mo;
mo.writeFromInputStream (input, numBytes - 1);
return var (mo.toUTF8());
}

case varMarker_Array:
{
var v;
Array<var>* const destArray = v.convertToArray();

for (int i = input.readCompressedInt(); --i >= 0;)
destArray->add (readFromStream (input));

return v;
}

default: input.skipNextBytes (numBytes - 1); break;
}
}

return var::null;
}

END_JUCE_NAMESPACE

/*** End of inlined file: juce_Variant.cpp ***/
@@ -4811,7 +4944,7 @@ const Identifier NamedValueSet::getName (const int index) const
return v->name;
}

var NamedValueSet::getValueAt (const int index) const
const var& NamedValueSet::getValueAt (const int index) const
{
const NamedValue* const v = values[index];
jassert (v != nullptr);
@@ -8694,6 +8827,20 @@ bool FileOutputStream::write (const void* const src, const int numBytes)
return true;
}

void FileOutputStream::writeRepeatedByte (uint8 byte, int numBytes)
{
if (bytesInBuffer + numBytes < bufferSize)
{
memset (buffer + bytesInBuffer, byte, numBytes);
bytesInBuffer += numBytes;
currentPosition += numBytes;
}
else
{
OutputStream::writeRepeatedByte (byte, numBytes);
}
}

END_JUCE_NAMESPACE

/*** End of inlined file: juce_FileOutputStream.cpp ***/
@@ -10439,15 +10586,19 @@ void MemoryOutputStream::reset() noexcept
size = 0;
}

void MemoryOutputStream::prepareToWrite (int numBytes)
{
const size_t storageNeeded = position + numBytes;

if (storageNeeded >= data.getSize())
data.ensureSize ((storageNeeded + jmin ((int) (storageNeeded / 2), 1024 * 1024) + 32) & ~31);
}

bool MemoryOutputStream::write (const void* const buffer, int howMany)
{
if (howMany > 0)
{
const size_t storageNeeded = position + howMany;

if (storageNeeded >= data.getSize())
data.ensureSize ((storageNeeded + jmin ((int) (storageNeeded / 2), 1024 * 1024) + 32) & ~31);

prepareToWrite (howMany);
memcpy (static_cast<char*> (data.getData()) + position, buffer, howMany);
position += howMany;
size = jmax (size, position);
@@ -10456,6 +10607,17 @@ bool MemoryOutputStream::write (const void* const buffer, int howMany)
return true;
}

void MemoryOutputStream::writeRepeatedByte (uint8 byte, int howMany)
{
if (howMany > 0)
{
prepareToWrite (howMany);
memset (static_cast<char*> (data.getData()) + position, byte, howMany);
position += howMany;
size = jmax (size, position);
}
}

const void* MemoryOutputStream::getData() const noexcept
{
void* const d = data.getData();
@@ -15618,21 +15780,9 @@ namespace XmlOutputFunctions
}
}

void writeSpaces (OutputStream& out, int numSpaces)
void writeSpaces (OutputStream& out, const int numSpaces)
{
if (numSpaces > 0)
{
const char blanks[] = " ";
const int blankSize = (int) numElementsInArray (blanks) - 1;

while (numSpaces > blankSize)
{
out.write (blanks, blankSize);
numSpaces -= blankSize;
}

out.write (blanks, numSpaces);
}
out.writeRepeatedByte (' ', numSpaces);
}
}

@@ -16278,6 +16428,506 @@ END_JUCE_NAMESPACE
/*** End of inlined file: juce_XmlElement.cpp ***/


/*** Start of inlined file: juce_JSON.cpp ***/
BEGIN_JUCE_NAMESPACE

class JSONParser
{
public:
static Result parseAny (String::CharPointerType& t, var& result)
{
t = t.findEndOfWhitespace();
String::CharPointerType t2 (t);

switch (t2.getAndAdvance())
{
case '{': t = t2; return parseObject (t, result);
case '[': t = t2; return parseArray (t, result);
case '"': t = t2; return parseString (t, result);

case '-':
t2 = t2.findEndOfWhitespace();
if (! CharacterFunctions::isDigit (*t2))
break;

t = t2;
return parseNumber (t, result, true);

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return parseNumber (t, result, false);

case 't': // "true"
if (t2.getAndAdvance() == 'r' && t2.getAndAdvance() == 'u' && t2.getAndAdvance() == 'e')
{
t = t2;
result = var (true);
return Result::ok();
}
break;

case 'f': // "false"
if (t2.getAndAdvance() == 'a' && t2.getAndAdvance() == 'l'
&& t2.getAndAdvance() == 's' && t2.getAndAdvance() == 'e')
{
t = t2;
result = var (false);
return Result::ok();
}
break;

case 'n': // "null"
if (t2.getAndAdvance() == 'u' && t2.getAndAdvance() == 'l' && t2.getAndAdvance() == 'l')
{
t = t2;
result = var::null;
return Result::ok();
}
break;

default:
break;
}

return createFail ("Syntax error", &t);
}

private:
static Result createFail (const char* const message, const String::CharPointerType* location = nullptr)
{
String m (message);
if (location != nullptr)
m << ": \"" << String (*location, 20) << '"';

return Result::fail (m);
}

static Result parseNumber (String::CharPointerType& t, var& result, const bool isNegative)
{
String::CharPointerType oldT (t);

int64 intValue = t.getAndAdvance() - '0';
jassert (intValue >= 0 && intValue < 10);

for (;;)
{
String::CharPointerType previousChar (t);
const juce_wchar c = t.getAndAdvance();
const int digit = ((int) c) - '0';

if (isPositiveAndBelow (digit, 10))
{
intValue = intValue * 10 + digit;
continue;
}

if (c == 'e' || c == 'E' || c == '.')
{
t = oldT;
const double asDouble = CharacterFunctions::readDoubleValue (t);
result = isNegative ? -asDouble : asDouble;
return Result::ok();
}

if (CharacterFunctions::isWhitespace (c)
|| c == ',' || c == '}' || c == ']' || c == 0)
{
t = previousChar;
break;
}

return createFail ("Syntax error in number", &oldT);
}

const int64 correctedValue = isNegative ? -intValue : intValue;

if ((intValue >> 31) != 0)
result = correctedValue;
else
result = (int) correctedValue;

return Result::ok();
}

static Result parseObject (String::CharPointerType& t, var& result)
{
DynamicObject* const resultObject = new DynamicObject();
result = resultObject;

for (;;)
{
t = t.findEndOfWhitespace();

String::CharPointerType oldT (t);
const juce_wchar c = t.getAndAdvance();

if (c == '}')
break;

if (c == 0)
return createFail ("Unexpected end-of-input in object declaration");

if (c == '"')
{
var propertyNameVar;
Result r (parseString (t, propertyNameVar));

if (r.failed())
return r;

const String propertyName (propertyNameVar.toString());

if (propertyName.isNotEmpty())
{
t = t.findEndOfWhitespace();
oldT = t;

const juce_wchar c = t.getAndAdvance();
if (c != ':')
return createFail ("Expected ':', but found", &oldT);

var propertyValue;
Result r (parseAny (t, propertyValue));

if (r.failed())
return r;

resultObject->setProperty (propertyName, propertyValue);

t = t.findEndOfWhitespace();
oldT = t;

const juce_wchar nextChar = t.getAndAdvance();

if (nextChar == ',')
continue;
else if (nextChar == '}')
break;
}
}

return createFail ("Expected object member declaration, but found", &oldT);
}

return Result::ok();
}

static Result parseArray (String::CharPointerType& t, var& result)
{
result = var (Array<var>());
Array<var>* const destArray = result.getArray();

for (;;)
{
t = t.findEndOfWhitespace();

String::CharPointerType oldT (t);
const juce_wchar c = t.getAndAdvance();

if (c == ']')
break;

if (c == 0)
return createFail ("Unexpected end-of-input in array declaration");

t = oldT;
destArray->add (var::null);
Result r (parseAny (t, destArray->getReference (destArray->size() - 1)));

if (r.failed())
return r;

t = t.findEndOfWhitespace();
oldT = t;

const juce_wchar nextChar = t.getAndAdvance();

if (nextChar == ',')
continue;
else if (nextChar == ']')
break;

return createFail ("Expected object array item, but found", &oldT);
}

return Result::ok();
}

static Result parseString (String::CharPointerType& t, var& result)
{
Array<juce_wchar> buffer;
buffer.ensureStorageAllocated (256);

for (;;)
{
juce_wchar c = t.getAndAdvance();

if (c == '"')
break;

if (c == '\\')
{
c = t.getAndAdvance();

switch (c)
{
case '"':
case '\\':
case '/': break;

case 'b': c = '\b'; break;
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;

case 'u':
{
c = 0;

for (int i = 4; --i >= 0;)
{
const int digitValue = CharacterFunctions::getHexDigitValue (t.getAndAdvance());
if (digitValue < 0)
return createFail ("Syntax error in unicode escape sequence");

c = (juce_wchar) ((c << 4) + digitValue);
}

break;
}
}
}

if (c == 0)
return createFail ("Unexpected end-of-input in string constant");

buffer.add (c);
}

buffer.add (0);
result = String (CharPointer_UTF32 (buffer.getRawDataPointer()));
return Result::ok();
}
};

class JSONFormatter
{
public:
static void write (OutputStream& out, const var& v,
const int indentLevel, const bool allOnOneLine)
{
if (v.isString())
{
writeString (out, v.toString().getCharPointer());
}
else if (v.isVoid())
{
out << "null";
}
else if (v.isBool())
{
out << (static_cast<bool> (v) ? "true" : "false");
}
else if (v.isArray())
{
writeArray (out, *v.getArray(), indentLevel, allOnOneLine);
}
else if (v.isObject())
{
DynamicObject* object = dynamic_cast<DynamicObject*> (v.getObject());

jassert (object != nullptr); // Only DynamicObjects can be converted to JSON!

writeObject (out, *object, indentLevel, allOnOneLine);
}
else
{
jassert (! v.isMethod()); // Can't convert an object with methods to JSON!

out << v.toString();
}
}

private:
enum { indentSize = 2 };

static void writeEscapedChar (OutputStream& out, const unsigned short value)
{
out << "\\u" << String::toHexString ((int) value).paddedLeft ('0', 4);
}

static void writeString (OutputStream& out, String::CharPointerType t)
{
out << '"';

for (;;)
{
const juce_wchar c (t.getAndAdvance());

switch (c)
{
case 0: out << '"'; return;

case '\"': out << "\\\""; break;
case '\\': out << "\\\\"; break;
case '\b': out << "\\b"; break;
case '\f': out << "\\f"; break;
case '\t': out << "\\t"; break;
case '\r': out << "\\r"; break;
case '\n': out << "\\n"; break;

default:
if (c >= 32 && c < 127)
{
out << (char) c;
}
else
{
if (CharPointer_UTF16::getBytesRequiredFor (c) > 2)
{
CharPointer_UTF16::CharType chars[2];
CharPointer_UTF16 utf16 (chars);
utf16.write (c);

for (int i = 0; i < 2; ++i)
writeEscapedChar (out, (unsigned short) chars[i]);
}
else
{
writeEscapedChar (out, (unsigned short) c);
}
}

break;
}
}
}

static void writeSpaces (OutputStream& out, int numSpaces)
{
out.writeRepeatedByte (' ', numSpaces);
}

static void writeArray (OutputStream& out, const Array<var>& array,
const int indentLevel, const bool allOnOneLine)
{
out << '[';
if (! allOnOneLine)
out << newLine;

for (int i = 0; i < array.size(); ++i)
{
if (! allOnOneLine)
writeSpaces (out, indentLevel + indentSize);

write (out, array.getReference(i), indentLevel + indentSize, allOnOneLine);

if (i < array.size() - 1)
{
if (allOnOneLine)
out << ", ";
else
out << ',' << newLine;
}
else if (! allOnOneLine)
out << newLine;
}

if (! allOnOneLine)
writeSpaces (out, indentLevel);

out << ']';
}

static void writeObject (OutputStream& out, DynamicObject& object,
const int indentLevel, const bool allOnOneLine)
{
NamedValueSet& props = object.getProperties();

out << '{';
if (! allOnOneLine)
out << newLine;

LinkedListPointer<NamedValueSet::NamedValue>* i = &(props.values);

for (;;)
{
NamedValueSet::NamedValue* const v = i->get();

if (v == nullptr)
break;

if (! allOnOneLine)
writeSpaces (out, indentLevel + indentSize);

writeString (out, v->name);
out << ": ";
write (out, v->value, indentLevel + indentSize, allOnOneLine);

if (v->nextListItem.get() != nullptr)
{
if (allOnOneLine)
out << ", ";
else
out << ',' << newLine;
}
else if (! allOnOneLine)
out << newLine;

i = &(v->nextListItem);
}

if (! allOnOneLine)
writeSpaces (out, indentLevel);

out << '}';
}
};

var JSON::parse (const String& text)
{
var result;
String::CharPointerType t (text.getCharPointer());
if (! JSONParser::parseAny (t, result))
result = var::null;

return result;
}

var JSON::parse (InputStream& input)
{
return parse (input.readEntireStreamAsString());
}

var JSON::parse (const File& file)
{
return parse (file.loadFileAsString());
}

Result JSON::parse (const String& text, var& result)
{
String::CharPointerType t (text.getCharPointer());
return JSONParser::parseAny (t, result);
}

String JSON::toString (const var& data, const bool allOnOneLine)
{
MemoryOutputStream mo (1024);
JSONFormatter::write (mo, data, 0, allOnOneLine);
return mo.toString();
}

void JSON::writeToStream (OutputStream& output, const var& data, const bool allOnOneLine)
{
JSONFormatter::write (output, data, 0, allOnOneLine);
}

END_JUCE_NAMESPACE

/*** End of inlined file: juce_JSON.cpp ***/


/*** Start of inlined file: juce_ReadWriteLock.cpp ***/
BEGIN_JUCE_NAMESPACE

@@ -243958,11 +244608,11 @@ bool SystemStats::isOperatingSystem64Bit()
#else
typedef BOOL (WINAPI* LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);

LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle (L"kernel32"), "IsWow64Process");
LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle (_T("kernel32")), "IsWow64Process");

BOOL isWow64 = FALSE;

return (fnIsWow64Process != 0)
return fnIsWow64Process != 0
&& fnIsWow64Process (GetCurrentProcess(), &isWow64)
&& (isWow64 != FALSE);
#endif
@@ -246073,14 +246723,8 @@ void PlatformUtilities::registerFileAssociation (const String& fileExtension,

bool juce_IsRunningInWine()
{
HKEY key;
if (RegOpenKeyEx (HKEY_CURRENT_USER, _T("Software\\Wine"), 0, KEY_READ, &key) == ERROR_SUCCESS)
{
RegCloseKey (key);
return true;
}

return false;
HMODULE ntdll = GetModuleHandle (_T("ntdll.dll"));
return ntdll != 0 && GetProcAddress (ntdll, "wine_get_version") != 0;
}

const String JUCE_CALLTYPE PlatformUtilities::getCurrentCommandLineParams()
@@ -249045,6 +249689,14 @@ private:
#endif
}

static int getMinTimeBetweenMouseMoves()
{
if (SystemStats::getOperatingSystemType() >= SystemStats::WinVista)
return 0;

return 1000 / 60; // Throttling the incoming mouse-events seems to still be needed in XP..
}

void doMouseMove (const Point<int>& position)
{
if (! isMouseOver)
@@ -249069,12 +249721,11 @@ private:
return;
}

// (Throttling the incoming queue of mouse-events seems to still be required in XP..)
static uint32 lastMouseTime = 0;
static int minTimeBetweenMouses = getMinTimeBetweenMouseMoves();
const uint32 now = Time::getMillisecondCounter();
const int maxMouseMovesPerSecond = 60;

if (now > lastMouseTime + 1000 / maxMouseMovesPerSecond)
if (now >= lastMouseTime + minTimeBetweenMouses)
{
lastMouseTime = now;
doMouseEvent (position);


+ 191
- 19
juce_amalgamated.h View File

@@ -73,7 +73,7 @@ namespace JuceDummyNamespace {}
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53
#define JUCE_BUILDNUMBER 97
#define JUCE_BUILDNUMBER 98

/** Current Juce version number.

@@ -7908,7 +7908,7 @@ public:

/** Checks a given string for characters that might not be valid in an Identifier.
Since Identifiers are used as a script variables and XML attributes, they should only contain
alphanumeric characters and underscores.
alphanumeric characters, underscores, or the '-' and ':' characters.
*/
static bool isValidIdentifier (const String& possibleIdentifier) noexcept;

@@ -8496,6 +8496,7 @@ public:
var (const char* value);
var (const wchar_t* value);
var (const String& value);
var (const Array<var>& value);
var (ReferenceCountedObject* object);
var (MethodFunction method) noexcept;

@@ -8507,6 +8508,7 @@ public:
const var& operator= (const char* value);
const var& operator= (const wchar_t* value);
const var& operator= (const String& value);
const var& operator= (const Array<var>& value);
const var& operator= (ReferenceCountedObject* object);
const var& operator= (MethodFunction method);

@@ -8519,6 +8521,7 @@ public:
operator double() const noexcept;
operator String() const;
String toString() const;
Array<var>* getArray() const noexcept;
ReferenceCountedObject* getObject() const noexcept;
DynamicObject* getDynamicObject() const noexcept;

@@ -8529,18 +8532,83 @@ public:
bool isDouble() const noexcept;
bool isString() const noexcept;
bool isObject() const noexcept;
bool isArray() const noexcept;
bool isMethod() const noexcept;

/** Writes a binary representation of this value to a stream.
The data can be read back later using readFromStream().
/** Returns true if this var has the same value as the one supplied.
Note that this ignores the type, so a string var "123" and an integer var with the
value 123 are considered to be equal.
@see equalsWithSameType
*/
void writeToStream (OutputStream& output) const;
bool equals (const var& other) const noexcept;

/** Reads back a stored binary representation of a value.
The data in the stream must have been written using writeToStream(), or this
will have unpredictable results.
/** Returns true if this var has the same value and type as the one supplied.
This differs from equals() because e.g. "123" and 123 will be considered different.
@see equals
*/
static var readFromStream (InputStream& input);
bool equalsWithSameType (const var& other) const noexcept;

/** If the var is an array, this returns the number of elements.
If the var isn't actually an array, this will return 0.
*/
int size() const;

/** If the var is an array, this can be used to return one of its elements.
To call this method, you must make sure that the var is actually an array, and
that the index is a valid number. If these conditions aren't met, behaviour is
undefined.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array<var>.
*/
const var& operator[] (int arrayIndex) const;

/** If the var is an array, this can be used to return one of its elements.
To call this method, you must make sure that the var is actually an array, and
that the index is a valid number. If these conditions aren't met, behaviour is
undefined.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array<var>.
*/
var& operator[] (int arrayIndex);

/** Appends an element to the var, converting it to an array if it isn't already one.
If the var isn't an array, it will be converted to one, and if its value was non-void,
this value will be kept as the first element of the new array. The parameter value
will then be appended to it.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array<var>.
*/
void append (const var& valueToAppend);

/** Inserts an element to the var, converting it to an array if it isn't already one.
If the var isn't an array, it will be converted to one, and if its value was non-void,
this value will be kept as the first element of the new array. The parameter value
will then be inserted into it.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array<var>.
*/
void insert (int index, const var& value);

/** If the var is an array, this removes one of its elements.
If the index is out-of-range or the var isn't an array, nothing will be done.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array<var>.
*/
void remove (int index);

/** Treating the var as an array, this resizes it to contain the specified number of elements.
If the var isn't an array, it will be converted to one, and if its value was non-void,
this value will be kept as the first element of the new array before resizing.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array<var>.
*/
void resize (int numArrayElementsWanted);

/** If the var is an array, this searches it for the first occurrence of the specified value,
and returns its index.
If the var isn't an array, or if the value isn't found, this returns -1.
*/
int indexOf (const var& value) const;

/** If this variant is an object, this returns one of its properties. */
var operator[] (const Identifier& propertyName) const;
@@ -8560,18 +8628,16 @@ public:
/** If this variant is an object, this invokes one of its methods with a list of arguments. */
var invoke (const Identifier& method, const var* arguments, int numArguments) const;

/** Returns true if this var has the same value as the one supplied.
Note that this ignores the type, so a string var "123" and an integer var with the
value 123 are considered to be equal.
@see equalsWithSameType
/** Writes a binary representation of this value to a stream.
The data can be read back later using readFromStream().
*/
bool equals (const var& other) const noexcept;
void writeToStream (OutputStream& output) const;

/** Returns true if this var has the same value and type as the one supplied.
This differs from equals() because e.g. "123" and 123 will be considered different.
@see equals
/** Reads back a stored binary representation of a value.
The data in the stream must have been written using writeToStream(), or this
will have unpredictable results.
*/
bool equalsWithSameType (const var& other) const noexcept;
static var readFromStream (InputStream& input);

private:

@@ -8583,6 +8649,7 @@ private:
class VariantType_Bool; friend class VariantType_Bool;
class VariantType_String; friend class VariantType_String;
class VariantType_Object; friend class VariantType_Object;
class VariantType_Array; friend class VariantType_Array;
class VariantType_Method; friend class VariantType_Method;

union ValueUnion
@@ -8593,12 +8660,14 @@ private:
double doubleValue;
char stringValue [sizeof (String)];
ReferenceCountedObject* objectValue;
Array<var>* arrayValue;
MethodFunction methodValue;
};

const VariantType* type;
ValueUnion value;

Array<var>* convertToArray();
friend class DynamicObject;
var invokeMethod (DynamicObject*, const var*, int) const;
};
@@ -8938,6 +9007,9 @@ private:
/*** End of inlined file: juce_LinkedListPointer.h ***/

class XmlElement;
#ifndef DOXYGEN
class JSONFormatter;
#endif

/** Holds a set of named var objects.

@@ -8999,7 +9071,7 @@ public:
/** Returns the value of the item at a given index.
The index must be between 0 and size() - 1.
*/
var getValueAt (int index) const;
const var& getValueAt (int index) const;

/** Removes all values. */
void clear();
@@ -9041,6 +9113,8 @@ private:

friend class LinkedListPointer<NamedValue>;
LinkedListPointer<NamedValue> values;

friend class JSONFormatter;
};

#endif // __JUCE_NAMEDVALUESET_JUCEHEADER__
@@ -9439,6 +9513,9 @@ public:
/** Removes all properties and methods from the object. */
void clear();

/** Returns the NamedValueSet that holds the object's properties. */
NamedValueSet& getProperties() noexcept { return properties; }

private:

NamedValueSet properties;
@@ -19285,6 +19362,7 @@ public:
int64 getPosition();
bool setPosition (int64 pos);
bool write (const void* data, int numBytes);
void writeRepeatedByte (uint8 byte, int numTimesToRepeat);

private:

@@ -21122,6 +21200,7 @@ public:
int64 getPosition() { return position; }
bool setPosition (int64 newPosition);
int writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite);
void writeRepeatedByte (uint8 byte, int numTimesToRepeat);

private:

@@ -21130,6 +21209,7 @@ private:
size_t position, size;

void trimExternalBlockSize();
void prepareToWrite (int numBytes);

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryOutputStream);
};
@@ -21802,6 +21882,98 @@ private:
#endif
#ifndef __JUCE_IDENTIFIER_JUCEHEADER__

#endif
#ifndef __JUCE_JSON_JUCEHEADER__

/*** Start of inlined file: juce_JSON.h ***/
#ifndef __JUCE_JSON_JUCEHEADER__
#define __JUCE_JSON_JUCEHEADER__

class InputStream;
class OutputStream;
class File;

/**
Contains static methods for converting JSON-formatted text to and from var objects.

The var class is structurally compatible with JSON-formatted data, so these
functions allow you to parse JSON into a var object, and to convert a var
object to JSON-formatted text.

@see var
*/
class JSON
{
public:

/** Parses a string of JSON-formatted text, and returns a result code containing
any parse errors.

This will return the parsed structure in the parsedResult parameter, and will
return a Result object to indicate whether parsing was successful, and if not,
it will contain an error message.

If you're not interested in the error message, you can use one of the other
shortcut parse methods, which simply return a var::null if the parsing fails.
*/
static Result parse (const String& text, var& parsedResult);

/** Attempts to parse some JSON-formatted text, and returns the result as a var object.

If the parsing fails, this simply returns var::null - if you need to find out more
detail about the parse error, use the alternative parse() method which returns a Result.
*/
static var parse (const String& text);

/** Attempts to parse some JSON-formatted text from a file, and returns the result
as a var object.

Note that this is just a short-cut for reading the entire file into a string and
parsing the result.

If the parsing fails, this simply returns var::null - if you need to find out more
detail about the parse error, use the alternative parse() method which returns a Result.
*/
static var parse (const File& file);

/** Attempts to parse some JSON-formatted text from a stream, and returns the result
as a var object.

Note that this is just a short-cut for reading the entire stream into a string and
parsing the result.

If the parsing fails, this simply returns var::null - if you need to find out more
detail about the parse error, use the alternative parse() method which returns a Result.
*/
static var parse (InputStream& input);

/** Returns a string which contains a JSON-formatted representation of the var object.
If allOnOneLine is true, the result will be compacted into a single line of text
with no carriage-returns. If false, it will be laid-out in a more human-readable format.
@see writeToStream
*/
static String toString (const var& objectToFormat,
bool allOnOneLine = false);

/** Writes a JSON-formatted representation of the var object to the given stream.
If allOnOneLine is true, the result will be compacted into a single line of text
with no carriage-returns. If false, it will be laid-out in a more human-readable format.
@see toString
*/
static void writeToStream (OutputStream& output,
const var& objectToFormat,
bool allOnOneLine = false);

private:

JSON(); // This class can't be instantiated - just use its static methods.
};

#endif // __JUCE_JSON_JUCEHEADER__

/*** End of inlined file: juce_JSON.h ***/


#endif
#ifndef __JUCE_LOCALISEDSTRINGS_JUCEHEADER__



+ 5
- 0
src/containers/juce_NamedValueSet.h View File

@@ -29,6 +29,9 @@
#include "juce_Variant.h"
#include "../containers/juce_LinkedListPointer.h"
class XmlElement;
#ifndef DOXYGEN
class JSONFormatter;
#endif
//==============================================================================
@@ -137,6 +140,8 @@ private:
friend class LinkedListPointer<NamedValue>;
LinkedListPointer<NamedValue> values;
friend class JSONFormatter;
};


+ 169
- 33
src/containers/juce_Variant.cpp View File

@@ -38,7 +38,8 @@ enum VariantStreamMarkers
varMarker_BoolFalse = 3,
varMarker_Double = 4,
varMarker_String = 5,
varMarker_Int64 = 6
varMarker_Int64 = 6,
varMarker_Array = 7
};
//==============================================================================
@@ -54,6 +55,7 @@ public:
virtual String toString (const ValueUnion&) const { return String::empty; }
virtual bool toBool (const ValueUnion&) const noexcept { return false; }
virtual ReferenceCountedObject* toObject (const ValueUnion&) const noexcept { return nullptr; }
virtual Array<var>* toArray (const ValueUnion&) const noexcept { return 0; }
virtual bool isVoid() const noexcept { return false; }
virtual bool isInt() const noexcept { return false; }
@@ -62,6 +64,7 @@ public:
virtual bool isDouble() const noexcept { return false; }
virtual bool isString() const noexcept { return false; }
virtual bool isObject() const noexcept { return false; }
virtual bool isArray() const noexcept { return false; }
virtual bool isMethod() const noexcept { return false; }
virtual void cleanUp (ValueUnion&) const noexcept {}
@@ -256,6 +259,41 @@ public:
}
};
//==============================================================================
class var::VariantType_Array : public var::VariantType
{
public:
VariantType_Array() noexcept {}
static const VariantType_Array instance;
void cleanUp (ValueUnion& data) const noexcept { delete data.arrayValue; }
void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.arrayValue = new Array<var> (*(source.arrayValue)); }
String toString (const ValueUnion&) const { return "[Array]"; }
bool isArray() const noexcept { return true; }
Array<var>* toArray (const ValueUnion& data) const noexcept { return data.arrayValue; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
{
const Array<var>* const otherArray = otherType.toArray (otherData);
return otherArray != nullptr && *otherArray == *(data.arrayValue);
}
void writeToStream (const ValueUnion& data, OutputStream& output) const
{
MemoryOutputStream buffer (512);
const int numItems = data.arrayValue->size();
buffer.writeCompressedInt (numItems);
for (int i = 0; i < numItems; ++i)
data.arrayValue->getReference(i).writeToStream (buffer);
output.writeCompressedInt (1 + buffer.getDataSize());
output.writeByte (varMarker_Array);
output << buffer;
}
};
//==============================================================================
class var::VariantType_Method : public var::VariantType
{
@@ -287,6 +325,7 @@ const var::VariantType_Bool var::VariantType_Bool::instance;
const var::VariantType_Double var::VariantType_Double::instance;
const var::VariantType_String var::VariantType_String::instance;
const var::VariantType_Object var::VariantType_Object::instance;
const var::VariantType_Array var::VariantType_Array::instance;
const var::VariantType_Method var::VariantType_Method::instance;
@@ -343,6 +382,11 @@ var::var (const wchar_t* const value_) : type (&VariantType_String::instance)
new (value.stringValue) String (value_);
}
var::var (const Array<var>& value_) : type (&VariantType_Array::instance)
{
value.arrayValue = new Array<var> (value_);
}
var::var (ReferenceCountedObject* const object) : type (&VariantType_Object::instance)
{
value.objectValue = object;
@@ -364,6 +408,7 @@ bool var::isBool() const noexcept { return type->isBool(); }
bool var::isDouble() const noexcept { return type->isDouble(); }
bool var::isString() const noexcept { return type->isString(); }
bool var::isObject() const noexcept { return type->isObject(); }
bool var::isArray() const noexcept { return type->isArray(); }
bool var::isMethod() const noexcept { return type->isMethod(); }
var::operator int() const noexcept { return type->toInt (value); }
@@ -374,6 +419,7 @@ var::operator double() const noexcept { return type->toDouble
String var::toString() const { return type->toString (value); }
var::operator String() const { return type->toString (value); }
ReferenceCountedObject* var::getObject() const noexcept { return type->toObject (value); }
Array<var>* var::getArray() const noexcept { return type->toArray (value); }
DynamicObject* var::getDynamicObject() const noexcept { return dynamic_cast <DynamicObject*> (getObject()); }
//==============================================================================
@@ -391,6 +437,7 @@ const var& var::operator= (const double newValue) { type->cleanUp (v
const var& var::operator= (const char* const newValue) { var v (newValue); swapWith (v); return *this; }
const var& var::operator= (const wchar_t* const newValue) { var v (newValue); swapWith (v); return *this; }
const var& var::operator= (const String& newValue) { var v (newValue); swapWith (v); return *this; }
const var& var::operator= (const Array<var>& newValue) { var v (newValue); swapWith (v); return *this; }
const var& var::operator= (ReferenceCountedObject* newValue) { var v (newValue); swapWith (v); return *this; }
const var& var::operator= (MethodFunction newValue) { var v (newValue); swapWith (v); return *this; }
@@ -414,38 +461,6 @@ bool operator!= (const var& v1, const char* const v2) { return v1.toString
//==============================================================================
void var::writeToStream (OutputStream& output) const
{
type->writeToStream (value, output);
}
var var::readFromStream (InputStream& input)
{
const int numBytes = input.readCompressedInt();
if (numBytes > 0)
{
switch (input.readByte())
{
case varMarker_Int: return var (input.readInt());
case varMarker_Int64: return var (input.readInt64());
case varMarker_BoolTrue: return var (true);
case varMarker_BoolFalse: return var (false);
case varMarker_Double: return var (input.readDouble());
case varMarker_String:
{
MemoryOutputStream mo;
mo.writeFromInputStream (input, numBytes - 1);
return var (mo.toUTF8());
}
default: input.skipNextBytes (numBytes - 1); break;
}
}
return var::null;
}
var var::operator[] (const Identifier& propertyName) const
{
DynamicObject* const o = getDynamicObject();
@@ -502,5 +517,126 @@ var var::call (const Identifier& method, const var& arg1, const var& arg2, const
return invoke (method, args, 5);
}
//==============================================================================
int var::size() const
{
const Array<var>* const array = getArray();
return array != nullptr ? array->size() : 0;
}
const var& var::operator[] (int arrayIndex) const
{
const Array<var>* const array = getArray();
// When using this method, the var must actually be an array, and the index
// must be in-range!
jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));
return array->getReference (arrayIndex);
}
var& var::operator[] (int arrayIndex)
{
const Array<var>* const array = getArray();
// When using this method, the var must actually be an array, and the index
// must be in-range!
jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));
return array->getReference (arrayIndex);
}
Array<var>* var::convertToArray()
{
Array<var>* array = getArray();
if (array == nullptr)
{
const Array<var> tempVar;
var v (tempVar);
array = v.value.arrayValue;
if (! isVoid())
array->add (*this);
swapWith (v);
}
return array;
}
void var::append (const var& value)
{
convertToArray()->add (value);
}
void var::remove (const int index)
{
Array<var>* const array = getArray();
if (array != nullptr)
array->remove (index);
}
void var::insert (const int index, const var& value)
{
convertToArray()->insert (index, value);
}
void var::resize (const int numArrayElementsWanted)
{
convertToArray()->resize (numArrayElementsWanted);
}
int var::indexOf (const var& value) const
{
const Array<var>* const array = getArray();
return array != nullptr ? array->indexOf (value) : -1;
}
//==============================================================================
void var::writeToStream (OutputStream& output) const
{
type->writeToStream (value, output);
}
var var::readFromStream (InputStream& input)
{
const int numBytes = input.readCompressedInt();
if (numBytes > 0)
{
switch (input.readByte())
{
case varMarker_Int: return var (input.readInt());
case varMarker_Int64: return var (input.readInt64());
case varMarker_BoolTrue: return var (true);
case varMarker_BoolFalse: return var (false);
case varMarker_Double: return var (input.readDouble());
case varMarker_String:
{
MemoryOutputStream mo;
mo.writeFromInputStream (input, numBytes - 1);
return var (mo.toUTF8());
}
case varMarker_Array:
{
var v;
Array<var>* const destArray = v.convertToArray();
for (int i = input.readCompressedInt(); --i >= 0;)
destArray->add (readFromStream (input));
return v;
}
default: input.skipNextBytes (numBytes - 1); break;
}
}
return var::null;
}
END_JUCE_NAMESPACE

+ 86
- 18
src/containers/juce_Variant.h View File

@@ -29,6 +29,7 @@
#include "../text/juce_Identifier.h"
#include "../io/streams/juce_OutputStream.h"
#include "../io/streams/juce_InputStream.h"
#include "../containers/juce_Array.h"
#ifndef DOXYGEN
class ReferenceCountedObject;
@@ -70,6 +71,7 @@ public:
var (const char* value);
var (const wchar_t* value);
var (const String& value);
var (const Array<var>& value);
var (ReferenceCountedObject* object);
var (MethodFunction method) noexcept;
@@ -81,6 +83,7 @@ public:
const var& operator= (const char* value);
const var& operator= (const wchar_t* value);
const var& operator= (const String& value);
const var& operator= (const Array<var>& value);
const var& operator= (ReferenceCountedObject* object);
const var& operator= (MethodFunction method);
@@ -93,6 +96,7 @@ public:
operator double() const noexcept;
operator String() const;
String toString() const;
Array<var>* getArray() const noexcept;
ReferenceCountedObject* getObject() const noexcept;
DynamicObject* getDynamicObject() const noexcept;
@@ -103,25 +107,89 @@ public:
bool isDouble() const noexcept;
bool isString() const noexcept;
bool isObject() const noexcept;
bool isArray() const noexcept;
bool isMethod() const noexcept;
/** Returns true if this var has the same value as the one supplied.
Note that this ignores the type, so a string var "123" and an integer var with the
value 123 are considered to be equal.
@see equalsWithSameType
*/
bool equals (const var& other) const noexcept;
/** Returns true if this var has the same value and type as the one supplied.
This differs from equals() because e.g. "123" and 123 will be considered different.
@see equals
*/
bool equalsWithSameType (const var& other) const noexcept;
//==============================================================================
/** Writes a binary representation of this value to a stream.
The data can be read back later using readFromStream().
/** If the var is an array, this returns the number of elements.
If the var isn't actually an array, this will return 0.
*/
void writeToStream (OutputStream& output) const;
int size() const;
/** If the var is an array, this can be used to return one of its elements.
To call this method, you must make sure that the var is actually an array, and
that the index is a valid number. If these conditions aren't met, behaviour is
undefined.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array<var>.
*/
const var& operator[] (int arrayIndex) const;
/** If the var is an array, this can be used to return one of its elements.
To call this method, you must make sure that the var is actually an array, and
that the index is a valid number. If these conditions aren't met, behaviour is
undefined.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array<var>.
*/
var& operator[] (int arrayIndex);
/** Appends an element to the var, converting it to an array if it isn't already one.
If the var isn't an array, it will be converted to one, and if its value was non-void,
this value will be kept as the first element of the new array. The parameter value
will then be appended to it.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array<var>.
*/
void append (const var& valueToAppend);
/** Inserts an element to the var, converting it to an array if it isn't already one.
If the var isn't an array, it will be converted to one, and if its value was non-void,
this value will be kept as the first element of the new array. The parameter value
will then be inserted into it.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array<var>.
*/
void insert (int index, const var& value);
/** Reads back a stored binary representation of a value.
The data in the stream must have been written using writeToStream(), or this
will have unpredictable results.
/** If the var is an array, this removes one of its elements.
If the index is out-of-range or the var isn't an array, nothing will be done.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array<var>.
*/
static var readFromStream (InputStream& input);
void remove (int index);
/** Treating the var as an array, this resizes it to contain the specified number of elements.
If the var isn't an array, it will be converted to one, and if its value was non-void,
this value will be kept as the first element of the new array before resizing.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array<var>.
*/
void resize (int numArrayElementsWanted);
/** If the var is an array, this searches it for the first occurrence of the specified value,
and returns its index.
If the var isn't an array, or if the value isn't found, this returns -1.
*/
int indexOf (const var& value) const;
//==============================================================================
/** If this variant is an object, this returns one of its properties. */
var operator[] (const Identifier& propertyName) const;
//==============================================================================
/** If this variant is an object, this invokes one of its methods with no arguments. */
var call (const Identifier& method) const;
/** If this variant is an object, this invokes one of its methods with one argument. */
@@ -138,19 +206,16 @@ public:
var invoke (const Identifier& method, const var* arguments, int numArguments) const;
//==============================================================================
/** Returns true if this var has the same value as the one supplied.
Note that this ignores the type, so a string var "123" and an integer var with the
value 123 are considered to be equal.
@see equalsWithSameType
/** Writes a binary representation of this value to a stream.
The data can be read back later using readFromStream().
*/
bool equals (const var& other) const noexcept;
void writeToStream (OutputStream& output) const;
/** Returns true if this var has the same value and type as the one supplied.
This differs from equals() because e.g. "123" and 123 will be considered different.
@see equals
/** Reads back a stored binary representation of a value.
The data in the stream must have been written using writeToStream(), or this
will have unpredictable results.
*/
bool equalsWithSameType (const var& other) const noexcept;
static var readFromStream (InputStream& input);
private:
//==============================================================================
@@ -162,6 +227,7 @@ private:
class VariantType_Bool; friend class VariantType_Bool;
class VariantType_String; friend class VariantType_String;
class VariantType_Object; friend class VariantType_Object;
class VariantType_Array; friend class VariantType_Array;
class VariantType_Method; friend class VariantType_Method;
union ValueUnion
@@ -172,12 +238,14 @@ private:
double doubleValue;
char stringValue [sizeof (String)];
ReferenceCountedObject* objectValue;
Array<var>* arrayValue;
MethodFunction methodValue;
};
const VariantType* type;
ValueUnion value;
Array<var>* convertToArray();
friend class DynamicObject;
var invokeMethod (DynamicObject*, const var*, int) const;
};


+ 1
- 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 97
#define JUCE_BUILDNUMBER 98
/** Current Juce version number.


+ 15
- 0
src/io/files/juce_FileOutputStream.cpp View File

@@ -121,4 +121,19 @@ bool FileOutputStream::write (const void* const src, const int numBytes)
return true;
}
void FileOutputStream::writeRepeatedByte (uint8 byte, int numBytes)
{
if (bytesInBuffer + numBytes < bufferSize)
{
memset (buffer + bytesInBuffer, byte, numBytes);
bytesInBuffer += numBytes;
currentPosition += numBytes;
}
else
{
OutputStream::writeRepeatedByte (byte, numBytes);
}
}
END_JUCE_NAMESPACE

+ 1
- 0
src/io/files/juce_FileOutputStream.h View File

@@ -83,6 +83,7 @@ public:
int64 getPosition();
bool setPosition (int64 pos);
bool write (const void* data, int numBytes);
void writeRepeatedByte (uint8 byte, int numTimesToRepeat);
private:


+ 20
- 5
src/io/streams/juce_MemoryOutputStream.cpp View File

@@ -77,15 +77,19 @@ void MemoryOutputStream::reset() noexcept
size = 0;
}
void MemoryOutputStream::prepareToWrite (int numBytes)
{
const size_t storageNeeded = position + numBytes;
if (storageNeeded >= data.getSize())
data.ensureSize ((storageNeeded + jmin ((int) (storageNeeded / 2), 1024 * 1024) + 32) & ~31);
}
bool MemoryOutputStream::write (const void* const buffer, int howMany)
{
if (howMany > 0)
{
const size_t storageNeeded = position + howMany;
if (storageNeeded >= data.getSize())
data.ensureSize ((storageNeeded + jmin ((int) (storageNeeded / 2), 1024 * 1024) + 32) & ~31);
prepareToWrite (howMany);
memcpy (static_cast<char*> (data.getData()) + position, buffer, howMany);
position += howMany;
size = jmax (size, position);
@@ -94,6 +98,17 @@ bool MemoryOutputStream::write (const void* const buffer, int howMany)
return true;
}
void MemoryOutputStream::writeRepeatedByte (uint8 byte, int howMany)
{
if (howMany > 0)
{
prepareToWrite (howMany);
memset (static_cast<char*> (data.getData()) + position, byte, howMany);
position += howMany;
size = jmax (size, position);
}
}
const void* MemoryOutputStream::getData() const noexcept
{
void* const d = data.getData();


+ 2
- 1
src/io/streams/juce_MemoryOutputStream.h View File

@@ -108,7 +108,7 @@ public:
int64 getPosition() { return position; }
bool setPosition (int64 newPosition);
int writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite);
void writeRepeatedByte (uint8 byte, int numTimesToRepeat);
private:
//==============================================================================
@@ -117,6 +117,7 @@ private:
size_t position, size;
void trimExternalBlockSize();
void prepareToWrite (int numBytes);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryOutputStream);
};


+ 3
- 0
src/juce_core_includes.h View File

@@ -260,6 +260,9 @@
#ifndef __JUCE_IDENTIFIER_JUCEHEADER__
#include "text/juce_Identifier.h"
#endif
#ifndef __JUCE_JSON_JUCEHEADER__
#include "text/juce_JSON.h"
#endif
#ifndef __JUCE_LOCALISEDSTRINGS_JUCEHEADER__
#include "text/juce_LocalisedStrings.h"
#endif


+ 532
- 0
src/text/juce_JSON.cpp View File

@@ -0,0 +1,532 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#include "../core/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_JSON.h"
#include "../io/files/juce_File.h"
#include "../io/streams/juce_MemoryOutputStream.h"
#include "../containers/juce_DynamicObject.h"
//==============================================================================
class JSONParser
{
public:
static Result parseAny (String::CharPointerType& t, var& result)
{
t = t.findEndOfWhitespace();
String::CharPointerType t2 (t);
switch (t2.getAndAdvance())
{
case '{': t = t2; return parseObject (t, result);
case '[': t = t2; return parseArray (t, result);
case '"': t = t2; return parseString (t, result);
case '-':
t2 = t2.findEndOfWhitespace();
if (! CharacterFunctions::isDigit (*t2))
break;
t = t2;
return parseNumber (t, result, true);
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return parseNumber (t, result, false);
case 't': // "true"
if (t2.getAndAdvance() == 'r' && t2.getAndAdvance() == 'u' && t2.getAndAdvance() == 'e')
{
t = t2;
result = var (true);
return Result::ok();
}
break;
case 'f': // "false"
if (t2.getAndAdvance() == 'a' && t2.getAndAdvance() == 'l'
&& t2.getAndAdvance() == 's' && t2.getAndAdvance() == 'e')
{
t = t2;
result = var (false);
return Result::ok();
}
break;
case 'n': // "null"
if (t2.getAndAdvance() == 'u' && t2.getAndAdvance() == 'l' && t2.getAndAdvance() == 'l')
{
t = t2;
result = var::null;
return Result::ok();
}
break;
default:
break;
}
return createFail ("Syntax error", &t);
}
private:
static Result createFail (const char* const message, const String::CharPointerType* location = nullptr)
{
String m (message);
if (location != nullptr)
m << ": \"" << String (*location, 20) << '"';
return Result::fail (m);
}
static Result parseNumber (String::CharPointerType& t, var& result, const bool isNegative)
{
String::CharPointerType oldT (t);
int64 intValue = t.getAndAdvance() - '0';
jassert (intValue >= 0 && intValue < 10);
for (;;)
{
String::CharPointerType previousChar (t);
const juce_wchar c = t.getAndAdvance();
const int digit = ((int) c) - '0';
if (isPositiveAndBelow (digit, 10))
{
intValue = intValue * 10 + digit;
continue;
}
if (c == 'e' || c == 'E' || c == '.')
{
t = oldT;
const double asDouble = CharacterFunctions::readDoubleValue (t);
result = isNegative ? -asDouble : asDouble;
return Result::ok();
}
if (CharacterFunctions::isWhitespace (c)
|| c == ',' || c == '}' || c == ']' || c == 0)
{
t = previousChar;
break;
}
return createFail ("Syntax error in number", &oldT);
}
const int64 correctedValue = isNegative ? -intValue : intValue;
if ((intValue >> 31) != 0)
result = correctedValue;
else
result = (int) correctedValue;
return Result::ok();
}
static Result parseObject (String::CharPointerType& t, var& result)
{
DynamicObject* const resultObject = new DynamicObject();
result = resultObject;
for (;;)
{
t = t.findEndOfWhitespace();
String::CharPointerType oldT (t);
const juce_wchar c = t.getAndAdvance();
if (c == '}')
break;
if (c == 0)
return createFail ("Unexpected end-of-input in object declaration");
if (c == '"')
{
var propertyNameVar;
Result r (parseString (t, propertyNameVar));
if (r.failed())
return r;
const String propertyName (propertyNameVar.toString());
if (propertyName.isNotEmpty())
{
t = t.findEndOfWhitespace();
oldT = t;
const juce_wchar c = t.getAndAdvance();
if (c != ':')
return createFail ("Expected ':', but found", &oldT);
var propertyValue;
Result r (parseAny (t, propertyValue));
if (r.failed())
return r;
resultObject->setProperty (propertyName, propertyValue);
t = t.findEndOfWhitespace();
oldT = t;
const juce_wchar nextChar = t.getAndAdvance();
if (nextChar == ',')
continue;
else if (nextChar == '}')
break;
}
}
return createFail ("Expected object member declaration, but found", &oldT);
}
return Result::ok();
}
static Result parseArray (String::CharPointerType& t, var& result)
{
result = var (Array<var>());
Array<var>* const destArray = result.getArray();
for (;;)
{
t = t.findEndOfWhitespace();
String::CharPointerType oldT (t);
const juce_wchar c = t.getAndAdvance();
if (c == ']')
break;
if (c == 0)
return createFail ("Unexpected end-of-input in array declaration");
t = oldT;
destArray->add (var::null);
Result r (parseAny (t, destArray->getReference (destArray->size() - 1)));
if (r.failed())
return r;
t = t.findEndOfWhitespace();
oldT = t;
const juce_wchar nextChar = t.getAndAdvance();
if (nextChar == ',')
continue;
else if (nextChar == ']')
break;
return createFail ("Expected object array item, but found", &oldT);
}
return Result::ok();
}
static Result parseString (String::CharPointerType& t, var& result)
{
Array<juce_wchar> buffer;
buffer.ensureStorageAllocated (256);
for (;;)
{
juce_wchar c = t.getAndAdvance();
if (c == '"')
break;
if (c == '\\')
{
c = t.getAndAdvance();
switch (c)
{
case '"':
case '\\':
case '/': break;
case 'b': c = '\b'; break;
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'u':
{
c = 0;
for (int i = 4; --i >= 0;)
{
const int digitValue = CharacterFunctions::getHexDigitValue (t.getAndAdvance());
if (digitValue < 0)
return createFail ("Syntax error in unicode escape sequence");
c = (juce_wchar) ((c << 4) + digitValue);
}
break;
}
}
}
if (c == 0)
return createFail ("Unexpected end-of-input in string constant");
buffer.add (c);
}
buffer.add (0);
result = String (CharPointer_UTF32 (buffer.getRawDataPointer()));
return Result::ok();
}
};
//==============================================================================
class JSONFormatter
{
public:
static void write (OutputStream& out, const var& v,
const int indentLevel, const bool allOnOneLine)
{
if (v.isString())
{
writeString (out, v.toString().getCharPointer());
}
else if (v.isVoid())
{
out << "null";
}
else if (v.isBool())
{
out << (static_cast<bool> (v) ? "true" : "false");
}
else if (v.isArray())
{
writeArray (out, *v.getArray(), indentLevel, allOnOneLine);
}
else if (v.isObject())
{
DynamicObject* object = dynamic_cast<DynamicObject*> (v.getObject());
jassert (object != nullptr); // Only DynamicObjects can be converted to JSON!
writeObject (out, *object, indentLevel, allOnOneLine);
}
else
{
jassert (! v.isMethod()); // Can't convert an object with methods to JSON!
out << v.toString();
}
}
private:
enum { indentSize = 2 };
static void writeEscapedChar (OutputStream& out, const unsigned short value)
{
out << "\\u" << String::toHexString ((int) value).paddedLeft ('0', 4);
}
static void writeString (OutputStream& out, String::CharPointerType t)
{
out << '"';
for (;;)
{
const juce_wchar c (t.getAndAdvance());
switch (c)
{
case 0: out << '"'; return;
case '\"': out << "\\\""; break;
case '\\': out << "\\\\"; break;
case '\b': out << "\\b"; break;
case '\f': out << "\\f"; break;
case '\t': out << "\\t"; break;
case '\r': out << "\\r"; break;
case '\n': out << "\\n"; break;
default:
if (c >= 32 && c < 127)
{
out << (char) c;
}
else
{
if (CharPointer_UTF16::getBytesRequiredFor (c) > 2)
{
CharPointer_UTF16::CharType chars[2];
CharPointer_UTF16 utf16 (chars);
utf16.write (c);
for (int i = 0; i < 2; ++i)
writeEscapedChar (out, (unsigned short) chars[i]);
}
else
{
writeEscapedChar (out, (unsigned short) c);
}
}
break;
}
}
}
static void writeSpaces (OutputStream& out, int numSpaces)
{
out.writeRepeatedByte (' ', numSpaces);
}
static void writeArray (OutputStream& out, const Array<var>& array,
const int indentLevel, const bool allOnOneLine)
{
out << '[';
if (! allOnOneLine)
out << newLine;
for (int i = 0; i < array.size(); ++i)
{
if (! allOnOneLine)
writeSpaces (out, indentLevel + indentSize);
write (out, array.getReference(i), indentLevel + indentSize, allOnOneLine);
if (i < array.size() - 1)
{
if (allOnOneLine)
out << ", ";
else
out << ',' << newLine;
}
else if (! allOnOneLine)
out << newLine;
}
if (! allOnOneLine)
writeSpaces (out, indentLevel);
out << ']';
}
static void writeObject (OutputStream& out, DynamicObject& object,
const int indentLevel, const bool allOnOneLine)
{
NamedValueSet& props = object.getProperties();
out << '{';
if (! allOnOneLine)
out << newLine;
LinkedListPointer<NamedValueSet::NamedValue>* i = &(props.values);
for (;;)
{
NamedValueSet::NamedValue* const v = i->get();
if (v == nullptr)
break;
if (! allOnOneLine)
writeSpaces (out, indentLevel + indentSize);
writeString (out, v->name);
out << ": ";
write (out, v->value, indentLevel + indentSize, allOnOneLine);
if (v->nextListItem.get() != nullptr)
{
if (allOnOneLine)
out << ", ";
else
out << ',' << newLine;
}
else if (! allOnOneLine)
out << newLine;
i = &(v->nextListItem);
}
if (! allOnOneLine)
writeSpaces (out, indentLevel);
out << '}';
}
};
//==============================================================================
var JSON::parse (const String& text)
{
var result;
String::CharPointerType t (text.getCharPointer());
if (! JSONParser::parseAny (t, result))
result = var::null;
return result;
}
var JSON::parse (InputStream& input)
{
return parse (input.readEntireStreamAsString());
}
var JSON::parse (const File& file)
{
return parse (file.loadFileAsString());
}
Result JSON::parse (const String& text, var& result)
{
String::CharPointerType t (text.getCharPointer());
return JSONParser::parseAny (t, result);
}
String JSON::toString (const var& data, const bool allOnOneLine)
{
MemoryOutputStream mo (1024);
JSONFormatter::write (mo, data, 0, allOnOneLine);
return mo.toString();
}
void JSON::writeToStream (OutputStream& output, const var& data, const bool allOnOneLine)
{
JSONFormatter::write (output, data, 0, allOnOneLine);
}
END_JUCE_NAMESPACE

+ 115
- 0
src/text/juce_JSON.h View File

@@ -0,0 +1,115 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 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_JSON_JUCEHEADER__
#define __JUCE_JSON_JUCEHEADER__
#include "../core/juce_Result.h"
#include "../containers/juce_Variant.h"
class InputStream;
class OutputStream;
class File;
//==============================================================================
/**
Contains static methods for converting JSON-formatted text to and from var objects.
The var class is structurally compatible with JSON-formatted data, so these
functions allow you to parse JSON into a var object, and to convert a var
object to JSON-formatted text.
@see var
*/
class JSON
{
public:
//==============================================================================
/** Parses a string of JSON-formatted text, and returns a result code containing
any parse errors.
This will return the parsed structure in the parsedResult parameter, and will
return a Result object to indicate whether parsing was successful, and if not,
it will contain an error message.
If you're not interested in the error message, you can use one of the other
shortcut parse methods, which simply return a var::null if the parsing fails.
*/
static Result parse (const String& text, var& parsedResult);
/** Attempts to parse some JSON-formatted text, and returns the result as a var object.
If the parsing fails, this simply returns var::null - if you need to find out more
detail about the parse error, use the alternative parse() method which returns a Result.
*/
static var parse (const String& text);
/** Attempts to parse some JSON-formatted text from a file, and returns the result
as a var object.
Note that this is just a short-cut for reading the entire file into a string and
parsing the result.
If the parsing fails, this simply returns var::null - if you need to find out more
detail about the parse error, use the alternative parse() method which returns a Result.
*/
static var parse (const File& file);
/** Attempts to parse some JSON-formatted text from a stream, and returns the result
as a var object.
Note that this is just a short-cut for reading the entire stream into a string and
parsing the result.
If the parsing fails, this simply returns var::null - if you need to find out more
detail about the parse error, use the alternative parse() method which returns a Result.
*/
static var parse (InputStream& input);
//==============================================================================
/** Returns a string which contains a JSON-formatted representation of the var object.
If allOnOneLine is true, the result will be compacted into a single line of text
with no carriage-returns. If false, it will be laid-out in a more human-readable format.
@see writeToStream
*/
static String toString (const var& objectToFormat,
bool allOnOneLine = false);
/** Writes a JSON-formatted representation of the var object to the given stream.
If allOnOneLine is true, the result will be compacted into a single line of text
with no carriage-returns. If false, it will be laid-out in a more human-readable format.
@see toString
*/
static void writeToStream (OutputStream& output,
const var& objectToFormat,
bool allOnOneLine = false);
private:
//==============================================================================
JSON(); // This class can't be instantiated - just use its static methods.
};
#endif // __JUCE_JSON_JUCEHEADER__

+ 2
- 14
src/text/juce_XmlElement.cpp View File

@@ -193,21 +193,9 @@ namespace XmlOutputFunctions
}
}
void writeSpaces (OutputStream& out, int numSpaces)
void writeSpaces (OutputStream& out, const int numSpaces)
{
if (numSpaces > 0)
{
const char blanks[] = " ";
const int blankSize = (int) numElementsInArray (blanks) - 1;
while (numSpaces > blankSize)
{
out.write (blanks, blankSize);
numSpaces -= blankSize;
}
out.write (blanks, numSpaces);
}
out.writeRepeatedByte (' ', numSpaces);
}
}


Loading…
Cancel
Save