From 1085d16e13cdc475abc3666434b76c78a0222cad Mon Sep 17 00:00:00 2001 From: scheffle Date: Tue, 6 Feb 2024 19:58:10 +0100 Subject: [PATCH] add custom allocator for TinyJS --- .../detail/drawcontextobject.cpp | 6 +- .../detail/scriptobject.h | 4 +- .../detail/uidescscriptobject.h | 2 +- .../detail/viewscriptobject.cpp | 10 +- .../tiny-js/TinyJS.cpp | 155 +++++++++++------- .../uidescription-scripting/tiny-js/TinyJS.h | 108 ++++++++---- .../tiny-js/TinyJS_Functions.cpp | 6 +- .../uidescription-scripting/uiscripting.cpp | 4 +- vstgui/uidescription-scripting/uiscripting.h | 2 +- vstgui/uidescription/uiviewcreator.cpp | 21 ++- vstgui/uidescription/uiviewcreator.h | 1 + 11 files changed, 201 insertions(+), 118 deletions(-) diff --git a/vstgui/uidescription-scripting/detail/drawcontextobject.cpp b/vstgui/uidescription-scripting/detail/drawcontextobject.cpp index bd4f51c89..1c3a51b82 100644 --- a/vstgui/uidescription-scripting/detail/drawcontextobject.cpp +++ b/vstgui/uidescription-scripting/detail/drawcontextobject.cpp @@ -226,7 +226,7 @@ DrawContextObject::DrawContextObject () throw CScriptException ( "Missing `color` argument in drawContext.setFontColor(color);"); CColor color {}; - UIViewCreator::stringToColor (&colorVar->getString (), color, uiDesc); + UIViewCreator::stringToColor (colorVar->getString (), color, uiDesc); context->setFontColor (color); }, {"color"}); @@ -239,7 +239,7 @@ DrawContextObject::DrawContextObject () throw CScriptException ( "Missing `color` argument in drawContext.setFillColor(color);"); CColor color {}; - UIViewCreator::stringToColor (&colorVar->getString (), color, uiDesc); + UIViewCreator::stringToColor (colorVar->getString (), color, uiDesc); context->setFillColor (color); }, {"color"}); @@ -252,7 +252,7 @@ DrawContextObject::DrawContextObject () throw CScriptException ( "Missing `color` argument in drawContext.setFrameColor(color);"); CColor color {}; - if (!UIViewCreator::stringToColor (&colorVar->getString (), color, uiDesc)) + if (!UIViewCreator::stringToColor (colorVar->getString (), color, uiDesc)) throw CScriptException ( "Unknown `color` argument in drawContext.setFrameColor(color);"); context->setFrameColor (color); diff --git a/vstgui/uidescription-scripting/detail/scriptobject.h b/vstgui/uidescription-scripting/detail/scriptobject.h index 0bca69e02..dadb9737d 100644 --- a/vstgui/uidescription-scripting/detail/scriptobject.h +++ b/vstgui/uidescription-scripting/detail/scriptobject.h @@ -120,9 +120,9 @@ struct ScriptObject { scriptVar->addChild (name, new CScriptVar (static_cast (i))); } - void addChild (std::string_view name, const std::string& value) + void addChild (std::string_view name, std::string_view value) { - scriptVar->addChild (name, new CScriptVar (value)); + scriptVar->addChild (name, new CScriptVar (TJS::string {value.data (), value.size ()})); } void addFunc (std::string_view name, std::function&& func) { diff --git a/vstgui/uidescription-scripting/detail/uidescscriptobject.h b/vstgui/uidescription-scripting/detail/uidescscriptobject.h index b89fcd286..f05aa7edf 100644 --- a/vstgui/uidescription-scripting/detail/uidescscriptobject.h +++ b/vstgui/uidescription-scripting/detail/uidescscriptobject.h @@ -53,7 +53,7 @@ struct UIDescScriptObject : ScriptObject { throw CScriptException ("Expect 'name' argument for getTagForName "); } - std::string name = param->getString (); + auto name = param->getString (); auto tag = desc->getTagForName (name.data ()); var->setReturnVar (new CScriptVar (static_cast (tag))); }, diff --git a/vstgui/uidescription-scripting/detail/viewscriptobject.cpp b/vstgui/uidescription-scripting/detail/viewscriptobject.cpp index 09f456634..0efe9dc0d 100644 --- a/vstgui/uidescription-scripting/detail/viewscriptobject.cpp +++ b/vstgui/uidescription-scripting/detail/viewscriptobject.cpp @@ -32,7 +32,7 @@ ViewScriptObject::ViewScriptObject (CView* view, IViewScriptObjectContext* conte auto key = var->getParameter ("key"sv); auto value = var->getParameter ("value"sv); UIAttributes attr; - attr.setAttribute (key->getString (), value->getString ()); + attr.setAttribute (key->getString ().data (), value->getString ().data ()); auto result = uiDesc->getViewFactory ()->applyAttributeValues (view, attr, uiDesc); var->getReturnVar ()->setInt (result); }, @@ -41,8 +41,8 @@ ViewScriptObject::ViewScriptObject (CView* view, IViewScriptObjectContext* conte [uiDesc = context->getUIDescription (), view] (CScriptVar* var) { auto key = var->getParameter ("key"sv); std::string result; - if (uiDesc->getViewFactory ()->getAttributeValue (view, key->getString (), result, - uiDesc)) + if (uiDesc->getViewFactory ()->getAttributeValue (view, key->getString ().data (), + result, uiDesc)) { var->getReturnVar ()->setString (result); } @@ -56,7 +56,7 @@ ViewScriptObject::ViewScriptObject (CView* view, IViewScriptObjectContext* conte [uiDesc = context->getUIDescription (), view] (CScriptVar* var) { auto typeName = var->getParameter ("typeName"sv); auto result = - uiDesc->getViewFactory ()->viewIsTypeOf (view, typeName->getString ()); + uiDesc->getViewFactory ()->viewIsTypeOf (view, typeName->getString ().data ()); var->getReturnVar ()->setInt (result); }, {"typeName"}); @@ -135,7 +135,7 @@ ViewScriptObject::ViewScriptObject (CView* view, IViewScriptObjectContext* conte else if (value->isDouble ()) propValue = value->getDouble (); else if (value->isString ()) - propValue = value->getString (); + propValue = value->getString ().data (); auto result = controller->setProperty (view, name->getString (), propValue); var->getReturnVar ()->setInt (result); }, diff --git a/vstgui/uidescription-scripting/tiny-js/TinyJS.cpp b/vstgui/uidescription-scripting/tiny-js/TinyJS.cpp index 2c8c2c04b..800b5bbc2 100644 --- a/vstgui/uidescription-scripting/tiny-js/TinyJS.cpp +++ b/vstgui/uidescription-scripting/tiny-js/TinyJS.cpp @@ -230,7 +230,7 @@ static inline void CREATE_LINK (CScriptVarLink*& link, CScriptVar* var) bool isWhitespace (char ch) { return (ch == ' ') || (ch == '\t') || (ch == '\n') || (ch == '\r'); } bool isNumeric (char ch) { return (ch >= '0') && (ch <= '9'); } -bool isNumber (const std::string& str) +bool isNumber (const string& str) { for (size_t i = 0; i < str.size (); i++) if (!isNumeric (str[i])) @@ -248,12 +248,12 @@ bool isAlpha (char ch) } /// convert the given string into a quoted string suitable for javascript -std::string getJSString (const std::string& str) +string getJSString (std::string_view str) { - std::string nStr = str; + string nStr {str.data (), str.size ()}; for (size_t i = 0; i < nStr.size (); i++) { - std::string replaceWith = ""; + string replaceWith = ""; bool replace = true; switch (nStr[i]) @@ -310,7 +310,7 @@ int64_t stringToInteger (std::string_view str) } else { - if (str.find_first_of ('.') == std::string::npos) + if (str.find_first_of ('.') == string::npos) { base = 8; } @@ -335,16 +335,33 @@ static double stringToDouble (std::string_view str) return value; } -// ----------------------------------------------------------------------------------- -// CSCRIPTEXCEPTION +//------------------------------------------------------------------------ +AllocatorFunc allocator = [] (size_t size) { + return operator new (size); +}; -CScriptException::CScriptException (const std::string& exceptionText) { text = exceptionText; } -CScriptException::CScriptException (std::string&& exceptionText) +//------------------------------------------------------------------------ +DeallocatorFunc deallocator = [] (void* ptr, size_t size) { + return operator delete (ptr, size); +}; + +//------------------------------------------------------------------------ +void setCustomAllocator (AllocatorFunc&& _allocator, DeallocatorFunc&& _deallocator) { - text = std::move (exceptionText); + allocator = std::move (_allocator); + deallocator = std::move (_deallocator); } + +// ----------------------------------------------------------------------------------- +// CSCRIPTEXCEPTION + +CScriptException::CScriptException (const string& exceptionText) { text = exceptionText; } +CScriptException::CScriptException (string&& exceptionText) { text = std::move (exceptionText); } CScriptException::~CScriptException () noexcept {} +void* CScriptException::operator new (std::size_t count) { return allocator (count); } +void CScriptException::operator delete (void* ptr, std::size_t size) { deallocator (ptr, size); } + struct LexTokenDef { LexType type; @@ -426,6 +443,9 @@ CScriptLex::CScriptLex (std::string_view input) CScriptLex::~CScriptLex (void) {} +void* CScriptLex::operator new (std::size_t count) { return allocator (count); } +void CScriptLex::operator delete (void* ptr, std::size_t size) { deallocator (ptr, size); } + void CScriptLex::reset () { dataPos = 0; @@ -443,7 +463,7 @@ void CScriptLex::match (int expected_tk) { if (token != expected_tk) { - std::ostringstream errorString; + ostringstream errorString; errorString << "Got " << getTokenStr (token) << " expected " << getTokenStr (expected_tk) << " at " << getPosition (tokenStart); throw CScriptException (errorString.str ()); @@ -455,7 +475,7 @@ void CScriptLex::match (LexType expected_tk) { if (token != asInteger (expected_tk)) { - std::ostringstream errorString; + ostringstream errorString; errorString << "Got " << getTokenStr (token) << " expected " << findTokenName (expected_tk) << " at " << getPosition (tokenStart); throw CScriptException (errorString.str ()); @@ -463,11 +483,11 @@ void CScriptLex::match (LexType expected_tk) getNextToken (); } -std::string CScriptLex::getTokenStr (int token) +string CScriptLex::getTokenStr (int token) { if (token > 32 && token < 128) { - std::string str ("' '"); + string str ("' '"); str[1] = static_cast (token); return str; } @@ -475,7 +495,7 @@ std::string CScriptLex::getTokenStr (int token) if (!tokenString.empty ()) return {tokenString.data (), tokenString.size ()}; - std::ostringstream msg; + ostringstream msg; msg << "?[" << token << "]"; return msg.str (); } @@ -787,17 +807,17 @@ void CScriptLex::getNextToken () tokenEnd = dataPos - 3; } -std::string CScriptLex::getSubString (size_t lastPosition) const +string CScriptLex::getSubString (size_t lastPosition) const { size_t lastCharIdx = tokenLastEnd + 1; if (lastCharIdx < dataEnd) { - std::string value (&data[lastPosition], lastCharIdx - lastPosition); + string value (&data[lastPosition], lastCharIdx - lastPosition); return value; } else { - return std::string (&data[lastPosition]); + return string (&data[lastPosition]); } } @@ -810,7 +830,7 @@ CScriptLex* CScriptLex::getSubLex (size_t lastPosition) const return new CScriptLex ({data + lastPosition, dataEnd - lastPosition}); } -std::string CScriptLex::getPosition (size_t pos) const +string CScriptLex::getPosition (size_t pos) const { if (pos == std::numeric_limits::max ()) pos = tokenLastEnd; @@ -826,14 +846,14 @@ std::string CScriptLex::getPosition (size_t pos) const } colNo = pos - lastLinePos; - return std::string ("(line: ") + std::to_string (lineNo) + std::string (", col: ") + - std::to_string (colNo) + std::string (")"); + return string ("(line: ") + std::to_string (lineNo).data () + string (", col: ") + + std::to_string (colNo).data () + string (")"); } // ----------------------------------------------------------------------------------- // CSCRIPTVARLINK -CScriptVarLink::CScriptVarLink (CScriptVar* inVar, const std::string& inName, bool own) +CScriptVarLink::CScriptVarLink (CScriptVar* inVar, const string& inName, bool own) : name (inName), var (inVar->addRef ()), isOwned (own) { #if DEBUG_MEMORY @@ -857,6 +877,9 @@ CScriptVarLink::~CScriptVarLink () var->release (); } +void* CScriptVarLink::operator new (std::size_t count) { return allocator (count); } +void CScriptVarLink::operator delete (void* ptr, std::size_t size) { deallocator (ptr, size); } + void CScriptVarLink::replaceWith (CScriptVar* newVar) { CScriptVar* oldVar = var; @@ -897,16 +920,16 @@ CScriptVar::CScriptVar () flags = SCRIPTVAR_UNDEFINED; } -CScriptVar::CScriptVar (const std::string& str) +CScriptVar::CScriptVar (std::string_view str) { #if DEBUG_MEMORY mark_allocated (this); #endif flags = SCRIPTVAR_STRING; - variant = str; + variant = string (str.data (), str.size ()); } -CScriptVar::CScriptVar (const std::string& varData, int varFlags) +CScriptVar::CScriptVar (const string& varData, int varFlags) { #if DEBUG_MEMORY mark_allocated (this); @@ -964,6 +987,9 @@ CScriptVar::~CScriptVar (void) removeAllChildren (); } +void* CScriptVar::operator new (std::size_t count) { return allocator (count); } +void CScriptVar::operator delete (void* ptr, std::size_t size) { deallocator (ptr, size); } + CScriptVar* CScriptVar::getReturnVar () { return getParameter (TINYJS_RETURN_VAR); } void CScriptVar::setReturnVar (CScriptVar* var) @@ -997,10 +1023,10 @@ CScriptVarLink* CScriptVar::findChildOrCreate (std::string_view childName, int v return addChild (childName, new CScriptVar (TINYJS_BLANK_DATA, varFlags)); } -CScriptVarLink* CScriptVar::findChildOrCreateByPath (const std::string& path) +CScriptVarLink* CScriptVar::findChildOrCreateByPath (const string& path) { size_t p = path.find ('.'); - if (p == std::string::npos) + if (p == string::npos) return findChildOrCreate (path); return findChildOrCreate (path.substr (0, p), SCRIPTVAR_OBJECT) @@ -1182,12 +1208,12 @@ double CScriptVar::getDouble () return 0; /* or NaN? */ } -const std::string& CScriptVar::getString () +const string& CScriptVar::getString () { /* Because we can't return a string that is generated on demand. * I should really just use char* :) */ - static std::string s_null = "null"; - static std::string s_undefined = "undefined"; + static string s_null = "null"; + static string s_undefined = "undefined"; if (isInt ()) { dataStr = std::to_string (std::get (variant)); @@ -1204,7 +1230,7 @@ const std::string& CScriptVar::getString () return s_null; if (isUndefined ()) return s_undefined; - if (auto s = std::get_if (&variant)) + if (auto s = std::get_if (&variant)) return *s; return s_undefined; } @@ -1225,7 +1251,7 @@ void CScriptVar::setString (std::string_view str) { // name sure it's not still a number or integer flags = (flags & ~SCRIPTVAR_VARTYPEMASK) | SCRIPTVAR_STRING; - variant = std::string (str); + variant = string (str); } void CScriptVar::setUndefined () @@ -1388,8 +1414,8 @@ CScriptVar* CScriptVar::mathsOp (CScriptVar* b, int op) } else { - std::string da = a->getString (); - std::string db = b->getString (); + string da = a->getString (); + string db = b->getString (); // use strings switch (op) { @@ -1472,11 +1498,11 @@ CScriptVar* CScriptVar::deepCopy () return newVar; } -void CScriptVar::trace (std::string indentStr, const std::string& name) +void CScriptVar::trace (string indentStr, const string& name) { TRACE ("%s'%s' = '%s' %s\n", indentStr.c_str (), name.c_str (), getString ().c_str (), getFlagsAsString ().c_str ()); - std::string indent = indentStr + " "; + string indent = indentStr + " "; CScriptVarLink* link = firstChild; while (link) { @@ -1485,9 +1511,9 @@ void CScriptVar::trace (std::string indentStr, const std::string& name) } } -std::string CScriptVar::getFlagsAsString () +string CScriptVar::getFlagsAsString () { - std::string flagstr = ""; + string flagstr = ""; if (flags & SCRIPTVAR_FUNCTION) flagstr = flagstr + "FUNCTION "; if (flags & SCRIPTVAR_OBJECT) @@ -1505,14 +1531,14 @@ std::string CScriptVar::getFlagsAsString () return flagstr; } -std::string CScriptVar::getParsableString () +string CScriptVar::getParsableString () { // Numbers can just be put in directly if (isNumeric ()) return getString (); if (isFunction ()) { - std::ostringstream funcStr; + ostringstream funcStr; funcStr << "function ("; // get list of parameters CScriptVarLink* link = firstChild; @@ -1535,11 +1561,11 @@ std::string CScriptVar::getParsableString () return "undefined"; } -void CScriptVar::getJSON (std::ostream& destination, const std::string linePrefix) +void CScriptVar::getJSON (std::ostream& destination, const string linePrefix) { if (isObject ()) { - std::string indentedLinePrefix = linePrefix + " "; + string indentedLinePrefix = linePrefix + " "; // children - handle with bracketed list destination << "{ \n"; CScriptVarLink* link = firstChild; @@ -1559,7 +1585,7 @@ void CScriptVar::getJSON (std::ostream& destination, const std::string linePrefi } else if (isArray ()) { - std::string indentedLinePrefix = linePrefix + " "; + string indentedLinePrefix = linePrefix + " "; destination << "[\n"; int len = getArrayLength (); if (len > 10000) @@ -1598,7 +1624,7 @@ void CScriptVar::callCallback (CScriptVar* var) void CScriptVar::setFunctionScript (std::string_view str) { ASSERT (isFunction ()); - variant = std::string {str.data (), str.size ()}; + variant = string {str.data (), str.size ()}; } CScriptVar* CScriptVar::addRef () @@ -1647,9 +1673,12 @@ CTinyJS::~CTinyJS () #endif } +void* CTinyJS::operator new (std::size_t count) { return allocator (count); } +void CTinyJS::operator delete (void* ptr, std::size_t size) { deallocator (ptr, size); } + void CTinyJS::trace () { root->trace (); } -void CTinyJS::execute (const std::string& code) +void CTinyJS::execute (const string& code) { CScriptLex* oldLex = lexer; std::vector oldScopes = std::move (scopes); @@ -1667,7 +1696,7 @@ void CTinyJS::execute (const std::string& code) } catch (CScriptException& e) { - std::ostringstream msg; + ostringstream msg; msg << "Error " << e.text; #ifdef TINYJS_CALL_STACK for (int i = (int)call_stack.size () - 1; i >= 0; i--) @@ -1710,7 +1739,7 @@ CScriptVarLink CTinyJS::evaluateComplex (std::string_view code) } catch (CScriptException& e) { - std::ostringstream msg; + ostringstream msg; msg << "Error: " << e.text; #ifdef TINYJS_CALL_STACK for (int i = (int)call_stack.size () - 1; i >= 0; i--) @@ -1737,7 +1766,7 @@ CScriptVarLink CTinyJS::evaluateComplex (std::string_view code) return CScriptVarLink (new CScriptVar ()); } -std::string CTinyJS::evaluate (std::string_view code) +string CTinyJS::evaluate (std::string_view code) { return evaluateComplex (code).getVar ()->getString (); } @@ -1763,7 +1792,7 @@ void CTinyJS::addNative (std::string_view funcDesc, const JSCallback& ptr) CScriptVar* base = root; lexer->match (LexType::R_FUNCTION); - std::string funcName = lexer->getTokenString (); + string funcName = lexer->getTokenString (); lexer->match (LexType::ID); /* Check for dots, we might want to do something like function String.substring ... */ while (lexer->getToken () == '.') @@ -1791,7 +1820,7 @@ CScriptVarLink* CTinyJS::parseFunctionDefinition () { // actually parse a function... lexer->match (LexType::R_FUNCTION); - std::string funcName = TINYJS_TEMP_NAME; + string funcName = TINYJS_TEMP_NAME; /* we can have functions without names */ if (lexer->getToken () == asInteger (LexType::ID)) { @@ -1818,7 +1847,7 @@ CScriptVarLink* CTinyJS::functionCall (bool& execute, CScriptVarLink* function, { if (!function->getVar ()->isFunction ()) { - std::string errorMsg = "Expecting '"; + string errorMsg = "Expecting '"; errorMsg = errorMsg + function->getName () + "' to be a function"; throw CScriptException (errorMsg.c_str ()); } @@ -1870,7 +1899,7 @@ CScriptVarLink* CTinyJS::functionCall (bool& execute, CScriptVarLink* function, /* we just want to execute the block, but something could * have messed up and left us with the wrong ScriptLex, so * we want to be careful here... */ - std::string exceptionText; + string exceptionText; CScriptLex* oldLex = lexer; CScriptLex* newLex = new CScriptLex (function->getVar ()->getString ()); lexer = newLex; @@ -1982,7 +2011,7 @@ CScriptVarLink* CTinyJS::factor (bool& execute) lexer->match ('.'); if (execute) { - const std::string& name = lexer->getTokenString (); + const string& name = lexer->getTokenString (); CScriptVarLink* child = a->getVar ()->findChild (name); if (!child) child = findInParentClasses (a->getVar (), name); @@ -2052,7 +2081,7 @@ CScriptVarLink* CTinyJS::factor (bool& execute) lexer->match ('{'); while (lexer->getToken () != '}') { - std::string id = lexer->getTokenString (); + string id = lexer->getTokenString (); // we only allow strings or IDs on the left hand side of an initialisation if (lexer->getToken () == asInteger (LexType::STR)) lexer->match (LexType::STR); @@ -2109,7 +2138,7 @@ CScriptVarLink* CTinyJS::factor (bool& execute) { // new -> create a new object lexer->match (LexType::R_NEW); - const std::string& className = lexer->getTokenString (); + const string& className = lexer->getTokenString (); if (execute) { CScriptVarLink* objClassOrFunc = findInScopes (className); @@ -2655,29 +2684,29 @@ void CTinyJS::statement (bool& execute) } /// Get the given variable specified by a path (var1.var2.etc), or return 0 -CScriptVar* CTinyJS::getScriptVariable (const std::string& path) const +CScriptVar* CTinyJS::getScriptVariable (const string& path) const { // traverse path size_t prevIdx = 0; size_t thisIdx = path.find ('.'); - if (thisIdx == std::string::npos) + if (thisIdx == string::npos) thisIdx = path.length (); CScriptVar* var = root; while (var && prevIdx < path.length ()) { - std::string el = path.substr (prevIdx, thisIdx - prevIdx); + string el = path.substr (prevIdx, thisIdx - prevIdx); CScriptVarLink* varl = var->findChild (el); var = varl ? varl->getVar () : 0; prevIdx = thisIdx + 1; thisIdx = path.find ('.', prevIdx); - if (thisIdx == std::string::npos) + if (thisIdx == string::npos) thisIdx = path.length (); } return var; } /// Get the value of the given variable, or return 0 -const std::string* CTinyJS::getVariable (const std::string& path) const +const string* CTinyJS::getVariable (const string& path) const { CScriptVar* var = getScriptVariable (path); // return result @@ -2688,7 +2717,7 @@ const std::string* CTinyJS::getVariable (const std::string& path) const } /// set the value of the given variable, return trur if it exists and gets set -bool CTinyJS::setVariable (const std::string& path, const std::string& varData) +bool CTinyJS::setVariable (const string& path, const string& varData) { CScriptVar* var = getScriptVariable (path); // return result @@ -2707,7 +2736,7 @@ bool CTinyJS::setVariable (const std::string& path, const std::string& varData) } /// Finds a child, looking recursively up the scopes -CScriptVarLink* CTinyJS::findInScopes (const std::string& childName) const +CScriptVarLink* CTinyJS::findInScopes (const string& childName) const { for (int64_t s = scopes.size () - 1; s >= 0; s--) { @@ -2719,7 +2748,7 @@ CScriptVarLink* CTinyJS::findInScopes (const std::string& childName) const } /// Look up in any parent classes of the given object -CScriptVarLink* CTinyJS::findInParentClasses (CScriptVar* object, const std::string& name) const +CScriptVarLink* CTinyJS::findInParentClasses (CScriptVar* object, const string& name) const { // Look for links to actual parent classes CScriptVarLink* parentClass = object->findChild (TINYJS_PROTOTYPE_CLASS); diff --git a/vstgui/uidescription-scripting/tiny-js/TinyJS.h b/vstgui/uidescription-scripting/tiny-js/TinyJS.h index d10efc5ec..4e8050258 100644 --- a/vstgui/uidescription-scripting/tiny-js/TinyJS.h +++ b/vstgui/uidescription-scripting/tiny-js/TinyJS.h @@ -135,20 +135,56 @@ static constexpr auto TINYJS_PROTOTYPE_CLASS = "prototype"; static constexpr auto TINYJS_TEMP_NAME = ""; static constexpr auto TINYJS_BLANK_DATA = ""; +//------------------------------------------------------------------------ +// Custom memory allocator +using AllocatorFunc = std::function; +using DeallocatorFunc = std::function; +extern AllocatorFunc allocator; +extern DeallocatorFunc deallocator; + +void setCustomAllocator (AllocatorFunc&& allocator, DeallocatorFunc&& deallocator); + +//------------------------------------------------------------------------ +template +struct Allocator +{ + using value_type = T; + using propagate_on_container_move_assignment = std::true_type; + + Allocator () = default; + + template + constexpr Allocator (const Allocator&) noexcept + { + } + + [[nodiscard]] T* allocate (std::size_t n) + { + return static_cast (allocator (n * sizeof (T))); + } + void deallocate (T* p, std::size_t n) noexcept { deallocator (p, n); } +}; + +using string = std::basic_string, Allocator>; +using ostringstream = std::basic_ostringstream, Allocator>; + /** convert the given string into a quoted string suitable for javascript */ -std::string getJSString (const std::string& str); +string getJSString (std::string_view str); /** convert the given string to an 64 bit integer supporting hex and octal written numbers */ int64_t stringToInteger (std::string_view str); class CScriptException { public: - std::string text; - CScriptException (const std::string& exceptionText); - CScriptException (std::string&& exceptionText); + string text; + CScriptException (const string& exceptionText); + CScriptException (string&& exceptionText); CScriptException (const CScriptException&) = default; CScriptException (CScriptException&&) = default; ~CScriptException () noexcept; + + static void* operator new (std::size_t count); + static void operator delete (void* ptr, std::size_t size); }; class CScriptLex @@ -158,7 +194,7 @@ class CScriptLex ~CScriptLex (void); /** Get the string representation of the given token */ - static std::string getTokenStr (int token); + static string getTokenStr (int token); /** Lexical match wotsit */ void match (int expected_tk); @@ -169,14 +205,17 @@ class CScriptLex int getToken () const { return token; } size_t getTokenStart () const { return tokenStart; } size_t getTokenEnd () const { return tokenEnd; } - const std::string& getTokenString () const { return tkStr; } + const string& getTokenString () const { return tkStr; } /** Return a sub-string from the given position up until right now */ - std::string getSubString (size_t pos) const; + string getSubString (size_t pos) const; /** Return a sub-lexer from the given position up until right now */ CScriptLex* getSubLex (size_t lastPosition) const; /** Return a string representing the position in lines and columns of the character pos given */ - std::string getPosition (size_t pos = std::numeric_limits::max ()) const; + string getPosition (size_t pos = std::numeric_limits::max ()) const; + + static void* operator new (std::size_t count); + static void operator delete (void* ptr, std::size_t size); private: void getNextCh (); @@ -192,7 +231,7 @@ class CScriptLex /** Position in the data at the last character of the last token */ size_t tokenLastEnd; /** Data contained in the token we have here */ - std::string tkStr; + string tkStr; char currCh, nextCh; @@ -213,7 +252,7 @@ using JSCallback = std::function; class CScriptVarLink { public: - CScriptVarLink (CScriptVar* var, const std::string& name = TINYJS_TEMP_NAME, bool own = false); + CScriptVarLink (CScriptVar* var, const string& name = TINYJS_TEMP_NAME, bool own = false); /** Copy constructor */ CScriptVarLink (const CScriptVarLink& link); ~CScriptVarLink (); @@ -226,7 +265,7 @@ class CScriptVarLink /** Set the name as an integer (for arrays) */ void setIntName (int n); - const std::string& getName () const { return name; } + const string& getName () const { return name; } void setNextSibling (CScriptVarLink* s) { nextSibling = s; } void setPrevSibling (CScriptVarLink* s) { prevSibling = s; } @@ -238,8 +277,11 @@ class CScriptVarLink bool owned () const { return isOwned; } + static void* operator new (std::size_t count); + static void operator delete (void* ptr, std::size_t size); + private: - std::string name; + string name; CScriptVarLink* nextSibling {nullptr}; CScriptVarLink* prevSibling {nullptr}; CScriptVar* var {nullptr}; @@ -260,9 +302,9 @@ class CScriptVar /** Create undefined */ CScriptVar (); /** User defined */ - CScriptVar (const std::string& varData, int varFlags); + CScriptVar (const string& varData, int varFlags); /** Create a string */ - CScriptVar (const std::string& str); + CScriptVar (std::string_view str); /** Create a double */ CScriptVar (double varData); /** Create an integer */ @@ -285,7 +327,7 @@ class CScriptVar CScriptVarLink* findChildOrCreate (std::string_view childName, int varFlags = SCRIPTVAR_UNDEFINED); /** Tries to find a child with the given path (separated by dots) */ - CScriptVarLink* findChildOrCreateByPath (const std::string& path); + CScriptVarLink* findChildOrCreateByPath (const string& path); /** add a child if not already exist */ CScriptVarLink* addChild (std::string_view childName, CScriptVar* child = NULL); /** add a child overwriting any with the same name */ @@ -307,9 +349,9 @@ class CScriptVar int64_t getInt (); bool getBool () { return getInt () != 0; } double getDouble (); - const std::string& getString (); + const string& getString (); /** get Data as a parsable javascript string */ - std::string getParsableString (); + string getParsableString (); void setInt (int64_t num); void setDouble (double val); void setString (std::string_view str); @@ -338,11 +380,11 @@ class CScriptVar CScriptVar* deepCopy (); /** Dump out the contents of this using trace */ - void trace (std::string indentStr = "", const std::string& name = ""); + void trace (string indentStr = "", const string& name = ""); /** For debugging - just dump a string version of the flags */ - std::string getFlagsAsString (); + string getFlagsAsString (); /** Write out all the JS code needed to recreate this script variable to the stream (as JSON) */ - void getJSON (std::ostream& destination, const std::string linePrefix = ""); + void getJSON (std::ostream& destination, const string linePrefix = ""); /** Set the callback for native functions */ void setCallback (const JSCallback& callback); /** Moves in the callback for native functions */ @@ -365,6 +407,9 @@ class CScriptVar CScriptVarLink* getFirstChild () const { return firstChild; } CScriptVarLink* getLastChild () const { return lastChild; } + static void* operator new (std::size_t count); + static void operator delete (void* ptr, std::size_t size); + protected: CScriptVarLink* firstChild {nullptr}; CScriptVarLink* lastChild {nullptr}; @@ -373,8 +418,8 @@ class CScriptVar int refs {0}; /** the flags determine the type of the variable - int/double/string/etc */ int flags {0}; - std::variant variant; - std::string dataStr; + std::variant variant; + string dataStr; /** Copy the basic data and flags from the variable given, with no * children. Should be used internally only - by copyValue and deepCopy */ @@ -390,7 +435,7 @@ class CTinyJS CTinyJS (); ~CTinyJS (); - void execute (const std::string& code); + void execute (const string& code); /** Evaluate the given code and return a link to a javascript object, * useful for (dangerous) JSON parsing. If nothing to return, will return * 'undefined' variable type. CScriptVarLink is returned as this will @@ -399,7 +444,7 @@ class CTinyJS CScriptVarLink evaluateComplex (std::string_view code); /** Evaluate the given code and return a string. If nothing to return, will return * 'undefined' */ - std::string evaluate (std::string_view code); + string evaluate (std::string_view code); /** add a native function to be called from TinyJS example: @@ -418,17 +463,20 @@ class CTinyJS void addNative (std::string_view funcDesc, const JSCallback& ptr); /** Get the given variable specified by a path (var1.var2.etc), or return 0 */ - CScriptVar* getScriptVariable (const std::string& path) const; + CScriptVar* getScriptVariable (const string& path) const; /** Get the value of the given variable, or return 0 */ - const std::string* getVariable (const std::string& path) const; + const string* getVariable (const string& path) const; /** set the value of the given variable, return trur if it exists and gets set */ - bool setVariable (const std::string& path, const std::string& varData); + bool setVariable (const string& path, const string& varData); /** Send all variables to stdout */ void trace (); CScriptVar* getRoot () const { return root; } + static void* operator new (std::size_t count); + static void operator delete (void* ptr, std::size_t size); + private: /** root of symbol table */ CScriptVar* root {nullptr}; @@ -438,7 +486,7 @@ class CTinyJS std::vector scopes; #ifdef TINYJS_CALL_STACK /** Names of places called so we can show when erroring */ - std::vector call_stack; + std::vector call_stack; #endif /** Built in string class */ @@ -466,9 +514,9 @@ class CTinyJS void parseFunctionArguments (CScriptVar* funcVar) const; /** Finds a child, looking recursively up the scopes */ - CScriptVarLink* findInScopes (const std::string& childName) const; + CScriptVarLink* findInScopes (const string& childName) const; /** Look up in any parent classes of the given object */ - CScriptVarLink* findInParentClasses (CScriptVar* object, const std::string& name) const; + CScriptVarLink* findInParentClasses (CScriptVar* object, const string& name) const; }; //------------------------------------------------------------------------ diff --git a/vstgui/uidescription-scripting/tiny-js/TinyJS_Functions.cpp b/vstgui/uidescription-scripting/tiny-js/TinyJS_Functions.cpp index 453081272..ebfa4ab8f 100644 --- a/vstgui/uidescription-scripting/tiny-js/TinyJS_Functions.cpp +++ b/vstgui/uidescription-scripting/tiny-js/TinyJS_Functions.cpp @@ -162,7 +162,7 @@ void scIntegerValueOf (CScriptVar* c) void scJSONStringify (CScriptVar* c) { - std::ostringstream result; + ostringstream result; c->getParameter ("obj"sv)->getJSON (result); c->getReturnVar ()->setString (result.str ()); } @@ -170,14 +170,14 @@ void scJSONStringify (CScriptVar* c) void scExec (CScriptVar* c, void* data) { CTinyJS* tinyJS = (CTinyJS*)data; - std::string str = c->getParameter ("jsCode"sv)->getString (); + string str = c->getParameter ("jsCode"sv)->getString (); tinyJS->execute (str); } void scEval (CScriptVar* c, void* data) { CTinyJS* tinyJS = (CTinyJS*)data; - std::string str = c->getParameter ("jsCode"sv)->getString (); + string str = c->getParameter ("jsCode"sv)->getString (); c->setReturnVar (tinyJS->evaluateComplex (str).getVar ()); } diff --git a/vstgui/uidescription-scripting/uiscripting.cpp b/vstgui/uidescription-scripting/uiscripting.cpp index 78dc61e97..ff3d0192c 100644 --- a/vstgui/uidescription-scripting/uiscripting.cpp +++ b/vstgui/uidescription-scripting/uiscripting.cpp @@ -39,7 +39,7 @@ struct ViewScriptObject; class ScriptContext : public IScriptContext { public: - using OnScriptException = std::function; + using OnScriptException = std::function; ScriptContext (IUIDescription* uiDesc, const OnScriptException& func); ~ScriptContext () noexcept; @@ -799,7 +799,7 @@ struct UIScripting::Impl static OnScriptException onScriptExceptionFunc; }; UIScripting::OnScriptException UIScripting::Impl::onScriptExceptionFunc = - [] (const std::string& reason) { + [] (std::string_view reason) { std::cerr << reason << '\n'; }; diff --git a/vstgui/uidescription-scripting/uiscripting.h b/vstgui/uidescription-scripting/uiscripting.h index 27500fe5a..cfd281967 100644 --- a/vstgui/uidescription-scripting/uiscripting.h +++ b/vstgui/uidescription-scripting/uiscripting.h @@ -22,7 +22,7 @@ namespace VSTGUI { class UIScripting : public UIDescriptionAddOnAdapter { public: - using OnScriptException = std::function; + using OnScriptException = std::function; /** initialize the UIScripting library * diff --git a/vstgui/uidescription/uiviewcreator.cpp b/vstgui/uidescription/uiviewcreator.cpp index 716059625..9a58afd7a 100644 --- a/vstgui/uidescription/uiviewcreator.cpp +++ b/vstgui/uidescription/uiviewcreator.cpp @@ -441,23 +441,20 @@ bool colorToString (const CColor& color, std::string& string, const IUIDescripti return true; } -//----------------------------------------------------------------------------- -bool stringToColor (const std::string* value, CColor& color, const IUIDescription* desc) +bool stringToColor (std::string_view value, CColor& color, const IUIDescription* desc) { - if (!value) - return false; - if (*value == "") + if (value == "") { color = kTransparentCColor; return true; } - if (desc->getColor (value->data (), color)) + if (desc->getColor (value.data (), color)) return true; - if (color.fromString (value->data ())) + if (color.fromString (value.data ())) return true; for (const auto& namedColor : getCSSNamedColors ()) { - if (namedColor.name == *value) + if (namedColor.name == value) { color = namedColor.color; return true; @@ -466,6 +463,14 @@ bool stringToColor (const std::string* value, CColor& color, const IUIDescriptio return false; } +//----------------------------------------------------------------------------- +bool stringToColor (const std::string* value, CColor& color, const IUIDescription* desc) +{ + if (!value) + return false; + return stringToColor (*value, color, desc); +} + //----------------------------------------------------------------------------- bool stringToBitmap (const std::string* value, CBitmap*& bitmap, const IUIDescription* desc) { diff --git a/vstgui/uidescription/uiviewcreator.h b/vstgui/uidescription/uiviewcreator.h index 785136b36..6354e444c 100644 --- a/vstgui/uidescription/uiviewcreator.h +++ b/vstgui/uidescription/uiviewcreator.h @@ -22,6 +22,7 @@ VSTGUI_DEPRECATED (extern bool pointToString (const CPoint& p, std::string& stri extern bool bitmapToString (CBitmap* bitmap, std::string& string, const IUIDescription* desc); extern bool colorToString (const CColor& color, std::string& string, const IUIDescription* desc); extern bool stringToColor (const std::string* value, CColor& color, const IUIDescription* desc); +extern bool stringToColor (std::string_view value, CColor& color, const IUIDescription* desc); extern bool stringToBitmap (const std::string* value, CBitmap*& bitmap, const IUIDescription* desc); extern void applyStyleMask (const std::string* value, int32_t mask, int32_t& style);