--- linuxsampler/trunk/src/scriptvm/CoreVMFunctions.cpp 2017/01/05 18:00:52 3076 +++ linuxsampler/trunk/src/scriptvm/CoreVMFunctions.cpp 2017/06/22 10:45:38 3285 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Christian Schoenebeck + * Copyright (c) 2014-2017 Christian Schoenebeck * * http://www.linuxsampler.org * @@ -10,10 +10,12 @@ #include "CoreVMFunctions.h" #include +#include // for std::sort() #include #include #include "tree.h" #include "ScriptVM.h" +#include "../common/RTMath.h" namespace LinuxSampler { @@ -70,15 +72,17 @@ VMFnResult* CoreVMFunction_message::exec(VMFnArgs* args) { if (!args->argsCount()) return errorResult(); + uint64_t usecs = RTMath::unsafeMicroSeconds(RTMath::real_clock); + VMStringExpr* strExpr = dynamic_cast(args->arg(0)); if (strExpr) { - std::cout << "[ScriptVM] " << strExpr->evalStr() << "\n"; + printf("[ScriptVM %.3f] %s\n", usecs/1000000.f, strExpr->evalStr().c_str()); return successResult(); } VMIntExpr* intExpr = dynamic_cast(args->arg(0)); if (intExpr) { - std::cout << "[ScriptVM] " << intExpr->evalInt() << "\n"; + printf("[ScriptVM %.3f] %d\n", usecs/1000000.f, intExpr->evalInt()); return successResult(); } @@ -230,4 +234,256 @@ return successResult(l > r ? l : r); } +/////////////////////////////////////////////////////////////////////////// +// built-in script function: array_equal() + +VMFnResult* CoreVMFunction_array_equal::exec(VMFnArgs* args) { + VMIntArrayExpr* l = args->arg(0)->asIntArray(); + VMIntArrayExpr* r = args->arg(1)->asIntArray(); + if (l->arraySize() != r->arraySize()) { + wrnMsg("array_equal(): the two arrays differ in size"); + return successResult(0); // false + } + const int n = l->arraySize(); + for (int i = 0; i < n; ++i) + if (l->evalIntElement(i) != r->evalIntElement(i)) + return successResult(0); // false + return successResult(1); // true +} + +/////////////////////////////////////////////////////////////////////////// +// built-in script function: search() + +ExprType_t CoreVMFunction_search::argType(int iArg) const { + return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR; +} + +bool CoreVMFunction_search::acceptsArgType(int iArg, ExprType_t type) const { + if (iArg == 0) + return type == INT_ARR_EXPR; + else + return type == INT_EXPR; +} + +VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) { + VMIntArrayExpr* a = args->arg(0)->asIntArray(); + const int needle = args->arg(1)->asInt()->evalInt(); + const int n = a->arraySize(); + for (int i = 0; i < n; ++i) + if (a->evalIntElement(i) == needle) + return successResult(i); + return successResult(-1); // not found +} + +/////////////////////////////////////////////////////////////////////////// +// built-in script function: sort() + +ExprType_t CoreVMFunction_sort::argType(int iArg) const { + return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR; +} + +bool CoreVMFunction_sort::acceptsArgType(int iArg, ExprType_t type) const { + if (iArg == 0) + return type == INT_ARR_EXPR; + else + return type == INT_EXPR; +} + +struct ArrElemPOD { + VMIntArrayExpr* m_array; + int m_index; +}; + +static inline void swap(class ArrElemRef a, class ArrElemRef b); + +class ArrElemRef : protected ArrElemPOD { +public: + ArrElemRef() { + m_array = NULL; + m_index = 0; + } + ArrElemRef(VMIntArrayExpr* a, int index) { + m_array = a; + m_index = index; + } + inline ArrElemRef& operator=(const ArrElemRef& e) { + setValue(e.getValue()); + return *this; + } + inline ArrElemRef& operator=(int val) { + setValue(val); + return *this; + } + inline bool operator==(const ArrElemRef& e) const { + if (m_index == e.m_index) + return true; + return getValue() == e.getValue(); + } + inline bool operator==(int val) const { + return getValue() == val; + } + inline bool operator!=(const ArrElemRef& e) const { + return !(operator==(e)); + } + inline bool operator!=(int val) const { + return !(operator==(val)); + } + inline bool operator<(const ArrElemRef& e) const { + if (m_index == e.m_index) + return false; + return getValue() < e.getValue(); + } + inline bool operator<(int val) const { + return getValue() < val; + } + inline bool operator>(const ArrElemRef& e) const { + if (m_index == e.m_index) + return false; + return getValue() > e.getValue(); + } + inline bool operator>(int val) const { + return getValue() > val; + } + inline bool operator<=(const ArrElemRef& e) const { + if (m_index == e.m_index) + return true; + return getValue() <= e.getValue(); + } + inline bool operator<=(int val) const { + return getValue() <= val; + } + inline bool operator>=(const ArrElemRef& e) const { + if (m_index == e.m_index) + return true; + return getValue() >= e.getValue(); + } + inline bool operator>=(int val) const { + return getValue() >= val; + } + inline operator int() const { + return getValue(); + } +protected: + inline int getValue() const { + return m_array->evalIntElement(m_index); + } + inline void setValue(int value) { + m_array->assignIntElement(m_index, value); + } + + friend void swap(class ArrElemRef a, class ArrElemRef b); +}; + +class ArrElemPtr : protected ArrElemPOD { +public: + ArrElemPtr() { + m_array = NULL; + m_index = 0; + } + ArrElemPtr(VMIntArrayExpr* a, int index) { + m_array = a; + m_index = index; + } + inline ArrElemRef operator*() { + return *(ArrElemRef*)this; + } +}; + +static inline void swap(ArrElemRef a, ArrElemRef b) { + int valueA = a.getValue(); + int valueB = b.getValue(); + a.setValue(valueB); + b.setValue(valueA); +} + +class ArrExprIter : public ArrElemPOD { +public: + typedef std::random_access_iterator_tag iterator_category; + typedef int value_type; + typedef ssize_t difference_type; + typedef ArrElemPtr pointer; + typedef ArrElemRef reference; + + ArrExprIter(VMIntArrayExpr* a, int index) { + m_array = a; + m_index = index; + } + inline ArrElemRef operator*() { + return *(ArrElemRef*)this; + } + inline ArrExprIter& operator++() { // prefix increment + ++m_index; + return *this; + } + inline ArrExprIter& operator--() { // prefix decrement + --m_index; + return *this; + } + inline ArrExprIter operator++(int) { // postfix increment + ArrExprIter it = *this; + ++m_index; + return it; + } + inline ArrExprIter operator--(int) { // postfix decrement + ArrExprIter it = *this; + --m_index; + return it; + } + inline bool operator==(const ArrExprIter& other) const { + return m_index == other.m_index; + } + inline bool operator!=(const ArrExprIter& other) const { + return m_index != other.m_index; + } + inline bool operator<(const ArrExprIter& other) const { + return m_index < other.m_index; + } + inline bool operator>(const ArrExprIter& other) const { + return m_index > other.m_index; + } + inline bool operator<=(const ArrExprIter& other) const { + return m_index <= other.m_index; + } + inline bool operator>=(const ArrExprIter& other) const { + return m_index >= other.m_index; + } + inline difference_type operator+(const ArrExprIter& other) const { + return m_index + other.m_index; + } + inline difference_type operator-(const ArrExprIter& other) const { + return m_index - other.m_index; + } + inline ArrExprIter operator-(difference_type d) const { + return ArrExprIter(m_array, m_index - d); + } + inline ArrExprIter operator+(difference_type d) const { + return ArrExprIter(m_array, m_index + d); + } + inline ArrExprIter operator*(difference_type factor) const { + return ArrExprIter(m_array, m_index * factor); + } +}; + +struct DescArrExprSorter { + inline bool operator()(const int& a, const int& b) const { + return a > b; + } +}; + +VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) { + VMIntArrayExpr* a = args->arg(0)->asIntArray(); + bool bAscending = + (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt(); + int n = a->arraySize(); + ArrExprIter itBegin(a, 0); + ArrExprIter itEnd(a, n); + if (bAscending) { + std::sort(itBegin, itEnd); + } else { + DescArrExprSorter sorter; + std::sort(itBegin, itEnd, sorter); + } + return successResult(); +} + } // namespace LinuxSampler