diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/opcodes.cpp | 976 | 
1 files changed, 976 insertions, 0 deletions
| diff --git a/src/opcodes.cpp b/src/opcodes.cpp new file mode 100644 index 0000000..6991051 --- /dev/null +++ b/src/opcodes.cpp @@ -0,0 +1,976 @@ +/* +    opcodes.cpp +    Copyright (C) 2022 Richard Knight + + +    This program is free software; you can redistribute it and/or +    modify it under the terms of the GNU Lesser General Public +    License as published by the Free Software Foundation; either +    version 3 of the License, or (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +    Lesser General Public License for more details. + +    You should have received a copy of the GNU Lesser General Public License +    along with this program; if not, write to the Free Software Foundation, +    Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. +  + */ +#include <jsoncons/json.hpp> +#include <jsoncons_ext/jsonpath/jsonpath.hpp> +#include <jsoncons_ext/jsonpointer/jsonpointer.hpp> +#include <iostream> +#include <fstream> +#include <exception> +#include <vector> +#include <plugin.h> +#include "handling.h" + +#define ARGT static constexpr char const + +struct JSONSession { +    jsoncons::json data; +}; + +const char* badHandle = "cannot obtain data from handle"; +const char* handleName = "jsonsession"; + + +/* +    Initialise an array and return STRINDAT pointer in case it is required + */ +STRINGDAT* arrayInit(csnd::Csound* csound, ARRAYDAT* array, int rows, int cols) { +    int totalResults = rows * cols; +    size_t totalAllocated; +     +    //if (array->data == NULL) { +        array->sizes = (int32_t*) csound->calloc(sizeof(int32_t) * 2); +        array->sizes[0] = rows; +        if (cols != 1) { +            array->sizes[1] = cols; +        } +        array->dimensions = cols; +        CS_VARIABLE *var = array->arrayType->createVariable(csound->get_csound(), NULL); +        array->arrayMemberSize = var->memBlockSize; +        totalAllocated = array->arrayMemberSize * totalResults; +        array->data = (MYFLT*) csound->calloc(totalAllocated); +    // } else +    if ((totalAllocated = array->arrayMemberSize * totalResults) > array->allocated) { +        array->data = (MYFLT*) csound->realloc(array->data, totalAllocated); +        memset((char*)(array->data)+array->allocated, '\0', totalAllocated - array->allocated); +        array->allocated = totalAllocated; +    } +     +    // convenience return to be used if it is a string array +    return (STRINGDAT*) array->data; +} + + +/* + Insert a string to an array + */ +void insertArrayStringItem(csnd::Csound* csound, STRINGDAT* strings, int index, char* item) { +    strings[index].size = strlen(item) + 1; +    if (strings[index].data != NULL) { +        csound->free(strings[index].data); +    } +    strings[index].data = csound->strdup(item); +} + + +/* + Convert JSON array to Csound array either as string or numeric + */ +void jsonArrayToCSArray(csnd::Csound* csound, jsoncons::json* jdatap, ARRAYDAT* array, bool asString) { +    jsoncons::json jdata = *jdatap; +    std::vector<std::string> vals = jdata.as<std::vector<std::string>>(); +     +    STRINGDAT* strings = arrayInit(csound, array, vals.size(), 1); +     +    char* value; +    for (std::size_t index = 0; index < vals.size(); index++) { +        value = (char*) vals[index].c_str(); +        if (asString) { +            insertArrayStringItem(csound, strings, index, value); +        } else { +            array->data[index] = (MYFLT) atof(value); +        }         +    } +} + + +/* + Get the JSON type of a session object + */ +int getJsonType(JSONSession* jsonSession) { +    jsoncons::json j = jsonSession->data; +    int outtype = -1; +    if (j.is_null()) { +        outtype = 0; +    } else if (j.is_string()) { +        outtype = 1; +    } else if (j.is_number()) { +        outtype = 2; +    } else if (j.is_bool()) { +        outtype = 3; +    } else if (j.is_array()) { +        outtype = 4; +    } else if (j.is_object()) { +        outtype = 5; +    } +    return outtype; +} + +// cs AppendOpcode mallocs struct so virtual functions cannot be used.  +// Macro workaround to fake struct derivation type model, just chuck it all in a macro... + +#define _PLUGINSESSIONBASE(idInArgs)\ +    JSONSession* jsonSession;\ +    void getSession() {\ +        if (!(jsonSession = getHandle<JSONSession>(csound, idInArgs[0], handleName))) {\ +			throw std::runtime_error(badHandle);\ +		}\ +    }\ +	void getSession(MYFLT handle, JSONSession** returnSession) {\ +		if (!(*returnSession = getHandle<JSONSession>(csound, handle, handleName))) {\ +			throw std::runtime_error(badHandle);\ +		}\ +	} + +#define _PLUGINITBASE(votypes, vitypes, doGetSession) \ +	ARGT* otypes = votypes;\ +	ARGT* itypes = vitypes;\ +	int init() {\ +		try {\ +			if (doGetSession) getSession();\ +			irun();\ +		} catch (const std::exception &ex) {\ +			return csound->init_error(ex.what());\ +		}\ +		return OK;\ +	} + +// extension of above for k-rate opcodes +#define _PLUGINITBASEK(votypes, vitypes, doGetSession) \ +    _PLUGINITBASE(votypes, vitypes, doGetSession)\ +    void irun() {}\ +    int kperf() {\ +        try {\ +            krun();\ +        } catch (const std::exception &ex) {\ +            return csound->perf_error(ex.what(), this);\ +        }\ +        return OK;\ +    } + +#define PLUGINSESSION \ +    _PLUGINSESSIONBASE(inargs) + +#define INPLUGSESSION \ +    _PLUGINSESSIONBASE(args) + +#define PLUGINIT(votypes, vitypes, doGetSession) \ +	_PLUGINITBASE(votypes, vitypes, doGetSession) + +#define INPLUGINIT(vitypes) \ +	_PLUGINITBASE("", vitypes, true) + +#define PLUGINITK(votypes, vitypes, doGetSession) \ +	_PLUGINITBASEK(votypes, vitypes, doGetSession) + +#define INPLUGINITK(vitypes) \ +	_PLUGINITBASEK("", vitypes, true) +             +#define INPLUGCHILD(vitypes) \ +    INPLUGINIT(vitypes)\ +    void irun() { run(); } + +#define INPLUGCHILDK(vitypes) \ +    INPLUGINITK(vitypes)\ +    void krun() { run(); } + +#define PLUGINCHILD(votypes, vitypes, doGetSession) \ +    PLUGINIT(votypes, vitypes, doGetSession)\ +    void irun() { run(); } + +#define PLUGINCHILDK(votypes, vitypes, doGetSession) \ +    PLUGINITK(votypes, vitypes, doGetSession)\ +    void krun() { run(); } + + + +template <std::size_t N>  +struct inplug : csnd::InPlug<N> { +    using csnd::InPlug<N>::args; +    using csnd::InPlug<N>::csound; +    INPLUGSESSION +}; + +template <std::size_t N, std::size_t M>  +struct plugin : csnd::Plugin<N, M> { +    using csnd::Plugin<N, M>::inargs; +    using csnd::Plugin<N, M>::outargs; +    using csnd::Plugin<N, M>::csound; +    PLUGINSESSION +}; + + +/* + Parse JSON object from a provided string + */ +struct jsonloads : plugin<1, 1> { +	PLUGINIT("i", "S", false) +	void irun() { +        outargs[0] = createHandle<JSONSession>(csound, &jsonSession, handleName); +        jsonSession->data = jsoncons::json::parse(std::string(inargs.str_data(0).data)); +	} +}; + + +/* + Initialise an empty JSON object + */ +struct jsoninit : plugin<1, 0> { +	PLUGINIT("i", "", false) +	void irun() { +        outargs[0] = createHandle<JSONSession>(csound, &jsonSession, handleName); +        jsonSession->data = jsoncons::json::parse("{}"); +	} +}; + + +/* + Merge two JSON objects + */ +struct jsonmerge : inplug<3> { +	INPLUGINIT("iio") +	int irun() {         +        JSONSession* jsonSession2; +        getSession(args[1], &jsonSession2); +        if (args[2] == 1) {  +            jsonSession->data.merge_or_update(jsonSession2->data); +        } else { +            jsonSession->data.merge(jsonSession2->data); +        } + +	} +}; + + +/* + Insert a JSON object to another JSON object with specified key + */ +struct jsoninsert : inplug<3> { +	INPLUGINIT("iSi") +	void irun() { +        JSONSession* jsonSession2; +        getSession(args[2], &jsonSession2); +        jsonSession->data.insert_or_assign( +            std::string(args.str_data(1).data), +            jsonSession2->data +        ); +	} +}; + + +/* +Insert an array of JSON objects to another JSON object with specified key         +*/       +struct jsoninsertArray : inplug<3> { +	INPLUGINIT("iSi[]") +	void irun() {       +        JSONSession* jsonSession2; +        ARRAYDAT* values = (ARRAYDAT*) args(2); +        std::vector<jsoncons::json> valuesVector; +         +        for (int i = 0; i < values->sizes[0]; i++) { +            getSession(values->data[i], &jsonSession2); +            valuesVector.push_back(jsonSession2->data); +        } +                +        jsonSession->data.insert_or_assign( +            std::string(args.str_data(1).data), +            valuesVector +        ); +	} +}; + + +/* + Insert a string value to a JSON object with specified key + */ +struct jsoninsertvalStringBase : inplug<3> { +    void run() { +        jsonSession->data.insert_or_assign( +            std::string(args.str_data(1).data), +            std::string(args.str_data(2).data) +        ); +	} +}; +struct jsoninsertvalString : jsoninsertvalStringBase { +	INPLUGCHILD("iSS") +}; +struct jsoninsertvalStringK : jsoninsertvalStringBase { +	INPLUGCHILDK("iSS") +}; + + +/* + Insert a numeric value to a JSON object with specified key + */ +struct jsoninsertvalNumericBase : inplug<3> { +    void run() { +        jsonSession->data.insert_or_assign( +            std::string(args.str_data(1).data), +            args[2] +        );   +    } +}; +struct jsoninsertvalNumeric : jsoninsertvalNumericBase {  +    INPLUGCHILD("iSi")  +}; +struct jsoninsertvalNumericK : jsoninsertvalNumericBase {  +    INPLUGCHILDK("iSk")  +}; + + + +/* + Insert a numeric array to a JSON object with specified key + */ +struct jsoninsertvalNumericArrayBase : inplug<3> { +    void run() { +        ARRAYDAT* values = (ARRAYDAT*) args(2); +        std::vector<MYFLT> valuesVector(values->data, values->data + values->sizes[0]); +        jsonSession->data.insert_or_assign( +            std::string(args.str_data(1).data), +            valuesVector +        ); +    } +}; +struct jsoninsertvalNumericArray : jsoninsertvalNumericArrayBase {  +    INPLUGCHILD("iSi[]")  +}; +struct jsoninsertvalNumericArrayK : jsoninsertvalNumericArrayBase {  +    INPLUGCHILDK("iSk[]")  +}; + + + +/* + Insert a string array to a JSON object with specified key + */ +struct jsoninsertvalStringArrayBase : inplug<3> {	 +	void run() {  +        ARRAYDAT* values = (ARRAYDAT*) args(2); +        STRINGDAT* strings = (STRINGDAT*) values->data; +        std::vector<std::string> valuesVector; +        for (int i = 0; i < values->sizes[0]; i++) { +            valuesVector.push_back(std::string(strings[i].data)); +        } +        jsonSession->data.insert_or_assign( +            std::string(args.str_data(1).data), +            valuesVector +        ); +	} +}; +struct jsoninsertvalStringArray : jsoninsertvalStringArrayBase {  +    INPLUGCHILD("iSS[]")  +}; +struct jsoninsertvalStringArrayK : jsoninsertvalStringArrayBase {  +    INPLUGCHILDK("iSS[]")  +}; + + +/* + Insert string key, string value pairs to a JSON object with specified key + */ +struct jsoninsertvalStringStringArrayBase : inplug<3> { +    void run() { +        ARRAYDAT* rawKeys = (ARRAYDAT*) args(1); +        STRINGDAT* keys = (STRINGDAT*) rawKeys->data; +        ARRAYDAT* rawValues = (ARRAYDAT*) args(2); +        STRINGDAT* values = (STRINGDAT*) rawValues->data; +        if (rawKeys->sizes[0] != rawValues->sizes[0]) { +            throw std::runtime_error("key and value arrays are not the same size"); +        } +        for (int i = 0; i < rawKeys->sizes[0]; i++) { +            jsonSession->data.insert_or_assign( +                std::string(keys[i].data), +                std::string(values[i].data) +            ); +        } +    } +}; +struct jsoninsertvalStringStringArray : jsoninsertvalStringStringArrayBase { +    INPLUGCHILD("iS[]S[]") +}; +struct jsoninsertvalStringStringArrayK : jsoninsertvalStringStringArrayBase { +    INPLUGCHILDK("iS[]S[]") +}; +  + +/* + Insert string key, numeric value pairs to a JSON object with specified key + */ +struct jsoninsertvalStringNumericArrayBase : inplug<3> { +    void run() { +        ARRAYDAT* rawKeys = (ARRAYDAT*) args(1); +        STRINGDAT* keys = (STRINGDAT*) rawKeys->data; +        ARRAYDAT* rawValues = (ARRAYDAT*) args(2); +        if (rawKeys->sizes[0] != rawValues->sizes[0]) { +            throw std::runtime_error("key and value arrays are not the same size"); +        } +        for (int i = 0; i < rawKeys->sizes[0]; i++) { +            jsonSession->data.insert_or_assign( +                std::string(keys[i].data), +                rawValues->data[i] // not like doubles? +            ); +        } +    } +}; +struct jsoninsertvalStringNumericArray : jsoninsertvalStringNumericArrayBase { +    INPLUGCHILD("iS[]i[]") +}; +struct jsoninsertvalStringNumericArrayK : jsoninsertvalStringNumericArrayBase { +    INPLUGCHILDK("iS[]k[]") +}; + + +/* + Get JSON type as number + */ +struct jsontype : plugin<1, 1> { +	PLUGINIT("i", "i", true) +    void irun() { +        outargs[0] = (MYFLT) getJsonType(jsonSession); +    } +}; + +/* + Get JSON type as string + */ +struct jsontypeString : plugin<1, 1> { +	PLUGINIT("S", "i", true) +    void irun() { +        STRINGDAT &sdoutput = outargs.str_data(0); +        int type = getJsonType(jsonSession); +        std::string output; +        switch (type) { +            case -1: +                output.assign("unknown"); +                break; +            case 0: +                output.assign("null"); +                break; +            case 1: +                output.assign("string"); +                break; +            case 2: +                output.assign("number"); +                break; +            case 3: +                output.assign("boolean"); +                break; +            case 4: +                output.assign("array"); +                break; +            case 5: +                output.assign("object"); +                break; +        } +        sdoutput.size = output.length(); +        sdoutput.data = csound->strdup((char*) output.c_str()); +    } +}; + +/* + Get the key names from an object + */ +struct jsonkeysBase : plugin<1, 1> { +    void run() { +        std::map<std::string, jsoncons::json> map =  +                jsonSession->data.as<std::map<std::string, jsoncons::json>>(); +        ARRAYDAT* array = (ARRAYDAT*) outargs(0); +        STRINGDAT* strings = arrayInit(csound, array, map.size(), 1); +         +        char* value; +        int index = 0; +        for (auto const& x : map) { +            value = (char*) x.first.c_str(); +            insertArrayStringItem(csound, strings, index, value); +            index ++; +        } +    } +}; +struct jsonkeys : jsonkeysBase { +    PLUGINCHILD("S[]", "i", true) +}; +struct jsonkeysK : jsonkeysBase { +    PLUGINCHILDK("S[]", "i", true) +}; + + +/*  + Get the size of a JSON object + */ +struct jsonsizeBase : plugin<1, 1> {     +    void run() { +        outargs[0] = (MYFLT) jsonSession->data.size(); +    } +}; +struct jsonsize : jsonsizeBase { +    PLUGINCHILD("i", "i", true) +}; +struct jsonsizeK : jsonsizeBase { +    PLUGINCHILDK("k", "i", true) +}; + + +/* + Get object from an object by key name + */ +struct jsongetvalString : plugin<1, 2> { +    PLUGINIT("i", "iS", true) +    void irun() { +        STRINGDAT &input = inargs.str_data(1); +        jsoncons::json selected = jsonSession->data[std::string(input.data)]; +        JSONSession* jsonSessionOutput; +        outargs[0] = createHandle<JSONSession>(csound, &jsonSessionOutput, handleName); +        jsonSessionOutput->data = selected; +    } +}; + + +/* + Get object from an array by index + */ +struct jsongetvalNumeric : plugin<1, 2> { +    PLUGINIT("i", "ii", true) +    void irun() { +        jsoncons::json selected = jsonSession->data[(int) inargs[1]]; +        JSONSession* jsonSessionOutput; +        outargs[0] = createHandle<JSONSession>(csound, &jsonSessionOutput, handleName); +        jsonSessionOutput->data = selected; +    } +}; + + +/* + Query by JSONPath + */ +struct jsonpath : plugin<1, 2> { +	PLUGINIT("i", "iS", true) +    void irun() { +        jsoncons::json queried = jsoncons::jsonpath::json_query( +            jsonSession->data, std::string(inargs.str_data(1).data) +        ); +        JSONSession* jsonSessionOutput; +        outargs[0] = createHandle<JSONSession>(csound, &jsonSessionOutput, handleName); +        jsonSessionOutput->data = queried; +    } +}; + + +/* + Replace string value by JSONPath + */ +struct jsonpathrplvalStringBase : inplug<3> { +	void run() { +        jsoncons::jsonpath::json_replace( +            jsonSession->data,  +            std::string(args.str_data(1).data),  +            std::string(args.str_data(2).data) +        ); +	} +}; +struct jsonpathrplvalString : jsonpathrplvalStringBase { +	INPLUGCHILD("iSS") +}; +struct jsonpathrplvalStringK : jsonpathrplvalStringBase { +	INPLUGCHILDK("iSS") +}; + + +/* + Replace numeric value by JSONPath + */ +struct jsonpathrplvalNumericBase : inplug<3> {	 +	void run() { +        jsoncons::jsonpath::json_replace( +            jsonSession->data,  +            std::string(args.str_data(1).data),  +            (float) args[2] // doesn't like double ?? +        ); +	} +}; +struct jsonpathrplvalNumeric : jsonpathrplvalNumericBase { +	INPLUGCHILD("iSi") +}; +struct jsonpathrplvalNumericK : jsonpathrplvalNumericBase { +	INPLUGCHILDK("iSi") +}; + + +/* + Replace element with object by JSONPath + */ +struct jsonpathrpl : inplug<3> { +	INPLUGINIT("iSi") +	void irun() { +        JSONSession* jsonSession2; +        getSession(args[2], &jsonSession2); +        jsoncons::jsonpath::json_replace( +            jsonSession->data,  +            std::string(args.str_data(1).data),  +            std::string("DAMN") //jsonSession2->data +        ); +	} +}; + + +/* + Query by JSON Pointer + */ +struct jsonptr : plugin<1, 2> { +	PLUGINIT("i", "iS", true) +    void irun() { +        jsoncons::json queried = jsoncons::jsonpointer::get( +            jsonSession->data, std::string(inargs.str_data(1).data) +        ); +        JSONSession* jsonSessionOutput; +        outargs[0] = createHandle<JSONSession>(csound, &jsonSessionOutput, handleName); +        jsonSessionOutput->data = queried; +    } +}; + +/* + Check for existence by JSON Pointer + */ +struct jsonptrhasBase : plugin<1, 2> { +    void run() { +        outargs[0] = (int) jsoncons::jsonpointer::contains( +            jsonSession->data, std::string(inargs.str_data(1).data) +        ); +    } +}; +struct jsonptrhas : jsonptrhasBase { +	PLUGINCHILD("i", "iS", true) +}; +struct jsonptrhasK : jsonptrhasBase { +	PLUGINCHILDK("k", "iS", true) +}; + + +/* + Add string value by JSON Pointer + */ +struct jsonptraddvalStringBase : inplug<3> { +	void run() { +        jsoncons::jsonpointer::add( +            jsonSession->data,  +            std::string(args.str_data(1).data),  +            std::string(args.str_data(2).data), +            true // create if not exists +        ); +	} +}; +struct jsonptraddvalString : jsonptraddvalStringBase { +    INPLUGCHILD("iSS") +}; +struct jsonptraddvalStringK : jsonptraddvalStringBase { +    INPLUGCHILDK("iSS") +}; + + +/* + Add numeric value by JSON Pointer + */ +struct jsonptraddvalNumericBase : inplug<3> { +	void run() { +        jsoncons::jsonpointer::add( +            jsonSession->data,  +            std::string(args.str_data(1).data),  +            args[2], +            true // create if not exists +        ); +	} +}; +struct jsonptraddvalNumeric : jsonptraddvalNumericBase { +	INPLUGCHILD("iSi") +}; +struct jsonptraddvalNumericK : jsonptraddvalNumericBase { +	INPLUGCHILDK("iSk") +}; + + +/* + Add object by JSON Pointer + */ +struct jsonptradd : inplug<3> { +	INPLUGINIT("iSi") +	void irun() { +        JSONSession* jsonSession2; +        getSession(args[1], &jsonSession2); +         +        jsoncons::jsonpointer::add( +            jsonSession->data,  +            std::string(args.str_data(1).data),  +            jsonSession2->data, +            true // create if not exists +        ); +	} +}; + + +/* + Remove by JSON Pointer + */ +struct jsonptrrmBase : inplug<2> { +	void run() { +        char* query = args.str_data(1).data; +        jsoncons::jsonpointer::remove(jsonSession->data, std::string(query)); +	} +}; +struct jsonptrrm : jsonptrrmBase { +	INPLUGCHILD("iS") +}; +struct jsonptrrmK : jsonptrrmBase { +	INPLUGCHILDK("iS") +}; + + +/* + Replace string value by JSON Pointer + */ +struct jsonptrrplvalStringBase : inplug<3> { +	void run() { +        jsoncons::jsonpointer::replace( +            jsonSession->data,  +            std::string(args.str_data(1).data),  +            std::string(args.str_data(2).data),  +            true // create if missing +        ); +	} +}; +struct jsonptrrplvalString : jsonptrrplvalStringBase { +	INPLUGCHILD("iSS") +}; +struct jsonptrrplvalStringK : jsonptrrplvalStringBase { +	INPLUGCHILDK("iSS") +}; + + +/* + Replace numeric value by JSON Pointer + */ +struct jsonptrrplvalNumericBase : inplug<3> { +	void run() { +        jsoncons::jsonpointer::replace( +            jsonSession->data,  +            std::string(args.str_data(1).data),  +            args[2], +            true // create if missing +        ); +	} +}; +struct jsonptrrplvalNumeric : jsonptrrplvalNumericBase { +	INPLUGCHILD("iSi") +}; +struct jsonptrrplvalNumericK : jsonptrrplvalNumericBase { +	INPLUGCHILDK("iSk") +}; + + +/* + Replace object by JSON Pointer + */ +struct jsonptrrpl : csnd::InPlug<3> { +    INPLUGSESSION +	INPLUGINIT("iSi") +	void irun() { +        JSONSession* jsonSession2; +        getSession(args[2], &jsonSession2); +         +        jsoncons::jsonpointer::replace( +            jsonSession->data,  +            std::string(args.str_data(1).data),  +            jsonSession2->data, +            true // create if missing +        ); +	} +}; + + +/* + Get numeric array from object + */ +struct jsonarrvalNumericBase : plugin<1, 1> { +    void run() { +        jsonArrayToCSArray(csound, &(jsonSession->data), (ARRAYDAT*) outargs(0), false);          +    } +}; +struct jsonarrvalNumeric : jsonarrvalNumericBase { +	PLUGINCHILD("i[]", "i", true) +}; +struct jsonarrvalNumericK : jsonarrvalNumericBase { +	PLUGINCHILDK("k[]", "i", true) +}; + + +/* + Get string array from object + */ +struct jsonarrvalStringBase : plugin<1, 1> { +    void run() { +        jsonArrayToCSArray(csound, &(jsonSession->data), (ARRAYDAT*) outargs(0), true);          +    } +}; +struct jsonarrvalString : jsonarrvalStringBase { +	PLUGINCHILD("S[]", "i", true) +}; +struct jsonarrvalStringK : jsonarrvalStringBase { +	PLUGINCHILDK("S[]", "i", true) +}; + + +/* + Get array of object handles from object + */ +struct jsonarr : plugin<1, 1> { +    PLUGINIT("i[]", "i", true) +    void irun() { +        JSONSession* jsonSession2; +        std::vector<jsoncons::json> vals =  +                jsonSession->data.as<std::vector<jsoncons::json>>(); +        ARRAYDAT* array = (ARRAYDAT*) outargs(0); +        arrayInit(csound, array, vals.size(), 1); +        MYFLT handle; +        for (std::size_t index = 0; index < vals.size(); index++) { +            handle = createHandle<JSONSession>(csound, &jsonSession2, handleName); +            jsonSession2->data = vals[index]; +            array->data[index] = handle; +        } +    } +}; + + +/* + Dump to string + */ +struct jsondumpsBase : plugin<1, 2> { +	void run() { +        STRINGDAT &output = outargs.str_data(0); +        std::ostringstream stream; +        if (inargs[1] == FL(1)) { +            stream << jsoncons::pretty_print(jsonSession->data); +        } else { +            stream << jsonSession->data; +        } +        char* text = csound->strdup((char*) stream.str().c_str()); +        output.size = strlen(text); +        output.data = text; +	} +}; +struct jsondumps : jsondumpsBase { +	PLUGINCHILD("S", "ip", true) +}; +struct jsondumpsK : jsondumpsBase { +	PLUGINCHILDK("S", "ip", true) +}; + + +struct jsonload : csnd::Plugin<1, 1> { +    PLUGINSESSION +	PLUGINIT("i", "S", false) +	void irun() { +        std::ifstream fileStream(inargs.str_data(0).data); +        jsoncons::json parsed = jsoncons::json::parse(fileStream); +        outargs[0] = createHandle<JSONSession>(csound, &jsonSession, handleName); +        jsonSession->data = parsed; +	} +}; + + +struct jsondump : csnd::InPlug<3> { +    INPLUGSESSION +	INPLUGINIT("iSp") +	void irun() { +        std::ofstream fileStream; +        fileStream.open(args.str_data(1).data, std::ios::in | std::ios::trunc); +        if (!fileStream.is_open()) { +            throw std::runtime_error("could not open file for writing"); +        } +        if (args[2] == FL(1)) { +            fileStream << jsoncons::pretty_print(jsonSession->data); +        } else { +            fileStream << jsonSession->data; +        } +        fileStream.close(); +	} +}; + +#include <modload.h> +void csnd::on_load(csnd::Csound *csound) { +    csnd::plugin<jsoninit>(csound, "jsoninit", csnd::thread::i); +    csnd::plugin<jsonloads>(csound, "jsonloads", csnd::thread::i); +    csnd::plugin<jsondumps>(csound, "jsondumps", csnd::thread::i); +    csnd::plugin<jsondumpsK>(csound, "jsondumpsk", csnd::thread::ik); +    csnd::plugin<jsonload>(csound, "jsonload", csnd::thread::i); +    csnd::plugin<jsondump>(csound, "jsondump", csnd::thread::i); +    csnd::plugin<jsonmerge>(csound, "jsonmerge", csnd::thread::i); +    csnd::plugin<jsontype>(csound, "jsontype", csnd::thread::i); +    csnd::plugin<jsontypeString>(csound, "jsontype.S", csnd::thread::i); +    csnd::plugin<jsonkeys>(csound, "jsonkeys", csnd::thread::i); +    csnd::plugin<jsonkeysK>(csound, "jsonkeysk", csnd::thread::ik); +    csnd::plugin<jsongetvalString>(csound, "jsongetval.S", csnd::thread::i); +    csnd::plugin<jsongetvalNumeric>(csound, "jsongetval.i", csnd::thread::i); +    csnd::plugin<jsonsize>(csound, "jsonsize", csnd::thread::i); +    csnd::plugin<jsonsizeK>(csound, "jsonsizek", csnd::thread::ik); +   +    csnd::plugin<jsoninsert>(csound, "jsoninsert", csnd::thread::i); +    csnd::plugin<jsoninsertArray>(csound, "jsoninsert.a", csnd::thread::i); +    csnd::plugin<jsoninsertvalString>(csound, "jsoninsertval.S", csnd::thread::i); +    csnd::plugin<jsoninsertvalStringK>(csound, "jsoninsertvalk.S", csnd::thread::ik); +    csnd::plugin<jsoninsertvalNumeric>(csound, "jsoninsertval.i", csnd::thread::i);     +    csnd::plugin<jsoninsertvalNumericK>(csound, "jsoninsertvalk", csnd::thread::ik);     +    csnd::plugin<jsoninsertvalStringArray>(csound, "jsoninsertval.Sa", csnd::thread::i); +    csnd::plugin<jsoninsertvalStringArrayK>(csound, "jsoninsertvalk.Sa", csnd::thread::ik); +    csnd::plugin<jsoninsertvalNumericArray>(csound, "jsoninsertval.ia", csnd::thread::i); +    csnd::plugin<jsoninsertvalNumericArrayK>(csound, "jsoninsertvalk.a", csnd::thread::ik); +    csnd::plugin<jsoninsertvalStringStringArray>(csound, "jsoninsertval.SaSa", csnd::thread::i); +    csnd::plugin<jsoninsertvalStringStringArrayK>(csound, "jsoninsertvalk.SaSa", csnd::thread::ik); +    csnd::plugin<jsoninsertvalStringNumericArray>(csound, "jsoninsertval.Saia", csnd::thread::i); +    csnd::plugin<jsoninsertvalStringNumericArrayK>(csound, "jsoninsertvalk.Saka", csnd::thread::ik); +     +    csnd::plugin<jsonpath>(csound, "jsonpath", csnd::thread::i); +    csnd::plugin<jsonpathrplvalString>(csound, "jsonpathrplval.S", csnd::thread::i); +    csnd::plugin<jsonpathrplvalStringK>(csound, "jsonpathrplvalk.S", csnd::thread::ik); +    csnd::plugin<jsonpathrplvalNumeric>(csound, "jsonpathrplval.i", csnd::thread::i); +    csnd::plugin<jsonpathrplvalNumericK>(csound, "jsonpathrplvalk.i", csnd::thread::ik); +    csnd::plugin<jsonpathrpl>(csound, "jsonpathrpl", csnd::thread::i); +     +    csnd::plugin<jsonptr>(csound, "jsonptr", csnd::thread::i); +    csnd::plugin<jsonptrhas>(csound, "jsonptrhas", csnd::thread::i); +    csnd::plugin<jsonptrhasK>(csound, "jsonptrhask", csnd::thread::ik); +    csnd::plugin<jsonptraddvalString>(csound, "jsonptraddval.S", csnd::thread::i); +    csnd::plugin<jsonptraddvalStringK>(csound, "jsonptraddvalk.S", csnd::thread::ik); +    csnd::plugin<jsonptraddvalNumeric>(csound, "jsonptraddval.i", csnd::thread::i); +    csnd::plugin<jsonptraddvalNumericK>(csound, "jsonptraddvalk.i", csnd::thread::ik); +    csnd::plugin<jsonptradd>(csound, "jsonptradd", csnd::thread::i); +    csnd::plugin<jsonptrrm>(csound, "jsonptrrm", csnd::thread::i); +    csnd::plugin<jsonptrrmK>(csound, "jsonptrrmk", csnd::thread::ik); +    csnd::plugin<jsonptrrplvalString>(csound, "jsonptrrplval.S", csnd::thread::i); +    csnd::plugin<jsonptrrplvalStringK>(csound, "jsonptrrplvalk.S", csnd::thread::ik); +    csnd::plugin<jsonptrrplvalNumeric>(csound, "jsonptrrplval.i", csnd::thread::i); +    csnd::plugin<jsonptrrplvalNumericK>(csound, "jsonptrrplvalk.i", csnd::thread::ik); +    csnd::plugin<jsonptrrpl>(csound, "jsonptrrpl", csnd::thread::i); +     +    csnd::plugin<jsonarrvalString>(csound, "jsonarrval.S", csnd::thread::i); +    csnd::plugin<jsonarrvalStringK>(csound, "jsonarrvalk.S", csnd::thread::ik); +    csnd::plugin<jsonarrvalNumeric>(csound, "jsonarrval.i", csnd::thread::i); +    csnd::plugin<jsonarrvalNumericK>(csound, "jsonarrval.k", csnd::thread::ik); +    csnd::plugin<jsonarr>(csound, "jsonarr", csnd::thread::i); +} |