#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