1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-09 23:34:20 +00:00

Javascript: Replace old engine with QuickJS

This commit is contained in:
attila 2023-03-03 22:58:11 +01:00 committed by Anthony Nicholls
parent 3af4adf82d
commit db3c2c6a52
52 changed files with 72999 additions and 1865 deletions

View file

@ -2,6 +2,77 @@
# Version 8.0.0
## Change
The JavascriptEngine::callFunctionObject() function has been removed.
**Possible Issues**
Projects that used the removed function will fail to compile.
**Workaround**
Use the JSObjectCursor::invokeMethod() function to call functions beyond the
root scope.
**Rationale**
The JavascriptEngine's underlying implementation has been changed, and the
DynamicObject type is no longer used for the internal implementation of the
engine. The JSObjectCursor class provides a way to navigate the Javascript
object graph without depending on the type of the engine's internal
implementation.
## Change
The JavascriptEngine::getRootObjectProperties() function returns its result by
value instead of const reference.
**Possible Issues**
Projects that captured the returned value by reference and depended on it being
valid for more than the current function's scope may stop working correctly.
**Workaround**
If the return value is used beyond the calling function's scope it must be
stored in a value.
**Rationale**
The JavascriptEngine's underlying implementation has been changed, and the
NamedValueSet type is no longer used in its internal representation. Hence a new
NamedValueSet object is created during the getRootObjectProperties() function
call.
## Change
JavascriptEngine::evaluate() will now return a void variant if the passed in
code successfully evaluates to void, and only return an undefined variant if
an error occurred during evaluation. The previous implementation would return
var::undefined() in both cases.
**Possible Issues**
Projects that depended on the returned value of JavascriptEngine::evaluate() to
be undefined even during successful evaluation may fail to work correctly.
**Workaround**
Code paths that depend on an undefined variant to be returned should be checked
if they aren't used exclusively to determine evaluation failure. In failed
cases the JavascriptEngine::evaluate() function will continue to return
var::undefined().
**Rationale**
When a Javascript expression successfully evaluates to void, and when it fails
evaluation due to timeout or syntax errors are distinctly different situations
and this should be reflected on the value returned.
## Change
The `WebBrowserComponent::pageAboutToLoad()` function on Android now only
@ -34,6 +105,7 @@ any visible effect, like there was on the other platforms. The fine grained per
resource control was not possible on other platforms. This change makes the
Android implementation more consistent with the other platforms.
## Change
The minimum supported compilers and deployment targets have been updated, with

View file

@ -1047,6 +1047,17 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_core/files/juce_TemporaryFile.h"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.cpp"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.h"
"../../../../../modules/juce_core/javascript/choc/containers/choc_Value.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript_QuickJS.h"
"../../../../../modules/juce_core/javascript/choc/math/choc_MathHelpers.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_Assert.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_DisableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_ReenableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_FloatToString.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_JSON.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_StringUtilities.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_UTF8.h"
"../../../../../modules/juce_core/javascript/juce_Javascript.cpp"
"../../../../../modules/juce_core/javascript/juce_Javascript.h"
"../../../../../modules/juce_core/javascript/juce_JSON.cpp"
@ -3163,6 +3174,17 @@ set_source_files_properties(
"../../../../../modules/juce_core/files/juce_TemporaryFile.h"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.cpp"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.h"
"../../../../../modules/juce_core/javascript/choc/containers/choc_Value.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript_QuickJS.h"
"../../../../../modules/juce_core/javascript/choc/math/choc_MathHelpers.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_Assert.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_DisableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_ReenableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_FloatToString.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_JSON.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_StringUtilities.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_UTF8.h"
"../../../../../modules/juce_core/javascript/juce_Javascript.cpp"
"../../../../../modules/juce_core/javascript/juce_Javascript.h"
"../../../../../modules/juce_core/javascript/juce_JSON.cpp"

View file

@ -3408,6 +3408,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -431,6 +431,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -5331,6 +5349,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -3408,6 +3408,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -431,6 +431,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -5331,6 +5349,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -3408,6 +3408,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -431,6 +431,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -5331,6 +5349,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -52,6 +52,28 @@
#include "../Assets/DemoUtilities.h"
static constexpr const char javascriptSource[] = R"x(/*
Javascript! In this simple demo, the native
code provides an object called 'Demo' which
has a method 'print' that writes to the
console below...
*/
Demo.print ("Hello World in JUCE + Javascript!");
Demo.print ("");
function factorial (n)
{
var total = 1;
while (n > 0)
total = total * n--;
return total;
}
for (var i = 1; i < 10; ++i)
Demo.print ("Factorial of " + i + " = " + factorial (i));
)x";
//==============================================================================
class JavaScriptDemo final : public Component,
private CodeDocument::Listener,
@ -75,28 +97,7 @@ public:
codeDocument.addListener (this);
editor->loadContent (
"/*\n"
" Javascript! In this simple demo, the native\n"
" code provides an object called \'Demo\' which\n"
" has a method \'print\' that writes to the\n"
" console below...\n"
"*/\n"
"\n"
"Demo.print (\"Hello World in JUCE + Javascript!\");\n"
"Demo.print (\"\");\n"
"\n"
"function factorial (n)\n"
"{\n"
" var total = 1;\n"
" while (n > 0)\n"
" total = total * n--;\n"
" return total;\n"
"}\n"
"\n"
"for (var i = 1; i < 10; ++i)\n"
" Demo.print (\"Factorial of \" + i \n"
" + \" = \" + factorial (i));\n");
editor->loadContent (javascriptSource);
setSize (600, 750);
}

View file

