From 9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 13 Apr 2025 18:48:02 +0100 Subject: initial --- site/udo/string_tools.udo | 375 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100755 site/udo/string_tools.udo (limited to 'site/udo/string_tools.udo') diff --git a/site/udo/string_tools.udo b/site/udo/string_tools.udo new file mode 100755 index 0000000..c2c14c0 --- /dev/null +++ b/site/udo/string_tools.udo @@ -0,0 +1,375 @@ +#ifndef UDO_STRINGTOOLS +#define UDO_STRINGTOOLS ## +/* + String processing tools + + This file is part of the SONICS UDO collection by Richard Knight 2021, 2022, 2023 + License: GPL-2.0-or-later + http://1bpm.net + +*/ + +#include "/host_platform.udo" + +/* + Replace character with another character or sequence of characters + Soutput str_replacechar Sinput, Sfrom, Sto + + Soutput string with replacements + Sinput input string + Sfrom character to replace + Sto string or character to substitute +*/ +opcode str_replacechar, S, SSS + Sinput, Sfrom, Sto xin + Soutput = "" + index = 0 + while (index < strlen(Sinput)) do + Schar = strsub(Sinput, index, index + 1) + if (strcmp(Sfrom, Schar) == 0) then + Soutput = strcat(Soutput, Sto) + else + Soutput = strcat(Soutput, Schar) + endif + index += 1 + od + xout Soutput +endop + + +/* + String alphabetical bubble sort + Sout[] srt_bubblestr Sin[] + + Sout[] sorted array + Sin[] array to sort +*/ +opcode srt_bubblestr, S[], S[] + Sin[] xin + Stemp = "" + ilen = lenarray(Sin) + index1 = 0 + while (index1 < ilen-1) do + index2 = 0 + while (index2 < ilen-1-index1) do + if (strcmp(Sin[index2], Sin[index2+1]) > 0) then + Stemp = Sin[index2] + Sin[index2] = Sin[index2+1] + Sin[index2+1] = Stemp + endif + + index2 += 1 + od + index1 += 1 + od + xout Sin +endop + + +/* + Polynomial rolling hash + ihash str_hash Sstring + + ihash the resulting hash value + Sstring string to be hashed +*/ +opcode str_hash, i, S + Sin xin + ip = 31 + im = 1e9+7 ; was 1e9+9, changed for 32bit + ipp = 1 + ihash = 0 + index = 0 + while (index < strlen(Sin)) do + ihash = (ihash + ((strchar(strsub(Sin, index)) - 97) + 1) * ipp) ; changed from *ip to *ipp ??? due to collisions. not fully checked + ipp = (ipp * ip) % im + index += 1 + od + xout ihash +endop + + +/* + Split separated string to array + Sitems[] str_split Sinput, Separator + + Sitems[] the processed items + Sinput string to split + Separator separator to split on +*/ +opcode str_split, S[], SS + Sin, Sep xin + Stemp = Sin + itemnum = 1 + index = 1 + while (index > 0) do + index strindex Stemp, Sep + if (index > 0) then + Stemp strsub Stemp, index+1 + itemnum += 1 + endif + od + Sout[] init itemnum + + iwindex = 0 + Stemp = Sin + index = 1 + while (index > 0) do + index strindex Stemp, Sep + if (index > 0) then + Sout[iwindex] strsub Stemp, 0, index + Stemp strsub Stemp, index+1 + else + Sout[iwindex] = Stemp + endif + iwindex += 1 + od + + xout Sout +endop + + +/* + Print ftable contents + printtable ifn + + ifn ftable number to print +*/ +opcode printtable, 0, i + ifn xin + index = 0 + while (index < ftlen(ifn)) do + print table:i(index, ifn) + index += 1 + od +endop + + + +/* + Store string to an exising table as ascii characters + str2tab String, ifn + + String string to store + ifn table to store to +*/ +opcode str2tab, 0, Si + String, ifn xin + index = 0 + while (index < strlen(String)) do + ival strchar String, index + tabw_i ival, index, ifn + index += 1 + od + tabw_i -99, index, ifn +endop + + +/* + Create a table and store a string in it as ascii characters + ifn str2newtab String + + ifn new table number + String string to store +*/ +opcode str2newtab, i, S + String xin + ifn ftgen 0, 0, strlen(String)+1, 7, 0 + str2tab String, ifn + xout ifn +endop + + +/* + Obtain a string from a table containing ascii characters + String tab2str ifn + + String retrieved string + ifn table number +*/ +opcode tab2str, S, i + ifn xin + index = 0 + Sval = "" + ival = 0 + while (ival != -99) do + ival tab_i index, ifn + if (ival == -99) igoto done + Sval strcat Sval, sprintf("%c", ival) + index += 1 + od +done: + xout Sval +endop + + +/* + Obtain file extension converted to lowercase (anything past the last dot) + Sextension fileextension Sfile + + Sfile path or filename + Sextension the extension in lower case +*/ +opcode fileextension, S, S + Sfile xin + ilastdot strrindex Sfile, "." + if (ilastdot == -1) then + Sextension = "none" + goto return + endif + ilen strlen Sfile + Sextension strsub Sfile, ilastdot + 1, ilen + Sextension strlower Sextension + goto return +return: + xout Sextension +endop + + +/* + Print a string array with each value separated by a newline + + str_printarray Sarray[] + + Sarray[] the array to print +*/ +opcode str_printarray, 0, S[] + Sarray[] xin + ilen = lenarray(Sarray) + index = 0 + while (index < ilen) do + prints sprintf("%s\n", Sarray[index]) + index += 1 + od +endop + + +/* + Test if a string is numeric + + isnumeric str_isnumeric Svalue + + isnumeric 0 if not numeric, 1 if numeric + Svalue string to test +*/ +opcode str_isnumeric, i, S + Svalue xin + isnumeric = 1 + ihaspoint = 0 + index = 0 + while (index < strlen(Svalue)) do + ichar = strchar(Svalue, index) + + ; allow only one decimal point + if (ichar == 46) then + if (ihaspoint == 1) then + isnumeric = 0 + goto complete + else + ihaspoint = 1 + endif + + ; not a number or decimal place + elseif (!(ichar >= 48 && ichar <= 57)) then + isnumeric = 0 + goto complete + endif + index += 1 + od +complete: + xout isnumeric +endop + + + +/* + Convert a string to float if numeric + + ivalid, ivalue try_strtod Svalue + + ivalid 0 if the input is not numeric, 1 if conversion is successful + ivalue converted value, or -1 if the input is not numeric +*/ +opcode try_strtod, ii, S + Svalue xin + if (str_isnumeric(Svalue) == 0) then + ivalid = 0 + ivalue = -1 + else + ivalid = 1 + ivalue = strtod(Svalue) + endif + xout ivalid, ivalue +endop + + +/* + Get the basename from a file path separated by slashes + + Sbasename str_basename Spath + + Sbasename the filename + Spath the path +*/ +opcode str_basename, S, S + Spath xin + Sbasename = strsub(Spath, strrindex(Spath, "/") + 1) + xout Sbasename +endop + + +/* + Get a random alphanumeric string + + Sout str_random [ilen=10] + + Sout the random string + ilen length of string +*/ +opcode str_random, S, j + ilen xin + Sout = "" + ilen = (ilen == -1) ? 10 : ilen + index = 0 + while (index < ilen) do + irange = round(random(0, 2)) + if (irange == 0) then + ichar random 48, 57 + elseif (irange == 1) then + ichar random 65, 90 + elseif (irange == 2) then + ichar random 97, 122 + endif + Sout = strcat(Sout, sprintf("%c", ichar)) + index += 1 + od + xout Sout +endop + +/* + Get a random filename + + Sout str_randomfilename Sext [,ilen=10] + + Sout the random filename + Sext file extension + ilen length of string +*/ +opcode str_randomfilename, S, Sj + Sext, ilen xin + Sfile str_random ilen + xout strcat(Sfile, sprintf(".%s", Sext)) +endop + +/* + Get a random filename in the host temporary directory + + Sout str_randomtempfilename Sext [,ilen=10] +*/ +opcode str_randomtempfilename, S, Sj + Sext, ilen xin + Sfile str_randomfilename Sext, ilen + xout sprintf("%s/%s", host_tempdir(), Sfile) +endop + +#end -- cgit v1.2.3