aboutsummaryrefslogtreecommitdiff
path: root/site/udo/json.udo
diff options
context:
space:
mode:
authorRichard <q@1bpm.net>2025-04-13 18:48:02 +0100
committerRichard <q@1bpm.net>2025-04-13 18:48:02 +0100
commit9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 (patch)
tree291bd79ce340e67affa755a8a6b4f6a83cce93ea /site/udo/json.udo
downloadapps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.gz
apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.bz2
apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.zip
initial
Diffstat (limited to 'site/udo/json.udo')
-rwxr-xr-xsite/udo/json.udo562
1 files changed, 562 insertions, 0 deletions
diff --git a/site/udo/json.udo b/site/udo/json.udo
new file mode 100755
index 0000000..b0bdcd1
--- /dev/null
+++ b/site/udo/json.udo
@@ -0,0 +1,562 @@
+#ifndef UDO_JSON
+#define UDO_JSON ##
+/*
+ JSON formatting and parsing
+
+ This file is part of the SONICS UDO collection by Richard Knight 2022
+ License: GPL-2.0-or-later
+ http://1bpm.net
+
+*/
+
+#include "/string_tools.udo"
+#include "/array_tools.udo"
+
+
+/*
+ Create a new empty JSON string
+
+ Sjson json_init
+
+ Sout empty JSON object/string
+*/
+opcode json_init, S, 0
+ xout "{}"
+endop
+
+
+/*
+ Append raw string to JSON string
+
+ Sout json_append Sjson, StoAppend
+
+ Sout string with appendage
+ Sjson input string to append to
+ StoAppend string to append
+*/
+opcode json_append, S, SS
+ Sjson, StoAppend xin
+ ilen strlen Sjson
+
+ Sjson = (ilen < 2) ? "{" : strsub(Sjson, 0, ilen-1)
+ Sout = sprintf("%s%s%s}", Sjson, (strlen(Sjson) == 1) ? "" : ",", StoAppend)
+
+ xout Sout
+endop
+
+
+/*
+ Append JSON object string to JSON object string with key
+
+ Sout json_appendobject Sjson, Skey, Svalue
+
+ Sout string with appendage
+ Sjson input string to append to
+ Skey key for appending
+ Svalue value for appending
+*/
+opcode json_appendobject, S, SSS
+ Sjson, Skey, Svalue xin
+ Sout = json_append(Sjson, sprintf("\"%s\":%s", Skey, Svalue))
+ xout Sout
+endop
+
+
+/*
+ Append string to JSON object string with key
+
+ Sout json_appendstring Sjson, Skey, Svalue
+
+ Sout string with quoted appendage
+ Sjson input string to append to
+ Skey key for appending
+ Svalue value for appending
+*/
+opcode json_appendstring, S, SSS
+ Sjson, Skey, Svalue xin
+ Sout = json_append(Sjson, sprintf("\"%s\":\"%s\"", Skey, Svalue))
+ xout Sout
+endop
+
+
+/*
+ Append numeric value to JSON object string with key
+
+ Sout json_appendvalue Sjson, Skey, ivalue
+
+ Sout string with appendage
+ Sjson input string to append to
+ Skey key for appending
+ ivalue value for appending
+*/
+opcode json_appendvalue, S, SSi
+ Sjson, Skey, ivalue xin
+ Sformat = (frac(ivalue) == 0) ? "\"%s\":%d" : "\"%s\":%f"
+ Sout = json_append(Sjson, sprintf(Sformat, Skey, ivalue))
+ xout Sout
+endop
+
+
+/*
+ Append numeric array to JSON object string with key
+
+ Sout json_appendarray Sjson, Skey, iarray[]
+
+ Sout string with appendage
+ Sjson input string to append to
+ Skey key for appending
+ iarray[] array for appending
+*/
+opcode json_appendarray, S, SSi[]o
+ Sjson, Skey, iarray[] xin
+ Sformatted = ""
+ ilen = lenarray(iarray)
+ index = 0
+ while (index < ilen) do
+ ivalue = iarray[index]
+ Sformat = (frac(ivalue) == 0) ? "%d" : "%f"
+ Sformatted strcat Sformatted, sprintf(Sformat, ivalue)
+ if (index != ilen - 1) then
+ Sformatted strcat Sformatted, ","
+ endif
+ index += 1
+ od
+ Sout = json_appendobject(Sjson, Skey, sprintf("[%s]", Sformatted))
+ xout Sout
+endop
+
+
+
+/*
+ Append string array to JSON object string with key
+
+ Sout json_appendarray Sjson, Skey, Sarray[]
+
+ Sout string with appendage
+ Sjson input string to append to
+ Skey key for appending
+ Sarray[] array for appending
+ iomitempty leave out empty strings
+*/
+opcode json_appendarray, S, SSS[]o
+ Sjson, Skey, Sarray[], iomitempty xin
+ Sformatted = ""
+ ilen = lenarray(Sarray)
+ index = 0
+ while (index < ilen) do
+ isempty = (strcmp(Sarray[index], "") == 0) ? 1 : 0
+ if ((iomitempty == 0 && isempty == 1) || isempty == 0) then
+ Sformatted strcat Sformatted, sprintf("\"%s\",", Sarray[index])
+ endif
+ index += 1
+ od
+
+ Sout = json_appendobject(Sjson, Skey, sprintf("[%s]", strsub(Sformatted, 0, strlen(Sformatted) - 1)))
+ xout Sout
+endop
+
+
+/*
+ Append f-table to JSON object string with key
+
+ Sout json_appendtable Sjson, Skey, ifn
+
+ Sout string with appendage
+ Sjson input string to append to
+ Skey key for appending
+ ifn f-table number
+*/
+opcode json_appendtable, S, SSi
+ Sjson, Skey, ifn xin
+ Sformatted = ""
+ ilen = ftlen(ifn)
+ index = 0
+ while (index < ilen) do
+ ivalue = table:i(index, ifn)
+ Sformat = (frac(ivalue) == 0) ? "%d" : "%f"
+ Sformatted strcat Sformatted, sprintf(Sformat, ivalue)
+ if (index != ilen - 1) then
+ Sformatted strcat Sformatted, ","
+ endif
+ index += 1
+ od
+ Sout = json_appendobject(Sjson, Skey, sprintf("[%s]", Sformatted))
+ xout Sout
+endop
+
+
+
+
+/*
+ Obtain an object, array or value from a json object given a string key
+
+ itype, Stringvalue, inumericvalue json_parse Sjson, Skey
+
+ itype type of returned value: 0=string, 1=object, 2=array, 3=numeric (1 and 2 are returned as strings for further parsing)
+ Stringvalue the requested value as a string
+ inumericvalue the numeric value if itype is 3 , otherwise -1
+
+ Sjson the json to parse
+ Skey the key to lookup
+*/
+opcode json_parse, iSi, SS
+ Sjson, Skey xin
+ itype = -1
+ index = 0
+ idepth = 0
+ idepthrequest = -1
+ iobjectstart = -1
+ inval = 0
+ instring = 0
+ inrequested = 0
+ while (index < strlen(Sjson)) do
+ Schar = strsub(Sjson, index, index + 1)
+ if (strcmp(Schar, "[") == 0 && instring == 0) then
+ idepth += 1
+ if (inrequested == 1 && iobjectstart == -1) then
+ iobjectstart = index
+ endif
+
+ elseif (strcmp(Schar, "]") == 0 && instring == 0) then
+ idepth -= 1
+ if (idepthrequest == idepth) then
+ itype = 2
+ goto complete
+ endif
+
+ elseif (strcmp(Schar, "{") == 0 && instring == 0) then
+ idepth += 1
+ if (inrequested == 1 && iobjectstart == -1) then
+ iobjectstart = index
+ endif
+
+ elseif (strcmp(Schar, "}") == 0 && instring == 0) then
+ idepth -= 1
+ if (idepthrequest == idepth) then
+ itype = 1
+ goto complete
+ endif
+
+ elseif (strcmp(Schar, ":") == 0 && instring == 0) then
+ inval = 1
+ iobjectstart = index + 1
+ elseif (strcmp(Schar, ",") == 0 && instring == 0) then
+ if (inval == 1) then
+ inval = 0
+ if (inrequested == 1 && idepthrequest == idepth) then
+ index -= 1
+ itype = 3
+ goto complete
+ endif
+ endif
+ elseif (strcmp(Schar, "\"") == 0) then
+ instring = 1 - instring
+ if (instring == 1) then
+ istringstart = index + 1
+ else
+ String = strsub(Sjson, istringstart, index)
+ if (inrequested == 1 && idepthrequest == idepth) then
+ iobjectstart = istringstart
+ index -= 1
+ itype = 0
+ goto complete
+ elseif (strcmp(String, Skey) == 0) then
+ idepthrequest = idepth
+ inrequested = 1
+ endif
+ endif
+ endif
+ index += 1
+ od
+
+complete:
+
+ Stringvalue = strsub(Sjson, iobjectstart, index+1) ; +1 required?
+ if (itype == 3) then
+ ivalid, inumericvalue try_strtod strstrip(Stringvalue)
+ itype = (ivalid == 1) ? 3 : 0
+ endif
+
+
+ xout itype, Stringvalue, inumericvalue
+endop
+
+
+; itype: 0=S, 1=i
+opcode _json_getarray, S[]i[], Si
+ Sjson, itype xin
+ index = 0
+ instring = 0
+ iobjectstart = -1
+ iobjectcount = 0
+ iwriteindex = 0
+
+ while (index < strlen(Sjson)) do
+ Schar = strsub(Sjson, index, index + 1)
+ if (strcmp(Schar, ",") == 0 && instring == 0) then
+ iobjectcount += 1
+ elseif (strcmp(Schar, "\"") == 0) then
+ instring = 1 - instring
+ endif
+ index += 1
+ od
+
+ if (itype == 0) then
+ Soutput[] init iobjectcount + 1
+ ioutput[] init 1
+ else
+ Soutput[] init 1
+ ioutput[] init iobjectcount + 1
+ endif
+ index = 0
+ instring = 0
+
+ while (index < strlen(Sjson)) do
+ Schar = strsub(Sjson, index, index + 1)
+ if (strcmp(Schar, ",") == 0 && instring == 0) then
+ if (itype == 1) then
+ ioutput[iwriteindex] = strtod(strsub(Sjson, iobjectstart, index))
+ iobjectstart = index + 1
+ endif
+ iwriteindex += 1
+ elseif (strcmp(Schar, "[") == 0 && instring == 0) then
+ iobjectstart = index + 1
+ elseif (strcmp(Schar, "]") == 0 && instring == 0) then
+ if (itype == 1) then
+ ioutput[iwriteindex] = strtod(strsub(Sjson, iobjectstart, index))
+ endif
+ elseif (strcmp(Schar, "\"") == 0) then
+ if (instring == 0) then
+ iobjectstart = index + 1
+ elseif (itype == 0) then
+ Svalue = strsub(Sjson, iobjectstart, index)
+ Soutput[iwriteindex] = Svalue
+ endif
+ instring = 1 - instring
+ endif
+ index += 1
+ od
+ xout Soutput, ioutput
+endop
+
+opcode json_getstringarray, S[], S
+ Sjson xin
+ Soutput[], i_[] _json_getarray Sjson, 0
+ xout Soutput
+endop
+
+opcode json_getnumericarray, i[], S
+ Sjson xin
+ S_[], ioutput[] _json_getarray Sjson, 1
+ xout ioutput
+endop
+
+/*
+ Obtain an object, array or value from a json array given an index
+
+ itype, Stringvalue, inumericvalue json_parsearray Sjson, irequestindex
+
+ itype type of returned value: 0=string, 1=object, 2=array, 3=numeric (1 and 2 are returned as strings for further parsing)
+ Stringvalue the requested value as a string
+ inumericvalue the numeric value if itype is 3 , otherwise -1
+
+ Sjson the json to parse
+ irequestindex index in the array to obtain
+*/
+opcode json_parsearray, iSi, Si
+ Sjson, irequestindex xin
+ itype = -1
+ inmainarray = 0
+ index = 0
+ iobjectstart = 0
+ iscanindex = 0
+ instring = 0
+ idepth = 0
+ while (index < strlen(Sjson)) do
+ Schar = strsub(Sjson, index, index + 1)
+
+ if (strcmp(Schar, "[") == 0 && instring == 0) then
+ if (inmainarray == 0) then
+ inmainarray = 1
+ iobjectstart = index + 1
+ else
+ idepth += 1
+ endif
+
+ elseif (strcmp(Schar, "]") == 0 && instring == 0) then
+ if (inmainarray == 1 && idepth == 0) then
+ itype = 0
+ goto complete
+ else
+ idepth -= 1
+ itype = 2
+ endif
+
+ elseif (strcmp(Schar, "{") == 0 && inmainarray == 1 && instring == 0) then
+ idepth += 1
+
+ elseif (strcmp(Schar, "}") == 0 && inmainarray == 1 && instring == 0) then
+ idepth -= 1
+ itype = 1
+
+ elseif (strcmp(Schar, ",") == 0 && idepth == 0 && inmainarray == 1 && instring == 0) then
+ if (iscanindex == irequestindex) then
+ itype = 0
+ goto complete
+ endif
+ iobjectstart = index + 1
+ iscanindex += 1
+
+ elseif (strcmp(Schar, "\"") == 0 && idepth == 0 && inmainarray == 1 && iscanindex == irequestindex) then
+ instring = 1 - instring
+ if (instring == 1) then
+ iobjectstart = index + 1
+ else
+ itype = 0
+ goto complete
+ endif
+ endif
+
+ index += 1
+ od
+
+complete:
+
+ Stringvalue = strsub(Sjson, iobjectstart, index)
+ if (itype == 0) then
+ ivalid, inumericvalue try_strtod strstrip(Stringvalue)
+ itype = (ivalid == 1) ? 3 : 0
+ endif
+
+
+ xout itype, Stringvalue, inumericvalue
+endop
+
+
+
+/*
+ Get the length of a json array
+
+ ilength json_arraylength Sjson
+
+ ilength length determined
+ Sjson input array
+*/
+opcode json_arraylength, i, S
+ Sjson xin
+ idepth = -1
+ idepthmax = -1
+ ihasitems = 0
+ instring = 0
+ index = 0
+ itemnum = 0
+
+ while (index < strlen(Sjson)) do
+ Schar = strsub(Sjson, index, index + 1)
+ if (strcmp(Schar, "[") == 0 && instring == 0) then
+ idepth += 1
+ idepthmax += 1
+
+ elseif (strcmp(Schar, "]") == 0 && instring == 0) then
+ idepth -= 1
+ if (idepth < 0) then
+ goto complete
+ endif
+
+ elseif (strcmp(Schar, "{") == 0 && instring == 0 && idepth >= 0) then
+ idepth += 1
+ idepthmax += 1
+
+ elseif (strcmp(Schar, "}") == 0 && instring == 0 && idepth >= 0) then
+ idepth -= 1
+
+ elseif (strcmp(Schar, ",") == 0 && instring == 0 && idepth == 0) then
+ itemnum += 1
+
+ elseif (strcmp(Schar, "\"") == 0) then
+ if (idepth == 0) then
+ ihasitems = 1
+ endif
+ instring = 1 - instring
+ endif
+ index += 1
+ od
+
+complete:
+ if (idepthmax != 0 || ihasitems == 1) then
+ itemnum += 1
+ endif
+ xout itemnum
+
+endop
+
+
+
+
+/*
+ Get the keys from an object
+
+ Skeys[] json_getkeys Sjson
+
+ Skeys[] the keys found
+ Sjson input json
+*/
+opcode json_getkeys, S[], S
+ Sjson xin
+ Stemp[] init 999
+
+ itempindex init 0
+ idepth = -1
+ instring = 0
+ index = 0
+ inmainobject = 0
+ iskey = 1
+
+ while (index < strlen(Sjson)) do
+ Schar = strsub(Sjson, index, index + 1)
+ if (strcmp(Schar, "[") == 0 && instring == 0 && idepth >= 0) then
+ idepth += 1
+
+ elseif (strcmp(Schar, "]") == 0 && instring == 0 && idepth >= 0) then
+ idepth -= 1
+
+ elseif (strcmp(Schar, "{") == 0 && instring == 0) then
+ idepth += 1
+
+ elseif (strcmp(Schar, "}") == 0 && instring == 0) then
+ idepth -= 1
+ if (idepth < 0) then
+ goto complete
+ endif
+
+ elseif (strcmp(Schar, ":") == 0 && instring == 0 && idepth == 0) then
+ iskey = 0
+
+ elseif (strcmp(Schar, ",") == 0 && instring == 0 && idepth == 0) then
+ iskey = 1
+
+ elseif (strcmp(Schar, "\"") == 0 && idepth == 0) then
+ instring = 1 - instring
+ if (instring == 1) then
+ istringstart = index + 1
+ elseif (iskey == 1) then
+ Stemp[itempindex] = strsub(Sjson, istringstart, index)
+ itempindex += 1
+ endif
+ endif
+ index += 1
+ od
+
+complete:
+ Skeys[] init itempindex ;+ 1
+ index = 0
+ while (index < itempindex) do
+ Skeys[index] = Stemp[index]
+ index += 1
+ od
+
+ xout Skeys
+endop
+
+
+#end