@ -906,6 +906,17 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_core/files/juce_TemporaryFile.h"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.cpp"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.h"
"../../../../../modules/juce_core/javascript/choc/containers/choc_Value.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript_QuickJS.h"
"../../../../../modules/juce_core/javascript/choc/math/choc_MathHelpers.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_Assert.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_DisableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_ReenableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_FloatToString.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_JSON.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_StringUtilities.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_UTF8.h"
"../../../../../modules/juce_core/javascript/juce_Javascript.cpp"
"../../../../../modules/juce_core/javascript/juce_Javascript.h"
"../../../../../modules/juce_core/javascript/juce_JSON.cpp"
@ -2704,6 +2715,17 @@ set_source_files_properties(
"../../../../../modules/juce_core/files/juce_TemporaryFile.h"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.cpp"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.h"
"../../../../../modules/juce_core/javascript/choc/containers/choc_Value.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript_QuickJS.h"
"../../../../../modules/juce_core/javascript/choc/math/choc_MathHelpers.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_Assert.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_DisableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_ReenableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_FloatToString.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_JSON.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_StringUtilities.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_UTF8.h"
"../../../../../modules/juce_core/javascript/juce_Javascript.cpp"
"../../../../../modules/juce_core/javascript/juce_Javascript.h"
"../../../../../modules/juce_core/javascript/juce_JSON.cpp"

View file

@ -2932,6 +2932,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -374,6 +374,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -4545,6 +4563,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -939,6 +939,17 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_core/files/juce_TemporaryFile.h"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.cpp"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.h"
"../../../../../modules/juce_core/javascript/choc/containers/choc_Value.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript_QuickJS.h"
"../../../../../modules/juce_core/javascript/choc/math/choc_MathHelpers.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_Assert.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_DisableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_ReenableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_FloatToString.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_JSON.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_StringUtilities.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_UTF8.h"
"../../../../../modules/juce_core/javascript/juce_Javascript.cpp"
"../../../../../modules/juce_core/javascript/juce_Javascript.h"
"../../../../../modules/juce_core/javascript/juce_JSON.cpp"
@ -2890,6 +2901,17 @@ set_source_files_properties(
"../../../../../modules/juce_core/files/juce_TemporaryFile.h"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.cpp"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.h"
"../../../../../modules/juce_core/javascript/choc/containers/choc_Value.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript_QuickJS.h"
"../../../../../modules/juce_core/javascript/choc/math/choc_MathHelpers.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_Assert.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_DisableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_ReenableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_FloatToString.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_JSON.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_StringUtilities.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_UTF8.h"
"../../../../../modules/juce_core/javascript/juce_Javascript.cpp"
"../../../../../modules/juce_core/javascript/juce_Javascript.h"
"../../../../../modules/juce_core/javascript/juce_JSON.cpp"

View file

@ -3112,6 +3112,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -383,6 +383,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -4821,6 +4839,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -3112,6 +3112,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -383,6 +383,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -4821,6 +4839,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -3112,6 +3112,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -383,6 +383,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -4821,6 +4839,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -536,6 +536,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -17,6 +17,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -573,6 +591,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -910,6 +910,17 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_core/files/juce_TemporaryFile.h"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.cpp"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.h"
"../../../../../modules/juce_core/javascript/choc/containers/choc_Value.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript_QuickJS.h"
"../../../../../modules/juce_core/javascript/choc/math/choc_MathHelpers.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_Assert.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_DisableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_ReenableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_FloatToString.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_JSON.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_StringUtilities.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_UTF8.h"
"../../../../../modules/juce_core/javascript/juce_Javascript.cpp"
"../../../../../modules/juce_core/javascript/juce_Javascript.h"
"../../../../../modules/juce_core/javascript/juce_JSON.cpp"
@ -2788,6 +2799,17 @@ set_source_files_properties(
"../../../../../modules/juce_core/files/juce_TemporaryFile.h"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.cpp"
"../../../../../modules/juce_core/files/juce_WildcardFileFilter.h"
"../../../../../modules/juce_core/javascript/choc/containers/choc_Value.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript.h"
"../../../../../modules/juce_core/javascript/choc/javascript/choc_javascript_QuickJS.h"
"../../../../../modules/juce_core/javascript/choc/math/choc_MathHelpers.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_Assert.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_DisableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/platform/choc_ReenableAllWarnings.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_FloatToString.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_JSON.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_StringUtilities.h"
"../../../../../modules/juce_core/javascript/choc/text/choc_UTF8.h"
"../../../../../modules/juce_core/javascript/juce_Javascript.cpp"
"../../../../../modules/juce_core/javascript/juce_Javascript.h"
"../../../../../modules/juce_core/javascript/juce_JSON.cpp"

View file

@ -3023,6 +3023,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -374,6 +374,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -4686,6 +4704,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -1840,6 +1840,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -98,6 +98,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -2664,6 +2682,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -1840,6 +1840,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -98,6 +98,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -2664,6 +2682,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -1840,6 +1840,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -98,6 +98,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -2664,6 +2682,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -3208,6 +3208,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -383,6 +383,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -4935,6 +4953,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -3208,6 +3208,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -383,6 +383,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -4935,6 +4953,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -3208,6 +3208,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -383,6 +383,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -4935,6 +4953,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

View file

@ -2999,6 +2999,17 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_RangedDirectoryIterator.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSON.h"/>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_JSONSerialisation.h"/>

View file

@ -368,6 +368,24 @@
<Filter Include="JUCE Modules\juce_core\files">
<UniqueIdentifier>{7868764A-6572-381A-906C-9C26792A4C29}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\containers">
<UniqueIdentifier>{259B70B2-0C68-1990-EC86-42DAA564D388}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\javascript">
<UniqueIdentifier>{19C3DF40-ABE4-49F7-CDD2-7A592EA01F73}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\math">
<UniqueIdentifier>{20DE6E65-B828-EB00-17F7-541D368DFA9B}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\platform">
<UniqueIdentifier>{5CCB85C1-6052-8F8C-FCA7-E34D5514A0EE}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc\text">
<UniqueIdentifier>{375615B1-7B81-BB18-920B-926E88A78F9A}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript\choc">
<UniqueIdentifier>{17CA846A-C621-9676-4FBD-8B04DBAA4488}</UniqueIdentifier>
</Filter>
<Filter Include="JUCE Modules\juce_core\javascript">
<UniqueIdentifier>{03678508-A517-48BB-FB4A-485628C34E08}</UniqueIdentifier>
</Filter>
@ -4653,6 +4671,39 @@
<ClInclude Include="..\..\..\..\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>JUCE Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\containers\choc_Value.h">
<Filter>JUCE Modules\juce_core\javascript\choc\containers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\javascript\choc_javascript_QuickJS.h">
<Filter>JUCE Modules\juce_core\javascript\choc\javascript</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\math\choc_MathHelpers.h">
<Filter>JUCE Modules\juce_core\javascript\choc\math</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_Assert.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_DisableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\platform\choc_ReenableAllWarnings.h">
<Filter>JUCE Modules\juce_core\javascript\choc\platform</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_FloatToString.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_JSON.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_StringUtilities.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\choc\text\choc_UTF8.h">
<Filter>JUCE Modules\juce_core\javascript\choc\text</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\modules\juce_core\javascript\juce_Javascript.h">
<Filter>JUCE Modules\juce_core\javascript</Filter>
</ClInclude>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,302 @@
//
// ██████ ██  ██  ██████  ██████
// ██      ██  ██ ██    ██ ██       ** Classy Header-Only Classes **
// ██  ███████ ██  ██ ██
// ██  ██   ██ ██  ██ ██ https://github.com/Tracktion/choc
//  ██████ ██  ██  ██████   ██████
//
// CHOC is (C)2022 Tracktion Corporation, and is offered under the terms of the ISC license:
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or
// without fee is hereby granted, provided that the above copyright notice and this permission
// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef CHOC_JAVASCRIPT_HEADER_INCLUDED
#define CHOC_JAVASCRIPT_HEADER_INCLUDED
#include <stdexcept>
#include <functional>
#include <optional>
#include "../containers/choc_Value.h"
#include "../text/choc_JSON.h"
/**
Wrapper classes for encapsulating different javascript engines such as
Duktape and QuickJS.
Just use one of the context-creation functions such as
choc::javascript::createQuickJSContext() to create a context for running
javascript code.
*/
namespace choc::javascript
{
/// This is thrown by any javascript functions that need to report an error
struct Error : public std::runtime_error
{
Error (const std::string& error) : std::runtime_error (error) {}
};
//==============================================================================
/// Helper class to hold and provide access to the arguments in a javascript
/// function callback.
struct ArgumentList
{
const choc::value::Value* args = nullptr;
size_t numArgs = 0;
/// Returns the number of arguments
size_t size() const noexcept { return numArgs; }
/// Returns true if there are no arguments
bool empty() const noexcept { return numArgs == 0; }
/// Returns an argument, or a nullptr if the index is out of range.
const choc::value::Value* operator[] (size_t index) const { return index < numArgs ? args + index : nullptr; }
/// Gets an argument as a primitive type (or a string).
/// If the index is out of range or the object isn't a suitable type,
/// then the default value provided will be returned instead.
template <typename PrimitiveType>
PrimitiveType get (size_t argIndex, PrimitiveType defaultValue = {}) const;
/// Standard iterator
const choc::value::Value* begin() const noexcept { return args; }
const choc::value::Value* end() const noexcept { return args + numArgs; }
};
//==============================================================================
/**
An execution context which you use for running javascript code.
These are really simple to use: call one of the creation functions such
as choc::javascript::createQuickJSContext() which will give you a shared_ptr to
a context. Then you can add any native bindings that you need with
registerFunction(), and call evaluate() or invoke() to execute code or call
functions directly.
These contexts are not thread-safe, so it's up to the caller to handle thread
synchronisation if using a single context from multiple threads.
They're also definitely not realtime-safe: any of the methods may allocate,
block, or make system calls.
*/
class Context
{
public:
/// To create a Context, use a function such as choc::javascript::createQuickJSContext();
Context() = default;
Context (Context&&);
Context& operator= (Context&&);
~Context();
/// When parsing modules, this function is expected to take a path to a module, and
/// to return the content of that module, or an empty optional if not found.
using ReadModuleContentFn = std::function<std::optional<std::string>(std::string_view)>;
//==============================================================================
/// Evaluates the given chunk of javascript.
/// If there are any parse errors, this will throw a choc::javascript::Error exception.
/// If the engine supports modules, then providing a value for the resolveModuleContent
/// function will treat the code as a module and will call your function to read the
/// content of any dependencies.
/// None of the methods in this class are either thread-safe or realtime-safe, so you'll
/// need to organise your own locking if you're calling into a single Context from
/// multiple threads.
choc::value::Value evaluate (const std::string& javascriptCode,
ReadModuleContentFn* resolveModuleContent = nullptr);
/// Attempts to invoke a global function with no arguments.
/// Any errors will throw a choc::javascript::Error exception.
/// None of the methods in this class are either thread-safe or realtime-safe, so you'll
/// need to organise your own locking if you're calling into a single Context from
/// multiple threads.
choc::value::Value invoke (std::string_view functionName);
/// Attempts to invoke a global function with the arguments provided.
/// The arguments can be primitives, strings, choc::value::ValueView or
/// choc::value::Value types.
/// Any errors will throw a choc::javascript::Error exception.
/// None of the methods in this class are either thread-safe or realtime-safe, so you'll
/// need to organise your own locking if you're calling into a single Context from
/// multiple threads.
template <typename... Args>
choc::value::Value invoke (std::string_view functionName, Args&&... args);
/// Attempts to invoke a global function with an array of arguments.
/// The objects in the argument list can be primitives, strings, choc::value::ValueView
/// or choc::value::Value types.
/// Any errors will throw a choc::javascript::Error exception.
/// None of the methods in this class are either thread-safe or realtime-safe, so you'll
/// need to organise your own locking if you're calling into a single Context from
/// multiple threads.
template <typename ArgList>
choc::value::Value invokeWithArgList (std::string_view functionName, const ArgList& args);
/// This is the prototype for a lambda which can be bound as a javascript function.
using NativeFunction = std::function<choc::value::Value(ArgumentList)>;
/// Binds a lambda function to a global name so that javascript code can invoke it.
void registerFunction (const std::string& name, NativeFunction fn);
/// Pumps the message loop in an engine-specific way - may have no effect on some platforms.
void pumpMessageLoop();
//==============================================================================
/// @internal
struct Pimpl;
/// @internal
Context (std::unique_ptr<Pimpl>);
Pimpl* getPimpl() const;
private:
std::unique_ptr<Pimpl> pimpl;
};
//==============================================================================
/// Creates a QuickJS-based context. If you call this, then you'll need to
/// include choc_javascript_QuickJS.h in one (and only one!) of your source files.
Context createQuickJSContext();
/// Creates a Duktape-based context. If you call this, then you'll need to
/// include choc_javascript_Duktape.h in one (and only one!) of your source files.
Context createDuktapeContext();
/// Creates a V8-based context. If you call this, then you'll need to
/// make sure that your project also has the V8 header folder in its
/// search path, and that you statically link the appropriate V8 libs.
Context createV8Context();
}
//==============================================================================
// _ _ _ _
// __| | ___ | |_ __ _ (_)| | ___
// / _` | / _ \| __| / _` || || |/ __|
// | (_| || __/| |_ | (_| || || |\__ \ _ _ _
// \__,_| \___| \__| \__,_||_||_||___/(_)(_)(_)
//
// Code beyond this point is implementation detail...
//
//==============================================================================
namespace choc::javascript
{
template <typename PrimitiveType>
PrimitiveType ArgumentList::get (size_t index, PrimitiveType defaultValue) const
{
if (auto a = (*this)[index])
return a->getWithDefault<PrimitiveType> (defaultValue);
return defaultValue;
}
struct Context::Pimpl
{
Pimpl() = default;
virtual ~Pimpl() = default;
virtual void registerFunction (const std::string&, NativeFunction) = 0;
virtual choc::value::Value evaluate (const std::string&, ReadModuleContentFn*) = 0;
virtual void prepareForCall (std::string_view, uint32_t numArgs) = 0;
virtual choc::value::Value performCall() = 0;
virtual void pushObjectOrArray (const choc::value::ValueView&) = 0;
virtual void pushArg (std::string_view) = 0;
virtual void pushArg (int32_t) = 0;
virtual void pushArg (int64_t) = 0;
virtual void pushArg (uint32_t) = 0;
virtual void pushArg (double) = 0;
virtual void pushArg (bool) = 0;
virtual void pumpMessageLoop() = 0;
void pushArg (const std::string& v) { pushArg (std::string_view (v)); }
void pushArg (const char* v) { pushArg (std::string_view (v)); }
void pushArg (uint64_t v) { pushArg (static_cast<int64_t> (v)); }
void pushArg (float v) { pushArg (static_cast<double> (v)); }
void pushArg (const choc::value::ValueView& v)
{
if (v.isInt32()) return pushArg (v.getInt32());
if (v.isInt64()) return pushArg (v.getInt64());
if (v.isFloat32()) return pushArg (v.getFloat32());
if (v.isFloat64()) return pushArg (v.getFloat64());
if (v.isString()) return pushArg (v.getString());
if (v.isBool()) return pushArg (v.getBool());
if (v.isVoid()) throw Error ("Function arguments cannot be void!");
pushObjectOrArray (v);
}
};
inline Context::Context (std::unique_ptr<Pimpl> p) : pimpl (std::move (p)) {}
inline Context::~Context() = default;
inline Context::Context (Context&&) = default;
inline Context& Context::operator= (Context&&) = default;
inline choc::value::Value Context::invoke (std::string_view functionName)
{
CHOC_ASSERT (pimpl != nullptr); // cannot call this on a moved-from context!
pimpl->prepareForCall (functionName, 0);
return pimpl->performCall();
}
template <typename... Args>
choc::value::Value Context::invoke (std::string_view functionName, Args&&... args)
{
CHOC_ASSERT (pimpl != nullptr); // cannot call this on a moved-from context!
pimpl->prepareForCall (functionName, sizeof...(args));
(pimpl->pushArg (std::forward<Args> (args)), ...);
return pimpl->performCall();
}
template <typename ArgList>
choc::value::Value Context::invokeWithArgList (std::string_view functionName, const ArgList& args)
{
CHOC_ASSERT (pimpl != nullptr); // cannot call this on a moved-from context!
pimpl->prepareForCall (functionName, static_cast<uint32_t> (args.size()));
for (auto& arg : args)
pimpl->pushArg (arg);
return pimpl->performCall();
}
inline void Context::registerFunction (const std::string& name, NativeFunction fn)
{
CHOC_ASSERT (pimpl != nullptr); // cannot call this on a moved-from context!
pimpl->registerFunction (name, std::move (fn));
}
inline choc::value::Value Context::evaluate (const std::string& javascriptCode, ReadModuleContentFn* resolveModule)
{
CHOC_ASSERT (pimpl != nullptr); // cannot call this on a moved-from context!
return pimpl->evaluate (javascriptCode, resolveModule);
}
inline void Context::pumpMessageLoop()
{
CHOC_ASSERT (pimpl != nullptr); // cannot call this on a moved-from context!
pimpl->pumpMessageLoop();
}
Context::Pimpl* Context::getPimpl() const
{
return pimpl.get();
}
} // namespace choc::javascript
#endif // CHOC_JAVASCRIPT_HEADER_INCLUDED
#ifdef CHOC_JAVASCRIPT_IMPLEMENTATION
// The way the javascript classes work has changed: instead of
// setting CHOC_JAVASCRIPT_IMPLEMENTATION in one of your source files, just
// include the actual engine that you want to use, e.g. choc_javascript_QuickJS.h
// in (only!) one of your source files, and use that to create instances of that engine.
#error "CHOC_JAVASCRIPT_IMPLEMENTATION is deprecated"
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,118 @@
//
// ██████ ██  ██  ██████  ██████
// ██      ██  ██ ██    ██ ██       ** Classy Header-Only Classes **
// ██  ███████ ██  ██ ██
// ██  ██   ██ ██  ██ ██ https://github.com/Tracktion/choc
//  ██████ ██  ██  ██████   ██████
//
// CHOC is (C)2022 Tracktion Corporation, and is offered under the terms of the ISC license:
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or
// without fee is hereby granted, provided that the above copyright notice and this permission
// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef CHOC_MATH_HELPERS_HEADER_INCLUDED
#define CHOC_MATH_HELPERS_HEADER_INCLUDED
#include <cstdlib>
#include <cstdint>
#ifdef _MSC_VER
#include <intrin.h>
#pragma intrinsic (_BitScanReverse)
#ifdef _WIN64
#pragma intrinsic (_BitScanReverse64)
#endif
#ifdef _M_X64
#pragma intrinsic (_umul128)
#define CHOC_HAS_UMUL128 1
#endif
#endif
namespace choc::math
{
//==============================================================================
/// Returns true if the given value is 2^something
template <typename Integer>
constexpr bool isPowerOf2 (Integer n) { return n > 0 && (n & (n - 1)) == 0; }
// Returns the number of contiguously-clear upper bits in a 32-bit value
/// Note this operation is undefined for value == 0!
inline uint32_t countUpperClearBits (uint32_t value)
{
#ifdef _MSC_VER
unsigned long result = 0;
_BitScanReverse (&result, static_cast<unsigned long> (value));
return static_cast<uint32_t> (31u - result);
#else
return static_cast<uint32_t> (__builtin_clz (value));
#endif
}
/// Returns the number of contiguously-clear upper bits in a 64-bit value.
/// Note this operation is undefined for value == 0!
inline uint32_t countUpperClearBits (uint64_t value)
{
#ifdef _MSC_VER
unsigned long result = 0;
#ifdef _WIN64
_BitScanReverse64 (&result, value);
#else
if (_BitScanReverse (&result, static_cast<unsigned long> (value >> 32))) return static_cast<uint32_t> (31u - result);
_BitScanReverse (&result, static_cast<unsigned long> (value));
#endif
return static_cast<uint32_t> (63u - result);
#else
return static_cast<uint32_t> (__builtin_clzll (value));
#endif
}
/// Returns the number of decimal digits required to print a given unsigned number
inline int getNumDecimalDigits (uint32_t n)
{
return n < 1000 ? (n < 10 ? 1 : (n < 100 ? 2 : 3))
: n < 1000000 ? (n < 10000 ? 4 : (n < 100000 ? 5 : 6))
: n < 100000000 ? (n < 10000000 ? 7 : 8)
: n < 1000000000 ? 9 : 10;
}
//==============================================================================
/// Used as a return type for multiply128()
struct Int128
{
uint64_t high, low;
};
/// A cross-platform function to multiply two 64-bit numbers and return a 128-bit result
inline Int128 multiply128 (uint64_t a, uint64_t b)
{
#if CHOC_HAS_UMUL128
Int128 result;
result.low = _umul128 (a, b, &result.high);
return result;
#elif __LP64__
auto total = static_cast<unsigned __int128> (a) * static_cast<unsigned __int128> (b);
return { static_cast<uint64_t> (total >> 64), static_cast<uint64_t> (total) };
#else
uint64_t a0 = static_cast<uint32_t> (a), a1 = a >> 32,
b0 = static_cast<uint32_t> (b), b1 = b >> 32;
auto p10 = a1 * b0, p00 = a0 * b0,
p11 = a1 * b1, p01 = a0 * b1;
auto middleBits = p10 + static_cast<uint32_t> (p01) + (p00 >> 32);
return { p11 + (middleBits >> 32) + (p01 >> 32), (middleBits << 32) | static_cast<uint32_t> (p00) };
#endif
}
} // namespace choc::math
#endif

View file

@ -0,0 +1,36 @@
//
// ██████ ██  ██  ██████  ██████
// ██      ██  ██ ██    ██ ██       ** Classy Header-Only Classes **
// ██  ███████ ██  ██ ██
// ██  ██   ██ ██  ██ ██ https://github.com/Tracktion/choc
//  ██████ ██  ██  ██████   ██████
//
// CHOC is (C)2022 Tracktion Corporation, and is offered under the terms of the ISC license:
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or
// without fee is hereby granted, provided that the above copyright notice and this permission
// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef CHOC_ASSERT_HEADER_INCLUDED
#define CHOC_ASSERT_HEADER_INCLUDED
// If the project doesn't define a custom implementation for CHOC_ASSERT, the default
// behaviour is just to call the normal system assert()
#ifndef CHOC_ASSERT
#include <cassert>
#define CHOC_ASSERT(x) assert(x);
#endif
// It's never a smart idea to include any C headers before your C++ ones, as they
// often pollute your namespace with all kinds of dangerous macros like these ones.
// This file is included by many of the choc headers, so is a convenient place to
// undef these.
#undef max
#undef min
#endif // CHOC_ASSERT_HEADER_INCLUDED

View file

@ -0,0 +1,78 @@
//
// ██████ ██  ██  ██████  ██████
// ██      ██  ██ ██    ██ ██       ** Classy Header-Only Classes **
// ██  ███████ ██  ██ ██
// ██  ██   ██ ██  ██ ██ https://github.com/Tracktion/choc
//  ██████ ██  ██  ██████   ██████
//
// CHOC is (C)2022 Tracktion Corporation, and is offered under the terms of the ISC license:
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or
// without fee is hereby granted, provided that the above copyright notice and this permission
// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/*
Sometimes you inevitably have to include some 3rd-party headers in your code, and it's
depressing how often even the most widely-used libraries are full of poorly-written
code that triggers all kinds of compiler warnings.
Obviously you're a proper programmer who always has warnings turned up to full, and "-Werror"
enabled, so rather than having to compromise your own standards to work around other people's
laziness, this header provides an easy way to locally disable warnings by sandwiching your
3rd-party headers between includes of these two files, e.g:
#include "choc_DisableAllWarnings.h"
#include "SloppilyWrittenButEssentialLibraryCode.h"
#include "choc_ReenableAllWarnings.h"
*/
#if __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Weverything"
#elif __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wall"
#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wfloat-conversion"
#pragma GCC diagnostic ignored "-Wswitch-enum"
#pragma GCC diagnostic ignored "-Wswitch"
#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC diagnostic ignored "-Wsubobject-linkage"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wredundant-move"
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
#pragma GCC diagnostic ignored "-Wc99-extensions"
#pragma GCC diagnostic ignored "-Wmisleading-indentation"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#pragma GCC diagnostic ignored "-Wcast-function-type"
#pragma GCC diagnostic ignored "-Wunused-label"
#pragma GCC diagnostic ignored "-Wnarrowing"
#pragma GCC diagnostic ignored "-Wparentheses"
#pragma GCC diagnostic ignored "-Wwrite-strings"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#pragma GCC diagnostic ignored "-Wfloat-equal"
#ifndef __MINGW32__
#pragma GCC diagnostic ignored "-Wredundant-move"
#endif
#else
#pragma warning (push, 0)
#pragma warning (disable: 4702)
#pragma warning (disable: 4706)
#endif

View file

@ -0,0 +1,30 @@
//
// ██████ ██  ██  ██████  ██████
// ██      ██  ██ ██    ██ ██       ** Classy Header-Only Classes **
// ██  ███████ ██  ██ ██
// ██  ██   ██ ██  ██ ██ https://github.com/Tracktion/choc
//  ██████ ██  ██  ██████   ██████
//
// CHOC is (C)2022 Tracktion Corporation, and is offered under the terms of the ISC license:
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or
// without fee is hereby granted, provided that the above copyright notice and this permission
// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// This file re-enables the warnings that were turned off by choc_DisableAllWarnings.h
// So when you have to include some crappy 3rd-party code which is full of warnings, you
// can sandwich it between includes of choc_DisableAllWarnings.h and choc_ReenableAllWarnings.h
#if __clang__
#pragma clang diagnostic pop
#elif __GNUC__
#pragma GCC diagnostic pop
#else
#pragma warning (pop)
#endif

View file

@ -0,0 +1,397 @@
//
// ██████ ██  ██  ██████  ██████
// ██      ██  ██ ██    ██ ██       ** Classy Header-Only Classes **
// ██  ███████ ██  ██ ██
// ██  ██   ██ ██  ██ ██ https://github.com/Tracktion/choc
//  ██████ ██  ██  ██████   ██████
//
// CHOC is (C)2022 Tracktion Corporation, and is offered under the terms of the ISC license:
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or
// without fee is hereby granted, provided that the above copyright notice and this permission
// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef CHOC_FLOAT_TO_STRING_HEADER_INCLUDED
#define CHOC_FLOAT_TO_STRING_HEADER_INCLUDED
#include <cstring>
#include <string>
#include "../math/choc_MathHelpers.h"
namespace choc::text
{
//==============================================================================
/** Converts a 32-bit float to an accurate, round-trip-safe string.
The algorithm used is "Grisu3" from the paper "Printing Floating-Point Numbers
Quickly and Accurately with Integers" by Florian Loitsch.
*/
std::string floatToString (float value);
/** Converts a 64-bit double to an accurate, round-trip-safe string.
The algorithm used is "Grisu3" from the paper "Printing Floating-Point Numbers
Quickly and Accurately with Integers" by Florian Loitsch.
*/
std::string floatToString (double value);
//==============================================================================
/** Converts a 32-bit float to an accurate, round-trip-safe string.
If maxDecimalPlaces is -1, a default is used.
If omitDecimalPointForRoundNumbers is true, then values such as "2.0" are returned
without the decimal point, e.g. simply "2".
The algorithm used is "Grisu3" from the paper "Printing Floating-Point Numbers
Quickly and Accurately with Integers" by Florian Loitsch.
*/
std::string floatToString (float value, int maxDecimalPlaces, bool omitDecimalPointForRoundNumbers = false);
/** Converts a 64-bit double to an accurate, round-trip-safe string.
If maxDecimalPlaces is -1, a default is used.
If omitDecimalPointForRoundNumbers is true, then values such as "2.0" are returned
without the decimal point, e.g. simply "2".
The algorithm used is "Grisu3" from the paper "Printing Floating-Point Numbers
Quickly and Accurately with Integers" by Florian Loitsch.
*/
std::string floatToString (double value, int maxDecimalPlaces, bool omitDecimalPointForRoundNumbers = false);
//==============================================================================
/** Helper class containing its own buffer for converting a float or double to a string.
The algorithm is "Grisu3" from the paper "Printing Floating-Point Numbers
Quickly and Accurately with Integers" by Florian Loitsch.
To use, just construct a FloatToStringBuffer with the value, and use its begin()/end()
methods to iterate the result. Or use the floatToString() functions to just convert a
value directly to a std::string.
*/
template <typename FloatOrDouble>
struct FloatToStringBuffer
{
FloatToStringBuffer (FloatOrDouble value, int maxDecimalPlaces, bool omitPointIfPossible)
: stringEnd (writeAndGetEnd (storage, value, maxDecimalPlaces, omitPointIfPossible)) {}
const char* begin() const { return storage; }
const char* end() const { return stringEnd; }
std::string toString() const { return std::string (begin(), end()); }
private:
//==============================================================================
static_assert (std::is_same<const float, const FloatOrDouble>::value || std::is_same<const double, const FloatOrDouble>::value,
"This class can only handle float or double template types");
char storage[32];
const char* stringEnd;
struct MantissaAndExponent
{
uint64_t mantissa;
int32_t exponent;
static constexpr MantissaAndExponent create (uint64_t floatBits, uint64_t significand)
{
constexpr int exponentBias = (sizeof (FloatOrDouble) == 8 ? 0x3ff : 0x7f) + numSignificandBits;
auto explonentPlusBias = static_cast<int> ((floatBits & exponentMask) >> numSignificandBits);
return explonentPlusBias == 0 ? MantissaAndExponent { significand, 1 - exponentBias }
: MantissaAndExponent { significand + hiddenBit, explonentPlusBias - exponentBias };
}
constexpr MantissaAndExponent operator* (MantissaAndExponent rhs) const
{
auto mantissaProduct = math::multiply128 (mantissa, rhs.mantissa);
return { mantissaProduct.high + (mantissaProduct.low >> 63), exponent + rhs.exponent + 64 };
}
constexpr MantissaAndExponent shiftedUp (int numBits) const { return { mantissa << numBits, exponent - numBits }; }
constexpr MantissaAndExponent normalized() const { return shiftedUp (static_cast<int> (math::countUpperClearBits (mantissa))); }
};
static uint32_t generateDigits (char* buffer, MantissaAndExponent upperBound, uint64_t mantissaDiff, uint64_t delta, int& K)
{
uint32_t length = 0;
const auto one = MantissaAndExponent { 1ull << -upperBound.exponent, upperBound.exponent };
auto p1 = static_cast<uint32_t> (upperBound.mantissa >> -one.exponent);
auto p2 = upperBound.mantissa & (one.mantissa - 1);
auto numDigits = math::getNumDecimalDigits (p1);
for (;;)
{
auto digit = p1;
switch (--numDigits)
{
case 0: p1 = 0; break;
case 1: digit /= powersOf10[1]; p1 %= powersOf10[1]; break;
case 2: digit /= powersOf10[2]; p1 %= powersOf10[2]; break;
case 3: digit /= powersOf10[3]; p1 %= powersOf10[3]; break;
case 4: digit /= powersOf10[4]; p1 %= powersOf10[4]; break;
case 5: digit /= powersOf10[5]; p1 %= powersOf10[5]; break;
case 6: digit /= powersOf10[6]; p1 %= powersOf10[6]; break;
case 7: digit /= powersOf10[7]; p1 %= powersOf10[7]; break;
case 8: digit /= powersOf10[8]; p1 %= powersOf10[8]; break;
default: break;
}
writeDigitIfNotLeadingZero (buffer, length, digit);
auto rest = p2 + (static_cast<uint64_t> (p1) << -one.exponent);
if (rest <= delta)
{
K += numDigits;
roundFinalDigit (buffer, length, delta, rest, static_cast<uint64_t> (powersOf10[numDigits]) << -one.exponent, mantissaDiff);
return length;
}
if (numDigits == 0)
{
for (;;)
{
delta *= 10;
p2 *= 10;
--numDigits;
writeDigitIfNotLeadingZero (buffer, length, static_cast<uint32_t> (p2 >> -one.exponent));
p2 &= one.mantissa - 1;
if (p2 < delta)
{
K += numDigits;
roundFinalDigit (buffer, length, delta, p2, one.mantissa, numDigits > -9 ? mantissaDiff * powersOf10[-numDigits] : 0);
return length;
}
}
}
}
}
static void roundFinalDigit (char* buffer, uint32_t length, uint64_t delta, uint64_t rest, uint64_t tenToPowerNumDigits, uint64_t diff)
{
while (rest < diff && delta - rest >= tenToPowerNumDigits
&& (rest + tenToPowerNumDigits < diff || diff - rest > rest + tenToPowerNumDigits - diff))
{
--(buffer[length - 1]);
rest += tenToPowerNumDigits;
}
}
[[nodiscard]] static char* write (char* dest, char c) { *dest = c; return dest + 1; }
template <typename... Chars> static char* write (char* dest, char first, Chars... others) { return write (write (dest, first), others...); }
[[nodiscard]] static char* writeDigit (char* dest, int digit) { return write (dest, static_cast<char> (digit + '0')); }
template <typename... Chars> static char* writeDigit (char* dest, int d, Chars... others) { return writeDigit (writeDigit (dest, d), others...); }
[[nodiscard]] static char* writeZero (char* dest) { return write (dest, '0', '.', '0'); }
[[nodiscard]] static char* writeExponent (char* dest, int e) { return writeShortInteger (write (dest, 'e'), e); }
static void writeDigitIfNotLeadingZero (char* dest, uint32_t& length, uint32_t digit) { if (digit != 0 || length != 0) dest[length++] = static_cast<char> (digit + '0'); }
[[nodiscard]] static char* writeShortInteger (char* dest, int n)
{
if (n < 0) return writeShortInteger (write (dest, '-'), -n);
if (n >= 100) return writeDigit (dest, n / 100, (n / 10) % 10, n % 10);
if (n >= 10) return writeDigit (dest, n / 10, n % 10);
return writeDigit (dest, n);
}
static void insertChar (char* dest, uint32_t length, char charToInsert, uint32_t numRepetitions)
{
std::memmove (dest + numRepetitions, dest, (size_t) length);
for (uint32_t i = 0; i < numRepetitions; ++i)
dest[i] = charToInsert;
}
static char* writeAsExponentNotation (char* dest, uint32_t totalLength, int exponent)
{
if (totalLength == 1)
return writeExponent (dest + 1, exponent);
insertChar (dest + 1, totalLength - 1, '.', 1);
while (dest[totalLength] == '0' && totalLength > 2)
--totalLength;
return writeExponent (dest + (totalLength + 1), exponent);
}
static char* writeWithoutExponentLessThan1 (char* dest, uint32_t length, int mantissaDigits, int maxDecimalPlaces)
{
auto numPaddingZeros = static_cast<uint32_t> (2 - mantissaDigits);
insertChar (dest, length, '0', numPaddingZeros);
dest[1] = '.';
if (static_cast<int> (length) > maxDecimalPlaces + mantissaDigits)
{
for (int i = maxDecimalPlaces + 1; i > 2; --i)
if (dest[i] != '0')
return dest + (i + 1);
return dest + 3;
}
length += numPaddingZeros;
while (dest[length - 1] == '0' && length > 3)
--length;
return dest + length;
}
static char* writeWithoutExponentGreaterThan1 (char* dest, uint32_t totalLength, uint32_t mantissaLength, int maxDecimalPlaces, int K)
{
if (K >= 0)
{
dest += totalLength;
for (auto i = totalLength; i < mantissaLength; ++i)
dest = write (dest, '0');
return write (dest, '.', '0');
}
insertChar (dest + mantissaLength, totalLength - mantissaLength, '.', 1);
if (K + maxDecimalPlaces >= 0)
return dest + (totalLength + 1);
for (auto i = static_cast<int> (mantissaLength) + maxDecimalPlaces; i > static_cast<int> (mantissaLength + 1); --i)
if (dest[i] != '0')
return dest + (i + 1);
return dest + (mantissaLength + 2);
}
struct Limits
{
constexpr Limits (MantissaAndExponent value)
{
upper = { (value.mantissa << 1) + 1, value.exponent - 1 };
while ((upper.mantissa & (hiddenBit << 1)) == 0)
upper = upper.shiftedUp (1);
upper = upper.shiftedUp (static_cast<int> (sizeof (upper.mantissa) * 8 - numSignificandBits - 2));
lower = value.mantissa == hiddenBit ? MantissaAndExponent { (value.mantissa << 2) - 1, value.exponent - 2 }
: MantissaAndExponent { (value.mantissa << 1) - 1, value.exponent - 1 };
lower.mantissa <<= lower.exponent - upper.exponent;
lower.exponent = upper.exponent;
}
MantissaAndExponent lower, upper;
};
static const char* writeAndGetEnd (char* pos, FloatOrDouble value, int maxDecimalPlaces, bool omitPointIfPossible)
{
auto startPos = pos;
auto floatBits = getFloatBits (value);
if ((floatBits & signMask) == 0)
{
if (isZero (floatBits)) return writeZero (pos);
}
else
{
pos = write (pos, '-');
if (isZero (floatBits)) return writeZero (pos);
value = -value;
floatBits &= ~signMask;
}
if (floatBits == nanBits) return write (pos, 'n', 'a', 'n');
if (floatBits == infBits) return write (pos, 'i', 'n', 'f');
auto v = MantissaAndExponent::create (floatBits, floatBits & significandMask);
Limits limits (v);
int K;
auto powerOf10 = createPowerOf10 (limits.upper.exponent, K);
auto w = powerOf10 * v.normalized();
auto upperBound = powerOf10 * limits.upper;
upperBound.mantissa--;
auto lowerBound = powerOf10 * limits.lower;
lowerBound.mantissa++;
auto totalLength = generateDigits (pos, upperBound, upperBound.mantissa - w.mantissa, upperBound.mantissa - lowerBound.mantissa, K);
auto end = addDecimalPointAndExponent (pos, totalLength, K, maxDecimalPlaces < 0 ? defaultNumDecimalPlaces : maxDecimalPlaces);
if (omitPointIfPossible && end > startPos + 1 && end[-1] == '0' && end[-2] == '.')
end -= 2;
return end;
}
static const char* addDecimalPointAndExponent (char* pos, uint32_t totalLength, int K, int maxDecimalPlaces)
{
auto mantissaDigits = static_cast<int> (totalLength) + K;
if (mantissaDigits < -maxDecimalPlaces) return writeZero (pos);
if (mantissaDigits <= 0 && mantissaDigits > -6) return writeWithoutExponentLessThan1 (pos, totalLength, mantissaDigits, maxDecimalPlaces);
if (mantissaDigits > 0 && mantissaDigits <= 21) return writeWithoutExponentGreaterThan1 (pos, totalLength, static_cast<uint32_t> (mantissaDigits), maxDecimalPlaces, K);
return writeAsExponentNotation (pos, totalLength, mantissaDigits - 1);
}
static uint64_t getFloatBits (double value) { uint64_t i; memcpy (&i, &value, sizeof (i)); return i; }
static uint64_t getFloatBits (float value) { uint32_t i; memcpy (&i, &value, sizeof (i)); return i; }
static bool isZero (uint64_t floatBits) { return (floatBits & (exponentMask | significandMask)) == 0; }
static constexpr int defaultNumDecimalPlaces = 324;
static constexpr int numSignificandBits = sizeof (FloatOrDouble) == 8 ? 52 : 23;
static constexpr uint64_t signMask = 1ull << (sizeof (FloatOrDouble) * 8 - 1);
static constexpr uint64_t hiddenBit = 1ull << numSignificandBits;
static constexpr uint64_t significandMask = hiddenBit - 1;
static constexpr uint64_t exponentMask = sizeof (FloatOrDouble) == 8 ? 0x7ff0000000000000ull : 0x7f800000ull;
static constexpr uint64_t nanBits = sizeof (FloatOrDouble) == 8 ? 0x7ff8000000000000ull : 0x7fc00000ull;
static constexpr uint64_t infBits = sizeof (FloatOrDouble) == 8 ? 0x7ff0000000000000ull : 0x7f800000ull;
static constexpr uint32_t powersOf10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
static MantissaAndExponent createPowerOf10 (int exponentBase2, int& K)
{
static constexpr MantissaAndExponent powerOf10List[] =
{
{ 0xfa8fd5a0081c0288ull, -1220 }, { 0xbaaee17fa23ebf76ull, -1193 }, { 0x8b16fb203055ac76ull, -1166 }, { 0xcf42894a5dce35eaull, -1140 }, { 0x9a6bb0aa55653b2dull, -1113 },
{ 0xe61acf033d1a45dfull, -1087 }, { 0xab70fe17c79ac6caull, -1060 }, { 0xff77b1fcbebcdc4full, -1034 }, { 0xbe5691ef416bd60cull, -1007 }, { 0x8dd01fad907ffc3cull, -980 },
{ 0xd3515c2831559a83ull, -954 }, { 0x9d71ac8fada6c9b5ull, -927 }, { 0xea9c227723ee8bcbull, -901 }, { 0xaecc49914078536dull, -874 }, { 0x823c12795db6ce57ull, -847 },
{ 0xc21094364dfb5637ull, -821 }, { 0x9096ea6f3848984full, -794 }, { 0xd77485cb25823ac7ull, -768 }, { 0xa086cfcd97bf97f4ull, -741 }, { 0xef340a98172aace5ull, -715 },
{ 0xb23867fb2a35b28eull, -688 }, { 0x84c8d4dfd2c63f3bull, -661 }, { 0xc5dd44271ad3cdbaull, -635 }, { 0x936b9fcebb25c996ull, -608 }, { 0xdbac6c247d62a584ull, -582 },
{ 0xa3ab66580d5fdaf6ull, -555 }, { 0xf3e2f893dec3f126ull, -529 }, { 0xb5b5ada8aaff80b8ull, -502 }, { 0x87625f056c7c4a8bull, -475 }, { 0xc9bcff6034c13053ull, -449 },
{ 0x964e858c91ba2655ull, -422 }, { 0xdff9772470297ebdull, -396 }, { 0xa6dfbd9fb8e5b88full, -369 }, { 0xf8a95fcf88747d94ull, -343 }, { 0xb94470938fa89bcfull, -316 },
{ 0x8a08f0f8bf0f156bull, -289 }, { 0xcdb02555653131b6ull, -263 }, { 0x993fe2c6d07b7facull, -236 }, { 0xe45c10c42a2b3b06ull, -210 }, { 0xaa242499697392d3ull, -183 },
{ 0xfd87b5f28300ca0eull, -157 }, { 0xbce5086492111aebull, -130 }, { 0x8cbccc096f5088ccull, -103 }, { 0xd1b71758e219652cull, -77 }, { 0x9c40000000000000ull, -50 },
{ 0xe8d4a51000000000ull, -24 }, { 0xad78ebc5ac620000ull, 3 }, { 0x813f3978f8940984ull, 30 }, { 0xc097ce7bc90715b3ull, 56 }, { 0x8f7e32ce7bea5c70ull, 83 },
{ 0xd5d238a4abe98068ull, 109 }, { 0x9f4f2726179a2245ull, 136 }, { 0xed63a231d4c4fb27ull, 162 }, { 0xb0de65388cc8ada8ull, 189 }, { 0x83c7088e1aab65dbull, 216 },
{ 0xc45d1df942711d9aull, 242 }, { 0x924d692ca61be758ull, 269 }, { 0xda01ee641a708deaull, 295 }, { 0xa26da3999aef774aull, 322 }, { 0xf209787bb47d6b85ull, 348 },
{ 0xb454e4a179dd1877ull, 375 }, { 0x865b86925b9bc5c2ull, 402 }, { 0xc83553c5c8965d3dull, 428 }, { 0x952ab45cfa97a0b3ull, 455 }, { 0xde469fbd99a05fe3ull, 481 },
{ 0xa59bc234db398c25ull, 508 }, { 0xf6c69a72a3989f5cull, 534 }, { 0xb7dcbf5354e9beceull, 561 }, { 0x88fcf317f22241e2ull, 588 }, { 0xcc20ce9bd35c78a5ull, 614 },
{ 0x98165af37b2153dfull, 641 }, { 0xe2a0b5dc971f303aull, 667 }, { 0xa8d9d1535ce3b396ull, 694 }, { 0xfb9b7cd9a4a7443cull, 720 }, { 0xbb764c4ca7a44410ull, 747 },
{ 0x8bab8eefb6409c1aull, 774 }, { 0xd01fef10a657842cull, 800 }, { 0x9b10a4e5e9913129ull, 827 }, { 0xe7109bfba19c0c9dull, 853 }, { 0xac2820d9623bf429ull, 880 },
{ 0x80444b5e7aa7cf85ull, 907 }, { 0xbf21e44003acdd2dull, 933 }, { 0x8e679c2f5e44ff8full, 960 }, { 0xd433179d9c8cb841ull, 986 }, { 0x9e19db92b4e31ba9ull, 1013 },
{ 0xeb96bf6ebadf77d9ull, 1039 }, { 0xaf87023b9bf0ee6bull, 1066 }
};
auto dk = (exponentBase2 + 61) * -0.30102999566398114;
auto ik = static_cast<int> (dk);
auto index = ((ik + (dk > ik ? 348 : 347)) >> 3) + 1;
K = 348 - (index << 3);
return powerOf10List[index];
}
};
inline std::string floatToString (float value) { return FloatToStringBuffer<float> (value, -1, false).toString(); }
inline std::string floatToString (double value) { return FloatToStringBuffer<double> (value, -1, false).toString(); }
inline std::string floatToString (float value, int maxDecimals, bool omitPointIfPossible) { return FloatToStringBuffer<float> (value, maxDecimals, omitPointIfPossible).toString(); }
inline std::string floatToString (double value, int maxDecimals, bool omitPointIfPossible) { return FloatToStringBuffer<double> (value, maxDecimals, omitPointIfPossible).toString(); }
} // namespace choc::text
#endif

View file

@ -0,0 +1,561 @@
//
// ██████ ██  ██  ██████  ██████
// ██      ██  ██ ██    ██ ██       ** Classy Header-Only Classes **
// ██  ███████ ██  ██ ██
// ██  ██   ██ ██  ██ ██ https://github.com/Tracktion/choc
//  ██████ ██  ██  ██████   ██████
//
// CHOC is (C)2022 Tracktion Corporation, and is offered under the terms of the ISC license:
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or
// without fee is hereby granted, provided that the above copyright notice and this permission
// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef CHOC_JSON_HEADER_INCLUDED
#define CHOC_JSON_HEADER_INCLUDED
#include <limits>
#include <sstream>
#include <string_view>
#include <stdexcept>
#include "choc_UTF8.h"
#include "choc_FloatToString.h"
#include "../containers/choc_Value.h"
#undef max // It's never a smart idea to include any C headers before your C++ ones, as it
#undef min // risks polluting your namespace with all kinds of dangerous macros like these ones.
namespace choc::json
{
//==============================================================================
/// A parse exception, thrown by choc::json::parse() as needed.
struct ParseError : public std::runtime_error
{
ParseError (const char* message, choc::text::LineAndColumn lc)
: std::runtime_error (message), lineAndColumn (lc) {}
choc::text::LineAndColumn lineAndColumn;
};
/// Parses some JSON text into a choc::value::Value object, using the given pool.
/// Any errors will result in a ParseError exception being thrown.
value::Value parse (text::UTF8Pointer);
/// Parses some JSON text into a choc::value::Value object, using the given pool.
/// Any errors will result in a ParseError exception being thrown.
value::Value parse (std::string_view);
/// Attempts to parse a bare JSON value such as a number, string, object etc
value::Value parseValue (std::string_view);
/// A helper function to create a JSON-friendly Value object with a set of properties.
/// The argument list must be contain pairs of names and values, e.g.
///
/// auto myObject = choc::json::create ("property1", 1234,
/// "property2", "hello",
/// "property3", 100.0f);
///
/// Essentially, this is a shorthand for calling choc::value::createObject()
/// and passing it an empty type name.
template <typename... Properties>
value::Value create (Properties&&... propertyNamesAndValues);
//==============================================================================
/// Formats a value as a JSON string.
/// If useLineBreaks is true, it'll be formatted as multi-line JSON, if false it'll
/// just be returned as a single line.
std::string toString (const value::ValueView&, bool useLineBreaks = false);
/// Writes a version of a string to an output stream, with any illegal or non-ascii
/// written as their equivalent JSON escape sequences.
template <typename OutputStreamType>
void writeWithEscapeCharacters (OutputStreamType&, text::UTF8Pointer sourceString);
/// Returns a version of a string with illegal or non-ascii converted into the
/// equivalent JSON escape sequences.
std::string addEscapeCharacters (text::UTF8Pointer sourceString);
/// Returns a version of a string with illegal or non-ascii converted into the
/// equivalent JSON escape sequences.
std::string addEscapeCharacters (std::string_view sourceString);
/// Returns a version of a string with illegal or non-ascii converted into the
/// equivalent JSON escape sequences.
std::string getEscapedQuotedString (std::string_view sourceString);
/// Converts a double to a JSON-format string representation.
std::string doubleToString (double value);
//==============================================================================
// _ _ _ _
// __| | ___ | |_ __ _ (_)| | ___
// / _` | / _ \| __| / _` || || |/ __|
// | (_| || __/| |_ | (_| || || |\__ \ _ _ _
// \__,_| \___| \__| \__,_||_||_||___/(_)(_)(_)
//
// Code beyond this point is implementation detail...
//
//==============================================================================
template <typename OutputStreamType>
void writeWithEscapeCharacters (OutputStreamType& out, text::UTF8Pointer source)
{
auto writeUnicode = [] (OutputStreamType& o, auto digit)
{
auto hexDigit = [] (auto value) -> char { return "0123456789abcdef"[value & 15]; };
o << "\\u" << hexDigit (digit >> 12) << hexDigit (digit >> 8) << hexDigit (digit >> 4) << hexDigit (digit);
};
for (;;)
{
auto c = *source;
switch (c)
{
case 0: return;
case '\"': out << "\\\""; break;
case '\\': out << "\\\\"; break;
case '\n': out << "\\n"; break;
case '\r': out << "\\r"; break;
case '\t': out << "\\t"; break;
case '\a': out << "\\a"; break;
case '\b': out << "\\b"; break;
case '\f': out << "\\f"; break;
default:
if (c > 31 && c < 127)
{
out << (char) c;
break;
}
if (c >= 0x10000)
{
auto pair = choc::text::splitCodePointIntoSurrogatePair (c);
writeUnicode (out, pair.high);
writeUnicode (out, pair.low);
break;
}
writeUnicode (out, c);
break;
}
++source;
}
}
inline std::string addEscapeCharacters (text::UTF8Pointer source)
{
std::ostringstream result;
writeWithEscapeCharacters (result, source);
return result.str();
}
inline std::string addEscapeCharacters (std::string_view source)
{
return addEscapeCharacters (text::UTF8Pointer (std::string (source).c_str()));
}
inline std::string getEscapedQuotedString (std::string_view s)
{
std::ostringstream result;
result << '"';
writeWithEscapeCharacters (result, text::UTF8Pointer (std::string (s).c_str()));
result << '"';
return result.str();
}
inline std::string doubleToString (double value)
{
if (std::isfinite (value)) return choc::text::floatToString (value, -1, true);
if (std::isnan (value)) return "\"NaN\"";
return value >= 0 ? "\"Infinity\""
: "\"-Infinity\"";
}
//==============================================================================
template <typename Stream>
struct Writer
{
Stream& out;
uint32_t indentSize, currentIndent = 0;
static constexpr const char newLine = '\n';
std::string getIndent() const { return std::string (currentIndent, ' '); }
void startIndent() { currentIndent += indentSize; out << newLine << getIndent(); }
void endIndent() { currentIndent -= indentSize; out << newLine << getIndent(); }
void dump (const value::ValueView& v)
{
if (v.isVoid()) { out << "null"; return; }
if (v.isString()) { out << getEscapedQuotedString (v.getString()); return; }
if (v.isBool()) { out << (v.getBool() ? "true" : "false"); return; }
if (v.isFloat()) { out << doubleToString (v.get<double>()); return; }
if (v.isInt()) { out << v.get<int64_t>(); return; }
if (v.isObject()) return dumpObject (v);
if (v.isArray() || v.isVector()) return dumpArrayOrVector (v);
}
void dumpArrayOrVector (const value::ValueView& v)
{
out << '[';
auto numElements = v.size();
if (indentSize != 0 && numElements != 0)
{
startIndent();
for (uint32_t i = 0; i < numElements; ++i)
{
dump (v[i]);
if (i != numElements - 1)
out << "," << newLine << getIndent();
}
endIndent();
}
else
{
for (uint32_t i = 0; i < numElements; ++i)
{
if (i != 0) out << ", ";
dump (v[i]);
}
}
out << ']';
}
void dumpObject (const value::ValueView& object)
{
out << '{';
auto numMembers = object.size();
if (indentSize != 0 && numMembers != 0)
{
startIndent();
for (uint32_t i = 0; i < numMembers; ++i)
{
auto member = object.getObjectMemberAt (i);
out << getEscapedQuotedString (member.name) << ": ";
dump (member.value);
if (i != numMembers - 1)
out << "," << newLine << getIndent();
}
endIndent();
}
else
{
for (uint32_t i = 0; i < numMembers; ++i)
{
if (i != 0) out << ", ";
auto member = object.getObjectMemberAt (i);
out << getEscapedQuotedString (member.name) << ": ";
dump (member.value);
}
}
out << '}';
}
};
template <typename Stream>
void writeAsJSON (Stream& output, const value::ValueView& value, bool useMultipleLines)
{
Writer<Stream> { output, useMultipleLines ? 2u : 0u }.dump (value);
}
inline std::string toString (const value::ValueView& v, bool useLineBreaks)
{
std::ostringstream out;
writeAsJSON (out, v, useLineBreaks);
return out.str();
}
//==============================================================================
[[noreturn]] static inline void throwParseError (const char* error, text::UTF8Pointer source, text::UTF8Pointer errorPos)
{
throw ParseError (error, text::findLineAndColumn (source, errorPos));
}
inline value::Value parse (text::UTF8Pointer text, bool parseBareValue)
{
struct Parser
{
text::UTF8Pointer source, current;
bool isEOF() const { return current.empty(); }
uint32_t peek() const { return *current; }
uint32_t pop() { return current.popFirstChar(); }
bool popIf (char c) { return current.skipIfStartsWith (c); }
bool popIf (const char* c) { return current.skipIfStartsWith (c); }
static bool isWhitespace (uint32_t c) { return c == ' ' || (c <= 13 && c >= 9); }
void skipWhitespace() { auto p = current; while (isWhitespace (p.popFirstChar())) current = p; }
[[noreturn]] void throwError (const char* error, text::UTF8Pointer errorPos) { throwParseError (error, source, errorPos); }
[[noreturn]] void throwError (const char* error) { throwError (error, current); }
value::Value parseTopLevel()
{
skipWhitespace();
if (popIf ('[')) return parseArray();
if (popIf ('{')) return parseObject();
if (! isEOF()) throwError ("Expected an object or array");
return {};
}
value::Value parseArray()
{
auto result = value::createEmptyArray();
auto arrayStart = current;
skipWhitespace();
if (popIf (']')) return result;
for (;;)
{
skipWhitespace();
if (isEOF()) throwError ("Unexpected EOF in array declaration", arrayStart);
result.addArrayElement (parseValue());
skipWhitespace();
if (popIf (',')) continue;
if (popIf (']')) break;
throwError ("Expected ',' or ']'");
}
return result;
}
value::Value parseObject()
{
auto result = value::createObject ({});
auto objectStart = current;
skipWhitespace();
if (popIf ('}')) return result;
for (;;)
{
skipWhitespace();
if (isEOF()) throwError ("Unexpected EOF in object declaration", objectStart);
if (! popIf ('"')) throwError ("Expected a name");
auto errorPos = current;
auto name = parseString();
if (name.empty())
throwError ("Property names cannot be empty", errorPos);
skipWhitespace();
errorPos = current;
if (! popIf (':')) throwError ("Expected ':'");
result.addMember (std::move (name), parseValue());
skipWhitespace();
if (popIf (',')) continue;
if (popIf ('}')) break;
throwError ("Expected ',' or '}'");
}
return result;
}
value::Value parseValue()
{
skipWhitespace();
auto startPos = current;
switch (pop())
{
case '[': return parseArray();
case '{': return parseObject();
case '"': return value::createString (parseString());
case '-': skipWhitespace(); return parseNumber (true);
case 'n': if (popIf ("ull")) return {}; break;
case 't': if (popIf ("rue")) return value::createBool (true); break;
case 'f': if (popIf ("alse")) return value::createBool (false); break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
current = startPos;
return parseNumber (false);
default: break;
}
throwError ("Syntax error", startPos);
}
value::Value parseNumber (bool negate)
{
auto startPos = current;
bool hadDot = false, hadExponent = false;
for (;;)
{
auto lastPos = current;
auto c = pop();
if (c >= '0' && c <= '9') continue;
if (c == '.' && ! hadDot) { hadDot = true; continue; }
if (! hadExponent && (c == 'e' || c == 'E'))
{
hadDot = true;
hadExponent = true;
popIf ('-');
continue;
}
if (isWhitespace (c) || c == ',' || c == '}' || c == ']' || c == 0)
{
current = lastPos;
char* endOfParsedNumber = nullptr;
if (! (hadDot || hadExponent))
{
auto v = std::strtoll (startPos.data(), &endOfParsedNumber, 10);
if (endOfParsedNumber == lastPos.data()
&& v != std::numeric_limits<long long>::max()
&& v != std::numeric_limits<long long>::min())
return value::createInt64 (static_cast<int64_t> (negate ? -v : v));
}
auto v = std::strtod (startPos.data(), &endOfParsedNumber);
if (endOfParsedNumber == lastPos.data())
return value::createFloat64 (negate ? -v : v);
}
throwError ("Syntax error in number", lastPos);
}
}
std::string parseString()
{
std::ostringstream s;
for (;;)
{
auto c = pop();
if (c == '"')
break;
if (c == '\\')
{
auto errorPos = current;
c = pop();
switch (c)
{
case 'a': c = '\a'; 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 = parseUnicodeCharacterNumber (false); break;
case 0: throwError ("Unexpected EOF in string constant", errorPos);
default: break;
}
}
char utf8Bytes[8];
auto numBytes = text::convertUnicodeCodepointToUTF8 (utf8Bytes, c);
for (uint32_t i = 0; i < numBytes; ++i)
s << utf8Bytes[i];
}
return s.str();
}
uint32_t parseUnicodeCharacterNumber (bool isLowSurrogate)
{
uint32_t result = 0;
for (int i = 4; --i >= 0;)
{
auto errorPos = current;
auto digit = pop();
if (digit >= '0' && digit <= '9') digit -= '0';
else if (digit >= 'a' && digit <= 'f') digit = 10 + (digit - 'a');
else if (digit >= 'A' && digit <= 'F') digit = 10 + (digit - 'A');
else throwError ("Syntax error in unicode character", errorPos);
result = (result << 4) + digit;
}
if (isLowSurrogate && ! text::isUnicodeLowSurrogate (result))
throwError ("Expected a unicode low surrogate codepoint");
if (text::isUnicodeHighSurrogate (result))
{
if (! isLowSurrogate && popIf ("\\u"))
return text::createUnicodeFromHighAndLowSurrogates ({ result, parseUnicodeCharacterNumber (true) });
throwError ("Expected a unicode low surrogate codepoint");
}
return result;
}
};
Parser p { text, text };
return parseBareValue ? p.parseValue()
: p.parseTopLevel();
}
inline value::Value parse (const char* text, size_t numbytes, bool parseBareValue)
{
if (text == nullptr)
{
text = "";
numbytes = 0;
}
if (auto error = text::findInvalidUTF8Data (text, numbytes))
throwParseError ("Illegal UTF8 data", text::UTF8Pointer (text), text::UTF8Pointer (error));
return parse (text::UTF8Pointer (text), parseBareValue);
}
inline value::Value parse (std::string_view text) { return parse (text.data(), text.length(), false); }
inline value::Value parseValue (std::string_view text) { return parse (text.data(), text.length(), true); }
template <typename... Properties>
value::Value create (Properties&&... properties)
{
static_assert ((sizeof...(properties) & 1) == 0, "The arguments must be a sequence of name, value pairs");
return choc::value::createObject ({}, std::forward<Properties> (properties)...);
}
} // namespace choc::json
#endif

View file

@ -0,0 +1,597 @@
//
// ██████ ██  ██  ██████  ██████
// ██      ██  ██ ██    ██ ██       ** Classy Header-Only Classes **
// ██  ███████ ██  ██ ██
// ██  ██   ██ ██  ██ ██ https://github.com/Tracktion/choc
//  ██████ ██  ██  ██████   ██████
//
// CHOC is (C)2022 Tracktion Corporation, and is offered under the terms of the ISC license:
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or
// without fee is hereby granted, provided that the above copyright notice and this permission
// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef CHOC_STRING_UTILS_HEADER_INCLUDED
#define CHOC_STRING_UTILS_HEADER_INCLUDED
#include <cctype>
#include <string>
#include <vector>
#include <cmath>
#include <chrono>
#include <memory>
#include <algorithm>
#include <cwctype>
#include "../platform/choc_Assert.h"
namespace choc::text
{
//==============================================================================
inline bool isWhitespace (char c) { return c == ' ' || (c <= 13 && c >= 9); }
inline bool isDigit (char c) { return static_cast<uint32_t> (c - '0') < 10; }
/// Replaces all occurrences of a one or more substrings.
/// The arguments must be a sequence of pairs of strings, where the first of each pair is the string to
/// look for, followed by its replacement.
template <typename StringType, typename... OtherReplacements>
std::string replace (StringType textToSearch,
std::string_view firstSubstringToReplace, std::string_view firstReplacement,
OtherReplacements&&... otherPairsOfStringsToReplace);
/// Returns a string with any whitespace trimmed from its start and end.
std::string trim (std::string textToTrim);
/// Returns a string with any whitespace trimmed from its start and end.
std::string_view trim (std::string_view textToTrim);
/// Returns a string with any whitespace trimmed from its start and end.
std::string_view trim (const char* textToTrim);
/// Returns a string with any whitespace trimmed from its start.
std::string trimStart (std::string textToTrim);
/// Returns a string with any whitespace trimmed from its start.
std::string_view trimStart (std::string_view textToTrim);
/// Returns a string with any whitespace trimmed from its start.
std::string_view trimStart (const char* textToTrim);
/// Returns a string with any whitespace trimmed from its end.
std::string trimEnd (std::string textToTrim);
/// Returns a string with any whitespace trimmed from its end.
std::string_view trimEnd (std::string_view textToTrim);
/// Returns a string with any whitespace trimmed from its end.
std::string_view trimEnd (const char* textToTrim);
/// If the string begins with one or more instances of the given character, this
/// skips past them, returning the remainder of the string.
std::string_view trimCharacterAtStart (std::string_view textToTrim, char characterToSkip);
/// If the given character is at the start and end of the string, it trims it away.
std::string removeOuterCharacter (std::string text, char outerChar);
inline std::string removeDoubleQuotes (std::string text) { return removeOuterCharacter (std::move (text), '"'); }
inline std::string removeSingleQuotes (std::string text) { return removeOuterCharacter (std::move (text), '\''); }
inline std::string addDoubleQuotes (std::string text) { return "\"" + std::move (text) + "\""; }
inline std::string addSingleQuotes (std::string text) { return "'" + std::move (text) + "'"; }
std::string toLowerCase (std::string);
std::string toUpperCase (std::string);
template <typename IsDelimiterChar>
std::vector<std::string> splitString (std::string_view textToSplit,
IsDelimiterChar&& isDelimiterChar,
bool includeDelimitersInResult);
template <typename CharStartsDelimiter, typename CharIsInDelimiterBody>
std::vector<std::string> splitString (std::string_view textToSplit,
CharStartsDelimiter&& isDelimiterStart,
CharIsInDelimiterBody&& isDelimiterBody,
bool includeDelimitersInResult);
std::vector<std::string> splitString (std::string_view textToSplit,
char delimiterCharacter,
bool includeDelimitersInResult);
std::vector<std::string> splitAtWhitespace (std::string_view text, bool keepDelimiters = false);
/// Splits a string at newline characters, returning an array of strings.
std::vector<std::string> splitIntoLines (std::string_view text, bool includeNewLinesInResult);
/// Joins some kind of array of strings into a single string, adding the given separator
/// between them (but not adding it at the start or end)
template <typename ArrayOfStrings>
std::string joinStrings (const ArrayOfStrings& strings, std::string_view separator);
/// Returns true if this text contains the given sub-string.
bool contains (std::string_view text, std::string_view possibleSubstring);
/// Returns true if this text starts with the given character.
bool startsWith (std::string_view text, char possibleStart);
/// Returns true if this text starts with the given sub-string.
bool startsWith (std::string_view text, std::string_view possibleStart);
/// Returns true if this text ends with the given sub-string.
bool endsWith (std::string_view text, char possibleEnd);
/// Returns true if this text ends with the given sub-string.
bool endsWith (std::string_view text, std::string_view possibleEnd);
/// Calculates the Levenstein distance between two strings.
template <typename StringType>
size_t getLevenshteinDistance (const StringType& string1,
const StringType& string2);
/// Converts a hex character to a number 0-15, or -1 if it's not a valid hex digit.
int hexDigitToInt (uint32_t unicodeChar);
/// Returns a hex string for the given value.
/// If the minimum number of digits is non-zero, it will be zero-padded to fill this length;
template <typename IntegerType>
std::string createHexString (IntegerType value, int minNumDigits = 0);
/// Returns a truncated, easy-to-read version of a time as hours, seconds or milliseconds,
/// depending on its magnitude. The use-cases include things like logging or console app output.
std::string getDurationDescription (std::chrono::duration<double, std::micro>);
/// Returns an easy-to-read description of a size in bytes. Depending on the magnitude,
/// it might choose different units such as GB, MB, KB or just bytes.
std::string getByteSizeDescription (uint64_t sizeInBytes);
/// Encodes a string as a legal URI, using percent-encoding (aka URL encoding)
std::string percentEncodeURI (std::string_view text);
//==============================================================================
// _ _ _ _
// __| | ___ | |_ __ _ (_)| | ___
// / _` | / _ \| __| / _` || || |/ __|
// | (_| || __/| |_ | (_| || || |\__ \ _ _ _
// \__,_| \___| \__| \__,_||_||_||___/(_)(_)(_)
//
// Code beyond this point is implementation detail...
//
//==============================================================================
inline int hexDigitToInt (uint32_t c)
{
auto d1 = c - static_cast<uint32_t> ('0'); if (d1 < 10u) return static_cast<int> (d1);
auto d2 = d1 + static_cast<uint32_t> ('0' - 'a'); if (d2 < 6u) return static_cast<int> (d2 + 10);
auto d3 = d2 + static_cast<uint32_t> ('a' - 'A'); if (d3 < 6u) return static_cast<int> (d3 + 10);
return -1;
}
template <typename IntegerType>
std::string createHexString (IntegerType v, int minNumDigits)
{
static_assert (std::is_integral<IntegerType>::value, "Need to pass integers into this method");
auto value = static_cast<typename std::make_unsigned<IntegerType>::type> (v);
CHOC_ASSERT (minNumDigits <= 32);
char hex[40];
const auto end = hex + sizeof (hex) - 1;
auto d = end;
*d = 0;
for (;;)
{
*--d = "0123456789abcdef"[static_cast<uint32_t> (value) & 15u];
value = static_cast<decltype (value)> (value >> 4);
--minNumDigits;
if (value == 0 && minNumDigits <= 0)
return std::string (d, end);
}
}
template <typename StringType, typename... OtherReplacements>
std::string replace (StringType textToSearch, std::string_view firstToReplace, std::string_view firstReplacement,
OtherReplacements&&... otherPairsOfStringsToReplace)
{
static_assert ((sizeof... (otherPairsOfStringsToReplace) & 1u) == 0,
"This function expects a list of pairs of strings as its arguments");
if constexpr (std::is_same<const StringType, const std::string_view>::value || std::is_same<const StringType, const char* const>::value)
{
return replace (std::string (textToSearch), firstToReplace, firstReplacement,
std::forward<OtherReplacements> (otherPairsOfStringsToReplace)...);
}
else if constexpr (sizeof... (otherPairsOfStringsToReplace) == 0)
{
size_t pos = 0;
for (;;)
{
pos = textToSearch.find (firstToReplace, pos);
if (pos == std::string::npos)
return textToSearch;
textToSearch.replace (pos, firstToReplace.length(), firstReplacement);
pos += firstReplacement.length();
}
}
else
{
return replace (replace (std::move (textToSearch), firstToReplace, firstReplacement),
std::forward<OtherReplacements> (otherPairsOfStringsToReplace)...);
}
}
inline std::string trim (std::string text) { return trimStart (trimEnd (std::move (text))); }
inline std::string_view trim (std::string_view text) { return trimStart (trimEnd (std::move (text))); }
inline std::string_view trim (const char* text) { return trim (std::string_view (text)); }
inline std::string_view trimStart (const char* text) { return trimStart (std::string_view (text)); }
inline std::string_view trimEnd (const char* text) { return trimEnd (std::string_view (text)); }
inline std::string trimStart (std::string text)
{
auto i = text.begin();
if (i == text.end()) return {};
if (! isWhitespace (*i)) return text;
for (;;)
{
++i;
if (i == text.end()) return {};
if (! isWhitespace (*i)) return { i, text.end() };
}
}
inline std::string_view trimStart (std::string_view text)
{
size_t i = 0;
for (auto c : text)
{
if (! isWhitespace (c))
{
text.remove_prefix (i);
return text;
}
++i;
}
return {};
}
inline std::string trimEnd (std::string text)
{
for (auto i = text.end();;)
{
if (i == text.begin())
return {};
--i;
if (! isWhitespace (*i))
{
text.erase (i + 1, text.end());
return text;
}
}
}
inline std::string_view trimEnd (std::string_view text)
{
for (auto i = text.length(); i != 0; --i)
if (! isWhitespace (text[i - 1]))
return text.substr (0, i);
return {};
}
inline std::string_view trimCharacterAtStart (std::string_view textToTrim, char characterToSkip)
{
for (size_t i = 0; i < textToTrim.length(); ++i)
if (textToTrim[i] != characterToSkip)
return textToTrim.substr (i);
return {};
}
inline std::string removeOuterCharacter (std::string t, char outerChar)
{
if (t.length() >= 2 && t.front() == outerChar && t.back() == outerChar)
return t.substr (1, t.length() - 2);
return t;
}
inline std::string toLowerCase (std::string s)
{
std::transform (s.begin(), s.end(), s.begin(), [] (auto c) { return static_cast<char> (std::tolower (static_cast<unsigned char> (c))); });
return s;
}
inline std::string toUpperCase (std::string s)
{
std::transform (s.begin(), s.end(), s.begin(), [] (auto c) { return static_cast<char> (std::toupper (static_cast<unsigned char> (c))); });
return s;
}
template <typename CharStartsDelimiter, typename CharIsInDelimiterBody>
std::vector<std::string> splitString (std::string_view source,
CharStartsDelimiter&& isDelimiterStart,
CharIsInDelimiterBody&& isDelimiterBody,
bool keepDelimiters)
{
std::vector<std::string> tokens;
auto tokenStart = source.begin();
auto pos = tokenStart;
while (pos != source.end())
{
if (isDelimiterStart (*pos))
{
auto delimiterStart = pos++;
while (pos != source.end() && isDelimiterBody (*pos))
++pos;
if (pos != source.begin())
tokens.push_back ({ tokenStart, keepDelimiters ? pos : delimiterStart });
tokenStart = pos;
}
else
{
++pos;
}
}
if (pos != source.begin())
tokens.push_back ({ tokenStart, pos });
return tokens;
}
template <typename IsDelimiterChar>
std::vector<std::string> splitString (std::string_view source, IsDelimiterChar&& isDelimiterChar, bool keepDelimiters)
{
std::vector<std::string> tokens;
auto tokenStart = source.begin();
auto pos = tokenStart;
while (pos != source.end())
{
if (isDelimiterChar (*pos))
{
tokens.push_back ({ tokenStart, keepDelimiters ? pos + 1 : pos });
tokenStart = ++pos;
}
else
{
++pos;
}
}
if (pos != source.begin())
tokens.push_back ({ tokenStart, pos });
return tokens;
}
inline std::vector<std::string> splitString (std::string_view text, char delimiterCharacter, bool keepDelimiters)
{
return splitString (text, [=] (char c) { return c == delimiterCharacter; }, keepDelimiters);
}
inline std::vector<std::string> splitAtWhitespace (std::string_view text, bool keepDelimiters)
{
return splitString (text,
[] (char c) { return isWhitespace (c); },
[] (char c) { return isWhitespace (c); },
keepDelimiters);
}
inline std::vector<std::string> splitIntoLines (std::string_view text, bool includeNewLinesInResult)
{
return splitString (text, '\n', includeNewLinesInResult);
}
template <typename ArrayOfStrings>
inline std::string joinStrings (const ArrayOfStrings& strings, std::string_view sep)
{
if (strings.empty())
return {};
auto spaceNeeded = sep.length() * strings.size();
for (auto& s : strings)
spaceNeeded += s.length();
std::string result (strings.front());
result.reserve (spaceNeeded);
for (size_t i = 1; i < strings.size(); ++i)
{
result += sep;
result += strings[i];
}
return result;
}
inline bool contains (std::string_view t, std::string_view s) { return t.find (s) != std::string::npos; }
inline bool startsWith (std::string_view t, char s) { return ! t.empty() && t.front() == s; }
inline bool endsWith (std::string_view t, char s) { return ! t.empty() && t.back() == s; }
inline bool startsWith (std::string_view t, std::string_view s)
{
auto len = s.length();
return t.length() >= len && t.substr (0, len) == s;
}
inline bool endsWith (std::string_view t, std::string_view s)
{
auto len1 = t.length(), len2 = s.length();
return len1 >= len2 && t.substr (len1 - len2) == s;
}
inline std::string getDurationDescription (std::chrono::duration<double, std::micro> d)
{
auto microseconds = std::chrono::duration_cast<std::chrono::microseconds> (d).count();
if (microseconds < 0) return "-" + getDurationDescription (-d);
if (microseconds == 0) return "0 sec";
std::string result;
auto addLevel = [&] (int64_t size, std::string_view units, int64_t decimalScale, int64_t modulo) -> bool
{
if (microseconds < size)
return false;
if (! result.empty())
result += ' ';
auto scaled = (microseconds * decimalScale + size / 2) / size;
auto whole = scaled / decimalScale;
if (modulo != 0)
whole = whole % modulo;
result += std::to_string (whole);
if (auto fraction = scaled % decimalScale)
{
result += '.';
result += static_cast<char> ('0' + (fraction / 10));
if (fraction % 10 != 0)
result += static_cast<char> ('0' + (fraction % 10));
}
result += (whole == 1 && units.length() > 3 && units.back() == 's') ? units.substr (0, units.length() - 1) : units;
return true;
};
bool hours = addLevel (60000000ll * 60ll, " hours", 1, 0);
bool mins = addLevel (60000000ll, " min", 1, hours ? 60 : 0);
if (hours)
return result;
if (mins)
{
addLevel (1000000, " sec", 1, 60);
}
else
{
if (! addLevel (1000000, " sec", 100, 0))
if (! addLevel (1000, " ms", 100, 0))
addLevel (1, " microseconds", 100, 0);
}
return result;
}
template <typename StringType>
size_t getLevenshteinDistance (const StringType& string1, const StringType& string2)
{
if (string1.empty()) return string2.length();
if (string2.empty()) return string1.length();
auto calculate = [] (size_t* costs, size_t numCosts, const StringType& s1, const StringType& s2) -> size_t
{
for (size_t i = 0; i < numCosts; ++i)
costs[i] = i;
size_t p1 = 0;
for (auto c1 : s1)
{
auto corner = p1;
*costs = p1 + 1;
size_t p2 = 0;
for (auto c2 : s2)
{
auto upper = costs[p2 + 1];
costs[p2 + 1] = c1 == c2 ? corner : (std::min (costs[p2], std::min (upper, corner)) + 1);
++p2;
corner = upper;
}
++p1;
}
return costs[numCosts - 1];
};
auto sizeNeeded = string2.length() + 1;
constexpr size_t maxStackSize = 96;
if (sizeNeeded <= maxStackSize)
{
size_t costs[maxStackSize];
return calculate (costs, sizeNeeded, string1, string2);
}
std::unique_ptr<size_t[]> costs (new size_t[sizeNeeded]);
return calculate (costs.get(), sizeNeeded, string1, string2);
}
inline std::string getByteSizeDescription (uint64_t size)
{
auto intToStringWith1DecPlace = [] (uint64_t n, uint64_t divisor) -> std::string
{
auto scaled = (n * 10 + divisor / 2) / divisor;
auto result = std::to_string (scaled / 10);
if (auto fraction = scaled % 10)
{
result += '.';
result += static_cast<char> ('0' + fraction);
}
return result;
};
static constexpr uint64_t maxValue = std::numeric_limits<uint64_t>::max() / 10;
if (size >= 0x40000000) return intToStringWith1DecPlace (std::min (maxValue, size), 0x40000000) + " GB";
if (size >= 0x100000) return intToStringWith1DecPlace (size, 0x100000) + " MB";
if (size >= 0x400) return intToStringWith1DecPlace (size, 0x400) + " KB";
if (size != 1) return std::to_string (size) + " bytes";
return "1 byte";
}
inline std::string percentEncodeURI (std::string_view text)
{
std::string result;
result.reserve (text.length());
for (auto c : text)
{
if (std::string_view ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.~").find (c) != std::string_view::npos)
{
result += c;
}
else
{
result += '%';
result += "0123456789abcdef"[static_cast<uint8_t> (c) >> 4];
result += "0123456789abcdef"[static_cast<uint8_t> (c) & 15u];
}
}
return result;
}
} // namespace choc::text
#endif

View file

@ -0,0 +1,655 @@
//
// ██████ ██  ██  ██████  ██████
// ██      ██  ██ ██    ██ ██       ** Classy Header-Only Classes **
// ██  ███████ ██  ██ ██
// ██  ██   ██ ██  ██ ██ https://github.com/Tracktion/choc
//  ██████ ██  ██  ██████   ██████
//
// CHOC is (C)2022 Tracktion Corporation, and is offered under the terms of the ISC license:
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or
// without fee is hereby granted, provided that the above copyright notice and this permission
// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef CHOC_UTF8_HEADER_INCLUDED
#define CHOC_UTF8_HEADER_INCLUDED
#include <cstddef>
#include "choc_StringUtilities.h"
namespace choc::text
{
/// An integer type to represent a unicode code-point.
using UnicodeChar = uint32_t;
//==============================================================================
/** A non-owning pointer which can iterate over a chunk of null-terminated UTF-8 text
and read it as wide unicode characters.
*/
struct UTF8Pointer
{
explicit constexpr UTF8Pointer (const char* utf8Text) noexcept : text (utf8Text) {}
UTF8Pointer() = default;
UTF8Pointer (const UTF8Pointer&) = default;
UTF8Pointer& operator= (const UTF8Pointer&) = default;
/// Returns the raw data that this points to.
const char* data() const noexcept { return text; }
/// Returns true if the pointer is not null.
operator bool() const noexcept { return text != nullptr; }
/// Returns true if the pointer is either null or points to a null terminator char.
bool empty() const { return text == nullptr || *text == 0; }
/// Returns the length by iterating all unicode chars and counting them.
/// Note that this is slow, and is not a count of the number of bytes in the string!
size_t length() const;
//==============================================================================
/// Returns the first unicode character in the string.
UnicodeChar operator*() const;
/// Skips past the first unicode character.
/// Moving beyond the end of the string is undefined behaviour and will trigger an assertion.
UTF8Pointer& operator++();
/// Skips past the first unicode character.
/// Moving beyond the end of the string is undefined behaviour and will trigger an assertion.
UTF8Pointer operator++ (int);
/// Moves backwards to the previous unicode character.
/// Moving beyond the end of the string is undefined behaviour.
UTF8Pointer operator--();
/// Skips past the given number of unicode characters.
/// Moving beyond the end of the string is undefined behaviour and will trigger an assertion.
UTF8Pointer& operator+= (size_t numCharsToSkip);
/// Returns a pointer which points to the n-th unicode character in the text
/// Reading beyond the end of the string is undefined behaviour and may trigger an assertion.
UTF8Pointer operator+ (size_t numCharsToSkip) const;
/// Returns a pointer which points to the n-th unicode character in the text.
/// Reading beyond the end of the string is undefined behaviour and may trigger an assertion.
UTF8Pointer operator+ (int numCharsToSkip) const;
/// Skips past the first unicode character and returns it as a code-point.
/// Calling this when the current character is the terminator will leave the pointer in an
/// invalid state.
UnicodeChar popFirstChar();
/// Finds the next occurrence of the given string, or return a nullptr if not found.
UTF8Pointer find (const char* textToFind) const;
/// Returns true if the text starts with this string
bool startsWith (const char* textToMatch) const;
/// If the first character matches the given one, this will advance the pointer and return true.
bool skipIfStartsWith (char charToMatch);
/// If the start of the text matches the given string, this will advance this pointer to skip
/// past it, and return true. If not, it will return false without modifying this pointer.
bool skipIfStartsWith (const char* textToMatch);
/// Returns a pointer to the first non-whitespace character in the given string (which may
/// be the terminating null character if it's all whitespace).
UTF8Pointer findEndOfWhitespace() const;
/// Iterates backwards from this position to find the first character that follows
/// a new-line. The pointer provided marks the furthest back that the function should search
UTF8Pointer findStartOfLine (UTF8Pointer startOfValidText) const;
/// Searches forwards for the next character that is followed by a new-line or a null-terminator.
UTF8Pointer findEndOfLine() const;
//==============================================================================
struct EndIterator {};
struct Iterator
{
explicit constexpr Iterator (const char* t) : text (t) {}
Iterator (const Iterator&) = default;
Iterator& operator= (const Iterator&) = default;
UnicodeChar operator*() const { return *UTF8Pointer (text); }
Iterator& operator++() { UTF8Pointer p (text); ++p; text = p.text; return *this; }
Iterator operator++ (int) { auto old = *this; ++*this; return old; }
bool operator== (EndIterator) const { return *text == 0; }
bool operator!= (EndIterator) const { return *text != 0; }
private:
const char* text;
};
Iterator begin() const;
EndIterator end() const;
//==============================================================================
/// This does a pointer comparison, NOT a comparison of the text itself!
bool operator== (UTF8Pointer other) const noexcept { return text == other.text; }
/// This does a pointer comparison, NOT a comparison of the text itself!
bool operator!= (UTF8Pointer other) const noexcept { return text != other.text; }
/// This does a pointer comparison, NOT a comparison of the text itself!
bool operator< (UTF8Pointer other) const noexcept { return text < other.text; }
/// This does a pointer comparison, NOT a comparison of the text itself!
bool operator> (UTF8Pointer other) const noexcept { return text > other.text; }
/// This does a pointer comparison, NOT a comparison of the text itself!
bool operator<= (UTF8Pointer other) const noexcept { return text <= other.text; }
/// This does a pointer comparison, NOT a comparison of the text itself!
bool operator>= (UTF8Pointer other) const noexcept { return text >= other.text; }
bool operator== (decltype(nullptr)) const noexcept { return text == nullptr; }
bool operator!= (decltype(nullptr)) const noexcept { return text != nullptr; }
private:
const char* text = nullptr;
};
//==============================================================================
/// Checks a given chunk of data to see whether it's valid UTF-8.
/// If no errors are found, this returns nullptr. If an error is found, it returns the address
/// of the offending byte. Note that zero bytes in the data are considered to be valid UTF-8.
const char* findInvalidUTF8Data (const void* dataToCheck, size_t numBytesToRead);
/// Writes the bytes for a unicode character, and returns the number of bytes that were needed.
/// The buffer passed in needs to have at least 4 bytes capacity.
uint32_t convertUnicodeCodepointToUTF8 (char* dest, UnicodeChar codepoint);
/// Appends a unicode codepoint to a std::string as a sequence of UTF-8 bytes.
void appendUTF8 (std::string& target, UnicodeChar codepoint);
/// Checks whether a given codepoint is a high-surrogate
bool isUnicodeHighSurrogate (UnicodeChar codepoint);
/// Checks whether a given codepoint is a low-surrogate
bool isUnicodeLowSurrogate (UnicodeChar codepoint);
struct SurrogatePair
{
UnicodeChar high = 0, low = 0;
};
/// For a codepoint >= 0x10000, this will return a surrogate pair to represent it.
SurrogatePair splitCodePointIntoSurrogatePair (UnicodeChar fullCodePoint);
/// Combines a high and low surrogate into a single codepoint.
UnicodeChar createUnicodeFromHighAndLowSurrogates (SurrogatePair);
/// Checks a UTF-8/CESU-8 string to see if it contains any surrogate pairs.
/// If it does, then to use it as UTF-8 you'll probably need to run it through
/// convertSurrogatePairsToUTF8().
bool containsSurrogatePairs (UTF8Pointer);
/// Returns a string where any surrogate pairs have been converted to UTF-8 codepoints.
std::string convertSurrogatePairsToUTF8 (UTF8Pointer);
/// Returns true if the given UTF-8 string can be used as CESU-8 without conversion. If not,
/// you'll need to run it through convertUTF8ToCESU8() to convert the 32-bit code-points
/// to surrogate pairs.
bool isValidCESU8 (std::string_view utf8);
/// Converts any 32-bit characters in this UTF-8 string to surrogate pairs, which makes
/// the resulting string suitable for use at CESU-8.
std::string convertUTF8ToCESU8 (UTF8Pointer);
//==============================================================================
/// Represents a line and column index within a block of text.
struct LineAndColumn
{
/// Valid line and column values start at 1.
/// If either is 0, it means that the LineAndColumn object is uninitialised.
size_t line = 0, column = 0;
/// Returns true if neither the line nor column is zero.
bool isValid() const noexcept { return line != 0 && column != 0; }
/// Turns this location into a [line]:[col] string suitable for use in a
/// standard compiler error message format.
std::string toString() const;
};
/// Given a block of text and a position within it, this will work out the
/// line and column of that position.
LineAndColumn findLineAndColumn (UTF8Pointer fullText,
UTF8Pointer targetPosition);
//==============================================================================
// _ _ _ _
// __| | ___ | |_ __ _ (_)| | ___
// / _` | / _ \| __| / _` || || |/ __|
// | (_| || __/| |_ | (_| || || |\__ \ _ _ _
// \__,_| \___| \__| \__,_||_||_||___/(_)(_)(_)
//
// Code beyond this point is implementation detail...
//
//==============================================================================
inline size_t UTF8Pointer::length() const
{
size_t count = 0;
if (text != nullptr)
for (auto p = *this; *p.text != 0; ++p)
++count;
return count;
}
inline const char* findInvalidUTF8Data (const void* dataToCheck, size_t numBytes)
{
CHOC_ASSERT (dataToCheck != nullptr);
auto source = static_cast<const char*> (dataToCheck);
const auto end = source + numBytes;
for (;;)
{
if (source >= end)
return nullptr;
auto byte = static_cast<signed char> (*source);
if (byte >= 0)
{
++source;
continue;
}
int testBit = 0x40, numExtraBytes = 0;
while ((byte & testBit) != 0)
{
testBit >>= 1;
++numExtraBytes;
if (numExtraBytes > 3
|| source + static_cast<size_t> (numExtraBytes) >= end
|| (numExtraBytes == 3 && *UTF8Pointer (source) > 0x10ffff))
{
return source;
}
}
if (numExtraBytes == 0)
return source;
++source;
for (int i = 0; i < numExtraBytes; ++i)
{
if ((*source & 0xc0) != 0x80)
return source;
++source;
}
}
}
inline UnicodeChar UTF8Pointer::operator*() const
{
return UTF8Pointer (*this).popFirstChar();
}
inline UTF8Pointer& UTF8Pointer::operator++()
{
CHOC_ASSERT (! empty()); // can't advance past the zero-terminator
auto firstByte = static_cast<signed char> (*text++);
if (firstByte >= 0)
return *this;
uint32_t testBit = 0x40, unicodeChar = static_cast<unsigned char> (firstByte);
while ((unicodeChar & testBit) != 0 && testBit > 8)
{
++text;
testBit >>= 1;
}
return *this;
}
inline UTF8Pointer UTF8Pointer::operator++ (int)
{
auto prev = *this;
operator++();
return prev;
}
inline UTF8Pointer UTF8Pointer::operator--()
{
CHOC_ASSERT (text != nullptr); // mustn't use this on nullptrs
uint32_t bytesSkipped = 0;
while ((*--text & 0xc0) == 0x80)
{
if (bytesSkipped > 2)
{
CHOC_ASSERT (bytesSkipped <= 2);
break;
}
++bytesSkipped;
}
return *this;
}
inline UTF8Pointer& UTF8Pointer::operator+= (size_t numCharsToSkip)
{
while (numCharsToSkip != 0)
{
--numCharsToSkip;
operator++();
}
return *this;
}
inline UTF8Pointer UTF8Pointer::operator+ (size_t numCharsToSkip) const
{
auto p = *this;
p += numCharsToSkip;
return p;
}
inline UTF8Pointer UTF8Pointer::operator+ (int numCharsToSkip) const
{
CHOC_ASSERT (numCharsToSkip >= 0);
return operator+ (static_cast<size_t> (numCharsToSkip));
}
inline UnicodeChar UTF8Pointer::popFirstChar()
{
CHOC_ASSERT (text != nullptr); // mustn't use this on nullptrs
auto firstByte = static_cast<signed char> (*text++);
UnicodeChar unicodeChar = static_cast<unsigned char> (firstByte);
if (firstByte < 0)
{
uint32_t bitMask = 0x7f, numExtraBytes = 0;
for (uint32_t testBit = 0x40; (unicodeChar & testBit) != 0 && testBit > 8; ++numExtraBytes)
{
bitMask >>= 1;
testBit >>= 1;
}
unicodeChar &= bitMask;
for (uint32_t i = 0; i < numExtraBytes; ++i)
{
uint32_t nextByte = static_cast<unsigned char> (*text);
CHOC_ASSERT ((nextByte & 0xc0) == 0x80); // error in the data - you should always make sure the source
// gets validated before iterating a UTF8Pointer over it
unicodeChar = (unicodeChar << 6) | (nextByte & 0x3f);
++text;
}
}
return unicodeChar;
}
inline bool UTF8Pointer::startsWith (const char* textToMatch) const
{
CHOC_ASSERT (textToMatch != nullptr);
if (auto p = text)
{
while (*textToMatch != 0)
if (*textToMatch++ != *p++)
return false;
return true;
}
return false;
}
inline UTF8Pointer UTF8Pointer::find (const char* textToFind) const
{
CHOC_ASSERT (textToFind != nullptr);
for (auto t = *this;; ++t)
if (t.startsWith (textToFind) || t.empty())
return t;
}
inline bool UTF8Pointer::skipIfStartsWith (char charToMatch)
{
if (text != nullptr && *text == charToMatch && charToMatch != 0)
{
++text;
return true;
}
return false;
}
inline bool UTF8Pointer::skipIfStartsWith (const char* textToMatch)
{
CHOC_ASSERT (textToMatch != nullptr);
if (auto p = text)
{
while (*textToMatch != 0)
if (*textToMatch++ != *p++)
return false;
text = p;
return true;
}
return false;
}
inline UTF8Pointer UTF8Pointer::findEndOfWhitespace() const
{
auto p = *this;
if (p.text != nullptr)
while (choc::text::isWhitespace (*p.text))
++p;
return p;
}
inline UTF8Pointer UTF8Pointer::findStartOfLine (UTF8Pointer start) const
{
if (text == nullptr)
return {};
auto l = *this;
CHOC_ASSERT (l.text >= start.text && start.text != nullptr);
while (l.text > start.text)
{
auto prev = l;
auto c = *--prev;
if (c == '\r' || c == '\n')
break;
l = prev;
}
return l;
}
inline UTF8Pointer UTF8Pointer::findEndOfLine() const
{
if (text == nullptr)
return {};
auto l = *this;
while (! l.empty())
{
auto c = l.popFirstChar();
if (c == '\r' || c == '\n')
break;
}
return l;
}
inline UTF8Pointer::Iterator UTF8Pointer::begin() const { CHOC_ASSERT (text != nullptr); return Iterator (text); }
inline UTF8Pointer::EndIterator UTF8Pointer::end() const { return EndIterator(); }
inline LineAndColumn findLineAndColumn (UTF8Pointer start, UTF8Pointer targetPosition)
{
if (start == nullptr || targetPosition == nullptr)
return {};
CHOC_ASSERT (start <= targetPosition);
LineAndColumn lc { 1, 1 };
while (start < targetPosition && ! start.empty())
{
++lc.column;
if (*start++ == '\n') { lc.line++; lc.column = 1; }
}
return lc;
}
inline std::string LineAndColumn::toString() const { return std::to_string (line) + ':' + std::to_string (column); }
//==============================================================================
inline uint32_t convertUnicodeCodepointToUTF8 (char* dest, UnicodeChar unicodeChar)
{
if (unicodeChar < 0x80)
{
*dest = static_cast<char> (unicodeChar);
return 1;
}
uint32_t extraBytes = 1;
if (unicodeChar >= 0x800)
{
++extraBytes;
if (unicodeChar >= 0x10000)
++extraBytes;
}
dest[0] = static_cast<char> ((0xffu << (7 - extraBytes)) | (unicodeChar >> (extraBytes * 6)));
for (uint32_t i = 1; i <= extraBytes; ++i)
dest[i] = static_cast<char> (0x80u | (0x3fu & (unicodeChar >> ((extraBytes - i) * 6))));
return extraBytes + 1;
}
inline void appendUTF8 (std::string& target, UnicodeChar unicodeChar)
{
char bytes[4];
auto num = convertUnicodeCodepointToUTF8 (bytes, unicodeChar);
target.append (bytes, num);
}
inline bool isUnicodeHighSurrogate (UnicodeChar codepoint) { return codepoint >= 0xd800 && codepoint <= 0xdbff; }
inline bool isUnicodeLowSurrogate (UnicodeChar codepoint) { return codepoint >= 0xdc00 && codepoint <= 0xdfff; }
inline UnicodeChar createUnicodeFromHighAndLowSurrogates (SurrogatePair pair)
{
if (! isUnicodeHighSurrogate (pair.high)) return pair.high;
if (! isUnicodeLowSurrogate (pair.low)) return 0;
return (pair.high << 10) + pair.low - 0x35fdc00u;
}
inline bool containsSurrogatePairs (UTF8Pointer text)
{
for (;;)
{
auto c = text.popFirstChar();
if (c == 0)
return false;
if (isUnicodeHighSurrogate (c))
return true;
}
}
inline std::string convertSurrogatePairsToUTF8 (UTF8Pointer text)
{
std::string result;
for (;;)
{
auto c = text.popFirstChar();
if (choc::text::isUnicodeHighSurrogate (c))
c = createUnicodeFromHighAndLowSurrogates ({ c, text.popFirstChar() });
if (c == 0)
return result;
appendUTF8 (result, c);
}
}
inline SurrogatePair splitCodePointIntoSurrogatePair (UnicodeChar fullCodePoint)
{
CHOC_ASSERT (fullCodePoint >= 0x10000);
return { static_cast<UnicodeChar> (0xd800u + ((fullCodePoint - 0x10000u) >> 10)),
static_cast<UnicodeChar> (0xdc00u + (fullCodePoint & 0x3ffu)) };
}
inline bool isValidCESU8 (std::string_view utf8)
{
for (auto c : utf8)
if (static_cast<uint8_t> (c) >= 0xe8)
return false;
return true;
}
inline std::string convertUTF8ToCESU8 (UTF8Pointer utf8)
{
std::string result;
for (;;)
{
auto c = utf8.popFirstChar();
if (c == 0)
return result;
if (c < 128)
{
result += (char) c;
}
else if (c >= 0x10000)
{
auto pair = splitCodePointIntoSurrogatePair (c);
appendUTF8 (result, pair.high);
appendUTF8 (result, pair.low);
}
else
{
appendUTF8 (result, c);
}
}
}
} // namespace choc::text
#endif

File diff suppressed because it is too large Load diff

View file

@ -35,6 +35,291 @@
namespace juce
{
/**
A JSObject represents an owning reference to the underlying JS object, meaning it will remain
valid even if a subsequent script execution deletes other handles to it.
Objects of this class can be used to traverse the current object graph inside the specified
Javascript engine.
This is a low-level providing only operations that map directly to the underlying Javascript
Object implementation. The JSCursor class generally provides a more convenient interface with
functions that may fail based on the Javascript engine's current state.
@see JSCursor
@tags{Core}
*/
class JUCE_API JSObject
{
public:
/** Constructor, used internally by the JavascriptEngine implementation.
To create a new JSObject pointing at the root object of the engine's context use
JavascriptEngine::getRootObject().
*/
explicit JSObject (const detail::QuickJSWrapper* engine);
/** Destructor. */
~JSObject();
/** Copy constructor. */
JSObject (const JSObject&);
/** Move constructor. */
JSObject (JSObject&&) noexcept;
/** Copy assignment operator. */
JSObject& operator= (const JSObject&);
/** Move assignment operator. */
JSObject& operator= (JSObject&&) noexcept;
/** Returns a new cursor pointing to a JS object that is a property of the parent cursor's
underlying object and has the provided name.
You can use hasProperty() to check if such a property exists prior to the creation of this
cursor. If no such property exists, this constructor will create a new JS Object and attach
it to the parent under the specified name. This can be used to manipulate the object graph.
*/
JSObject getChild (const Identifier& name) const;
/** Returns a cursor object pointing to the property with the given name. If such property
doesn't exist it will be created as an empty JS Object. Shorthand for getChild.
*/
JSObject operator[] (const Identifier& name) const;
/** Returns a new cursor object pointing to the specified element in an Array.
You must ensure that the cursor points to an Array before calling this function.
@see isArray
*/
JSObject getChild (int64 index) const;
/** Returns a new cursor object pointing to the specified element in an Array. This function is
a shorthand for getChild (int64).
You must ensure that the cursor points to an Array before calling this function.
@see isArray
*/
JSObject operator[] (int64 index) const;
/** Returns true if the JS Object under the cursor is an Array.
You can use getChild() or operator[]() to get a cursor to individual elements in the
array or get() to obtain a JUCE variant wrapping all array elements.
*/
bool isArray() const;
/** Returns the size of the underlying JS Array.
You must ensure that the cursor points to an Array before calling this function.
@see isArray
*/
int64 getSize() const;
/** Returns true if the object under the cursor has a property with the given name. */
bool hasProperty (const Identifier& name) const;
/** Returns a variant with a value of the property under the given name. If no such property
exists an undefined variant is returned.
If this property points to an object created by JavascriptEngine::registerNativeObject(),
then the returned variant will contain a pointer to the original object and can be acquired
by variant::getDynamicObject().
*/
var get() const;
/** Adds a named property to the underlying Object with the provided value, or assigns this
value to an existing property with this name.
*/
void setProperty (const Identifier& name, const var& value) const;
/** Adds a property with an integral identifier and the provided value to the underlying Object,
or assigns the value to an existing property.
If the underlying Object is also an Array, then the provided value will be assigned to the
specified element of this Array, and ensure that it will have a size of at least index - 1.
*/
void setProperty (int64 index, const var& value) const;
/** Invokes this node as though it were a method.
If the optional Result pointer is provided it will contain Result::ok() in case of success,
or an error message in case an exception was thrown during evaluation.
*/
var invokeMethod (const Identifier& methodName, Span<const var> args, Result* result = nullptr) const;
/** Returns all properties of the current object that are own properties, i.e. not inherited. */
NamedValueSet getProperties() const;
private:
class Impl;
explicit JSObject (std::unique_ptr<Impl> implIn);
void swap (JSObject& other) noexcept;
std::unique_ptr<Impl> impl;
};
/**
A high-level wrapper around an owning root JSObject and a hierarchical path relative to it.
It can be used to query and manipulate the location relative to the root JSObject in the
Javascript Object graph. A cursor only maintains ownership of the root Object. So as long as a
cursor points at the root it will always remain in a valid state, and isValid will return true.
Using getChild you can add elements to the cursor's relative path. You need to ensure that the
cursor is in a valid state when calling get or set in such cases. You can use the isValid
function to determine if the cursor currently points to a reachable location.
@tags{Core}
*/
class JUCE_API JSCursor
{
public:
/** Creates a JSCursor that points to the provided root object and also participates in its
ownership. This guarantees that this root object will remain valid for the lifetime of
this cursor.
Child JSCursors created by getChild() will contain this same root object and each will
further ensure that this root remains valid through reference counting.
While the validity of the root is ensured through shared ownership, the JSCursor itself is
not guaranteed to be valid, unless its also pointing directly at the root.
@see isValid
*/
explicit JSCursor (JSObject root);
/** Returns an owning reference to the Javascript Object at the cursor's location. If there is
no Object at the location but the cursor is valid, a new Object will be created.
You must only call this function on a valid JSCursor.
By creating an owning reference, you can create a new JSCursor object that owns the
underlying object and is guaranteed to remain in a valid state e.g.
@code
JSCursor rootCursor { engine.getRootObject() };
auto nonOwningCursor = rootCursor["path"]["to"]["object"];
jassert (nonOwningCursor.isValid());
JSCursor owningCursor { nonOwningCursor.getOrCreateObject(); };
engine.execute (arbitraryScript);
// owningCursor is guaranteed to remain valid even after subsequent script evaluations
jassert (owningCursor.isValid());
@endcode
@see isValid
*/
JSObject getOrCreateObject() const;
/** Returns the value corresponding to the Object that the cursor points to. If there is no
Object at the cursor's location var::undefined() is returned.
This function is safe to call for invalid cursors.
@see isValid
*/
var get() const;
/** Sets the Object under the cursor's location to the specified value.
You must only call this function for valid cursors.
@see isValid
*/
void set (const var& value) const;
/** Invokes this node as though it were a method. If the optional Result pointer is provided it
will contain Result::ok() in case of success, or an error message in case an exception was
thrown during evaluation.
You must only call this function for valid cursors.
*/
var invoke (Span<const var> args, Result* result = nullptr) const;
/** Equivalent to invoke(). */
var operator() (Span<const var> args, Result* result = nullptr) const
{
return invoke (args, result);
}
/** Returns a new cursor that has the same root Object as the parent and has the name parameter
appended to the cursor's location.
If the new path points to a location unreachable from the root, the resulting JSCursor
object will be invalid. This however can change due to subsequent script executions.
*/
JSCursor getChild (const Identifier& name) const;
/** Returns a new cursor that has the same root Object as the parent and has the name parameter
appended to the cursor's location.
If the new path points to a location unreachable from the root, the resulting JSCursor
object will be invalid. This however can change due to subsequent script executions.
Shorthand for getChild.
*/
JSCursor operator[] (const Identifier& name) const;
/** Returns a new cursor that has the same root Object as the parent and has the index parameter
appended to the cursor's location. This overload will create a path that indexes into an
Array.
If the new path points to a location unreachable from the root, the resulting JSCursor
object will be invalid. This however can change due to subsequent script executions.
*/
JSCursor getChild (int64 index) const;
/** Returns a new cursor that has the same root Object as the parent and has the index parameter
appended to the cursor's location. This overload will create a path that indexes into an
Array.
If the new path points to a location unreachable from the root, the resulting JSCursor
object will be invalid. This however can change due to subsequent script executions.
Shorthand for getChild.
*/
JSCursor operator[] (int64 index) const;
/** Returns true if the location of the cursor is reachable from the cursor's JSObject root.
This means it is safe to call set on this JSCursor and the location will then point to an
Object corresponding to the supplied value.
It isn't guaranteed that there is already an Object at this location, in which case calling
get will return var::undefined().
*/
bool isValid() const;
/** Returns true if there is an Array under the cursor's location.
It is safe to call this function on an invalid cursor.
*/
bool isArray() const;
private:
using Property = std::variant<Identifier, int64>;
using PartialResolution = std::pair<JSObject, std::optional<Property>>;
static std::optional<JSObject> resolve (JSObject reference, Property property);
// Resolves the path to the second to last element. By taking ownership (creating an object for)
// of the second to last element, the result of a successful partial resolution can be used to
// construct the last element if it doesn't yet exist.
std::optional<PartialResolution> getPartialResolution() const;
// Fully resolves the path and takes ownership of the object that was specified by it.
std::optional<JSObject> getFullResolution() const;
JSObject root;
std::vector<Property> path;
};
//==============================================================================
/**
A simple javascript interpreter!
@ -60,8 +345,6 @@ class JUCE_API JavascriptEngine final
{
public:
/** Creates an instance of the engine.
This creates a root namespace and defines some basic Object, String, Array
and Math library methods.
*/
JavascriptEngine();
@ -80,6 +363,8 @@ public:
If there's a syntax error, or the expression can't be evaluated, the return value
will be var::undefined(). The errorMessage parameter gives you a way to find out
any parsing errors.
If the expression is successfully evaluated but yields no result the return value
will be a void var.
You can specify a maximum time for which the program is allowed to run, and
it'll return with an error message if this time is exceeded.
*/
@ -94,15 +379,6 @@ public:
const var::NativeFunctionArgs& args,
Result* errorMessage = nullptr);
/** Calls a function object in the namespace of a dynamic object, and returns the result.
The function arguments are passed in the same format as used by native
methods in the var class.
*/
var callFunctionObject (DynamicObject* objectScope,
const var& functionObject,
const var::NativeFunctionArgs& args,
Result* errorMessage = nullptr);
/** Adds a native object to the root namespace.
The object passed-in is reference-counted, and will be retained by the
engine until the engine is deleted. The name must be a simple JS identifier,
@ -120,15 +396,19 @@ public:
/** When called from another thread, causes the interpreter to time-out as soon as possible */
void stop() noexcept;
/** Returns the object from which all Javascript objects are reachable in the engine's context.
*/
JSObject getRootObject() const;
/** Provides access to the set of properties of the root namespace object. */
const NamedValueSet& getRootObjectProperties() const noexcept;
NamedValueSet getRootObjectProperties() const;
private:
JUCE_PUBLIC_IN_DLL_BUILD (struct RootObject)
const ReferenceCountedObjectPtr<RootObject> root;
void prepareTimeout() const noexcept;
class Impl;
std::unique_ptr<Impl> impl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JavascriptEngine)
JUCE_DECLARE_NON_MOVEABLE (JavascriptEngine)
};
} // namespace juce

View file

@ -229,6 +229,11 @@ namespace juce
extern JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger() noexcept;
extern JUCE_API void JUCE_CALLTYPE logAssertion (const char* file, int line) noexcept;
namespace detail
{
class QuickJSWrapper;
}
}
#include "misc/juce_EnumHelpers.h"