Mercurial > repos > rhope
view string.rhope @ 185:4580c08fd4e8
Fix an import missed in last commit
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 27 Jul 2011 21:32:40 -0700 |
parents | 64be565a40c6 |
children |
line wrap: on
line source
Import pattern.rhope UTF8 Expect[num,arr,index,count,consumed:out] { byte <- [arr]Index[index] { If[[128u8]>[byte]] { //Error: ASCII byte when we were expecting part of a mutlibyte sequence //treat each byte as a separate character ncount <- [1i32]+[[count]+[consumed]] }{ If[[192u8]>[byte]] { If[[num]=[1]] { //Sequence is complete count as single character ncount <- [1i32]+[count] }{ out <- UTF8 Expect[[num]-[1], arr, [index]+[1], count, [1i32]+[consumed]] } }{ //Error: too high to be a continuation byte ncount <- [1i32]+[[count]+[consumed]] } } }{ //Error: string ended in the middle of a multi-byte sequence out <- [count]+[consumed] } Val[ncount] { [arr]Next[index] { out <- Count UTF8[arr, ~, ncount] }{ out <- Val[ncount] } } } Count UTF8[arr,index,count:out] { byte <- [arr]Index[index] If[[128u8]>[byte]] { ncount <- [1i32]+[count] } { If[[192u8]>[byte]] { //Error: Encoding for 2nd,3rd or 4th byte of sequence //treat as a single character ncount <- [1i32]+[count] }{ If[[224u8]>[byte]] { out <- UTF8 Expect[1, arr, [index]+[1], count, 1] }{ If[[240u8]>[byte]] { out <- UTF8 Expect[2, arr, [index]+[1], count, 1] }{ If[[245u8]>[byte]] { out <- UTF8 Expect[3, arr, [index]+[1], count, 1] }{ //Error: Out of range of Unicode standard //treat as a single character ncount <- [1i32]+[count] } } } } } [arr]Next[index] { out <- Count UTF8[arr, ~, ncount] }{ out <- Val[ncount] } } Blueprint String { Buffer Length(Int32,Naked) } String@Array[in:out(String)] { [in]First { len <- Count UTF8[in, ~, 0i32] } { len <- 0i32 } out <- [[Build[String()]]Buffer <<[in]]Length <<[len] } String@Empty Array[in:out(String)] { out <- "" } Print@String[string:out] { //TODO: Sanitize string (remove terminal escapes and replace invalid UTF) write[1i32, [string]Buffer >>, Int64[[[string]Buffer >>]Length >>]] { out <- write[1i32, [Array[]]Append[10u8], 1i64] } } Get Char[:out,err] { ret,data <- read[0, [Array[]]Set[0, 0u8], 1i64] If[[ret]<[1i64]] { err <- Val[ret] } { out <- String[data] } } _String to Int[current,index,array,ten,conv:out] { char <- [array]Index[index] { If[[char]<[48u8]] { out <- Val[current] }{ If[[char]>[57u8]] { out <- Val[current] }{ out <- _String to Int[[[current]*[ten]]+[[conv]Call[[char]-[48u8]]], [index]+[1], array, ten, conv] } } }{ out <- Val[current] } } U8toI8[val:out] { out <- Trunc Int8[Int16[val]] } Int8@String[string:out] { buf <- [string]Buffer >> [buf]Index[0] { If[[~]=[45u8]] { out <- [0i8]-[_String to Int[0i8, 1, buf, 10i8, U8toI8[?]]] }{ out <- _String to Int[0i8, 0, buf, 10i8, U8toI8[?]] } }{ out <- 0i8 } } Int16@String[string:out] { buf <- [string]Buffer >> [buf]Index[0] { If[[~]=[45u8]] { out <- [0i16]-[_String to Int[0i16, 1, buf, 10i16, Int16[?]]] }{ out <- _String to Int[0i16, 0, buf, 10i16, Int16[?]] } }{ out <- 0i16 } } Int32@String[string:out] { buf <- [string]Buffer >> [buf]Index[0] { If[[~]=[45u8]] { out <- [0i32]-[_String to Int[0i32, 1, buf, 10i32, Int32[?]]] }{ out <- _String to Int[0i32, 0, buf, 10i32, Int32[?]] } }{ out <- 0i32 } } _Hex Int32[str,cur,idx:out] { char <- [str]Byte[idx] { //0-9 [char]Between[47u8, 58u8] { adjust <- 48u8 }{ //A-F [char]Between[64u8, 71u8] { adjust <- 55u8 }{ //a-f [char]Between[96u8, 103u8] { adjust <- 87u8 }{ out <- cur } } } Val[adjust] { out <- _Hex Int32[str, [[cur]*[16i32]]+[Int32[[char]-[adjust]]], [idx]+[1]] } }{ out <- cur } } Hex Int32[str:out] { out <- _Hex Int32[str, 0i32, 0] } Int64@String[string:out] { buf <- [string]Buffer >> [buf]Index[0] { If[[~]=[45u8]] { out <- [0i64]-[_String to Int[0i64, 1, buf, 10i64, Int64[?]]] }{ out <- _String to Int[0i64, 0, buf, 10i64, Int64[?]] } }{ out <- 0i64 } } UInt8@String[string:out] { out <- _String to Int[0u8, 0, [string]Buffer >>, 10u8, Val[?]] } UInt16@String[string:out] { out <- _String to Int[0u16, 0, [string]Buffer >>, 10u16, UInt16[?]] } UInt32@String[string:out] { out <- _String to Int[0u32, 0, [string]Buffer >>, 10u32, UInt32[?]] } UInt64@String[string:out] { out <- _String to Int[0u64, 0, [string]Buffer >>, 10u64, UInt64[?]] } Int8@String Slice[string:out] { out <- Int8[[string]Flatten] } Int8@String Cat[string:out] { out <- Int8[[string]Flatten] } Int16@String Slice[string:out] { out <- Int16[[string]Flatten] } Int16@String Cat[string:out] { out <- Int16[[string]Flatten] } Int32@String Slice[string:out] { out <- Int32[[string]Flatten] } Int32@String Cat[string:out] { out <- Int32[[string]Flatten] } Int64@String Slice[string:out] { out <- Int64[[string]Flatten] } Int64@String Cat[string:out] { out <- Int64[[string]Flatten] } UInt8@String Slice[string:out] { out <- UInt8[[string]Flatten] } UInt8@String Cat[string:out] { out <- UInt8[[string]Flatten] } UInt16@String Slice[string:out] { out <- UInt16[[string]Flatten] } UInt16@String Cat[string:out] { out <- UInt16[[string]Flatten] } UInt32@String Slice[string:out] { out <- UInt32[[string]Flatten] } UInt32@String Cat[string:out] { out <- UInt32[[string]Flatten] } UInt64@String Slice[string:out] { out <- UInt64[[string]Flatten] } UInt64@String Cat[string:out] { out <- UInt64[[string]Flatten] } //TODO: Implement me once Real64 support is added Real64[string:out] { out <- string } Flatten@String[string:out] { out <- string } _CPOff to BOff[buff,cur,boff,cpoff,expected,used:out] { If[expected] { byte <- [buff]Index[boff] err <- If[[byte]>[192u8]] {} { err <- If[[byte]<[128u8]] {} { out <- _CPOff to BOff[buff, cur, [boff]+[1i32], cpoff, [expected]-[1i32], [used]+[1i32]] } } Val[err] { ncur <- [cur]+[used] If[[ncur]>[cpoff]] { out <- [boff]-[[cpoff]-[ncur]] }{ out <- CPOff to BOff[buff,ncur,boff,cpoff] } } }{ out <- CPOff to BOff[buff,[cur]+[1i32],boff,cpoff] } } CPOff to BOff[buff,cur,boff,cpoff:out] { If[[cur]=[cpoff]] { out <- boff }{ byte <- [buff]Index[boff] If[[byte] < [128u8]] { nboff <- [boff]+[1i32] ncur <- [cur]+[1i32] }{ If[[byte]<[192u8]] { //Error: Encoding for 2nd,3rd or 4th byte of sequence //treat as a single character nboff <- [boff]+[1i32] ncur <- [cur]+[1i32] }{ If[[byte]<[224u8]] { expect <- 1i32 }{ If[[byte]<[240u8]] { expect <- 2i32 }{ If[[byte]<[245u8]] { expect <- 3i32 }{ //Error nboff <- [boff]+[1i32] ncur <- [cur]+[1i32] } } } Val[expect] { out <- _CPOff to BOff[buff, cur, [boff]+[1i32], cpoff, expect, 1i32] {} } } } out <- CPOff to BOff[buff, ncur, cpoff, nboff] } } Slice@String[string,slicepoint:left,right] { If[[slicepoint]>=[[string]Length]] { left <- string right <- "" }{ If[[slicepoint]<=[0]] { left <- "" right <- string }{ If[[[string]Length] = [[string]Byte Length]] { sliceoffset <- Val[slicepoint] } { sliceoffset <- CPOff to BOff[[string]Buffer >>, 0i32, 0i32, slicepoint] } left <- String Slice[string, 0i32, slicepoint, sliceoffset] right <- String Slice[string, sliceoffset, [[string]Length >>]-[slicepoint], [[[string]Buffer >>]Length]-[sliceoffset]] } } } Substring@String[string,start,length:out] { If[[start]>=[[string]Length]] { out <- "" } { If[[length]<=[0]] { slength <- [[[string]Length]-[start]]+[length] } { If[[[start]+[length]] > [[string]Length]] { slength <- [[string]Length]-[start] } { slength <- Val[length] } } If[[[string]Length] = [[string]Byte Length]] { sliceoffset <- Val[start] sbytelen <- Val[slength] }{ sliceoffset <- CPOff to BOff[[string]Buffer >>, 0i32, 0i32, start] sbytelen <- CPOff to BOff[[string]Buffer >>, 0i32, sliceoffset, slength] } out <- String Slice[string, sliceoffset, slength, sbytelen] } } Byte@String[string,index:out,invalid] { out,invalid <- [[string]Buffer >>]Index[index] } Length@String[string:out] { out <- [string]Length >> } _=String[left,right,index:out] { [left]Byte[index] { rbyte <- [right]Byte[index] ,out <- If[[~]=[rbyte]] { out <- _=String[left,right,[index]+[1]] } }{ out <- Yes } } Eq String[left,right:out] { ,out <- If[[[left]Length] = [[right]Length]] { out <- _=String[left,right,0] } } Foreign C:libc { memcmp[a(Array,Raw Pointer),b(Array,Raw Pointer),len(Int64,Naked):out(Int32,Naked)] } Foreign C:runtime { _internal_memcmp_offset[left(Array,Raw Pointer),loffset(Int32,Naked),right(Array,Raw Pointer),roffset(Int32,Naked),len(Int32,Naked):out(Int32,Naked)] } _Flat=@String[left,right:out] { ,out <- If[[[left]Byte Length] = [[right]Byte Length]] { If[memcmp[[left]Buffer >>, [right]Buffer >>, Int64[[left]Byte Length]]] { out <- No }{ out <- Yes } } } _Flat=@String Slice[left,right:out] { ,out <- If[[[left]Byte Length] = [[right]Byte Length]] { If[_internal_memcmp_offset[[[left]Source >>]Buffer >>, [left]Offset >>, [right]Buffer >>, 0i32, [left]Byte Length]] { out <- No }{ out <- Yes } } } _Flat=@String Cat[left,right:out] { out <- Eq String[left,right] } _Find Memcmp[haybuf,hayoff,haylen,needlebuf,needleoff,needlelen:found,not found] { not found <- If[[haylen]<[needlelen]] {} { If[_internal_memcmp_offset[haybuf, hayoff, needlebuf, needleoff, needlelen]] { found,not found <- _Find Memcmp[haybuf, [hayoff]+[1], [haylen]-[1], needlebuf, needleoff, needlelen] }{ found <- hayoff } } } _Find Flat@String[haystack,needlebuf,off,bytelen:found,not found] { found,not found <- _Find Memcmp[[haystack]Buffer >>, 0, [haystack]Byte Length, needlebuf, off, bytelen] } _Find Flat@String Slice[haystack,needlebuf,off,bytelen:found,not found] { ,not found <- _Find Memcmp[[[haystack]Source >>]Buffer >>, [haystack]Offset >>, [haystack]Byte Length, needlebuf, off, bytelen] { found <- [~]-[[haystack]Offset >>] } } _Find Partial Memcmp[haybuf,hayoff,haylen,needlebuf,needleoff,needlelen:found,partial,not found] { If[[haylen]<[needlelen]] { ,not found <- If[haylen] { cont <- If[_internal_memcmp_offset[haybuf, hayoff, needlebuf, needleoff, haylen]] {} { partial <- hayoff } } }{ cont <- If[_internal_memcmp_offset[haybuf, hayoff, needlebuf, needleoff, needlelen]] {} { found <- hayoff } } Val[cont] { found,partial,not found <- _Find Partial Memcmp[haybuf, [hayoff]+[1], [haylen]-[1], needlebuf, needleoff, needlelen] } } _Find Partial@String[haystack,hayoff,needlebuf,needleoff,needlelen:found,partial,not found] { found,partial,not found <- _Find Partial Memcmp[[haystack]Buffer >>, hayoff, [[haystack]Byte Length]-[hayoff], needlebuf, needleoff, needlelen] {} {} } _Check Rest@String[haystack,needlebuf,needleoff,needlelen:found,not found] { haylen <- [haystack]Byte Length ,not found <- If[[haylen]<[needlelen]] { not found,found <- If[_internal_memcmp_offset[[haystack]Buffer >>, 0, needlebuf, needleoff, needlelen]] } } _Check Rest@String Slice[haystack,needlebuf,needleoff,needlelen:found,not found] { haylen <- [haystack]Byte Length ,not found <- If[[haylen]<[needlelen]] { not found,found <- If[_internal_memcmp_offset[[[haystack]Source >>]Buffer >>, [haystack]Offset >>, needlebuf, needleoff, needlelen]] } } _Check Rest@String Slice[haystack,needlebuf,needleoff,needlelen:found,not found] { llen <- [[haystack]Left >>]Byte Length If[[needlelen]<[llen]] { found,not found <- _Check Rest[[haystack]Left >>, needlebuf, needleoff, needlelen] } { ,not found <- _Check Rest[[haystack]Left >>, needlebuf, needleoff, llen] { found,not found <- _Check Rest[[haystack]Right >>, needlebuf, [needleoff]+[llen], [needlelen]-[llen]] } } } _Find Partial@String Slice[haystack,hayoff,needlebuf,needleoff,needlelen:found,partial,not found] { ,,not found <- _Find Partial Memcmp[[[haystack]Source >>]Buffer >>, [hayoff]+[[haystack]Offset >>], [[haystack]Byte Length]-[hayoff], needlebuf, needleoff, needlelen] { found <- [~]-[[haystack]Offset >>] } { partial <- [~]-[[haystack]Offset >>] } } _Find Partial@String Cat[haystack,hayoff,needlebuf,needleoff,needlelen:found,partial,not found] { llen <- [[haystack]Left >>]Byte Length If[[hayoff] < [llen]] { found,p,checkright <- [[haystack]Left >>]_Find Partial[hayoff,needlebuf,needleoff,needlelen] {} { partlen <- [llen]-[~] ,cont <- [[haystack]Right >>]_Check Rest[needlebuf,[needleoff]+[partlen], [needlelen]-[partlen]] { found <- Val[p] } { found,partial,not found <- _Find Partial[haystack,[hayoff]+[1],needlebuf,needleoff,needlelen] } }{ found,partial,not found <- _Find Partial[haystack,llen,needlebuf,needleoff,needlelen] } }{ ,,not found <- [[haystack]Right >>]_Find Partial[[hayoff]-[llen],needlebuf,needleoff,needlelen] { found <- [~]+[llen] } { partial <- [~]+[llen] } } } _Find Flat@String Cat[haystack,needlebuf,off,bytelen:found,not found] { found,not found,not found <- _Find Partial[haystack, 0, needlebuf, off, bytelen] {} } =@String[left,right:out] { out <- [right]_Flat=[left] } Byte Length@String[string:out] { out <- [[string]Buffer >>]Length } Append@String[left,right:out] { out <- String Cat[left,right] } Blueprint String Slice { Source Offset(Int32,Naked) Length(Int32,Naked) ByteLen(Int32,Naked) } String Slice[source,offset,length,bytelen:out(String Slice)] { out <- [[[[Build[String Slice()]]Source <<[source]]Offset <<[offset]]Length <<[length]]ByteLen <<[bytelen] } Byte@String Slice[string,index:out,invalid] { ,invalid <- If[[index]<[[string]ByteLen >>]] { out,invalid <- [[string]Source >>]Byte[[index]+[[string]Offset >>]] } } Byte Length@String Slice[string:out] { out <- [string]ByteLen >> } Length@String Slice[string:out] { out <- [string]Length >> } _Slice=@String Slice[left,right:out] { ,out <- If[[[left]Byte Length]=[[right]Byte Length]] { If[_internal_memcmp_offset[[[left]Source >>]Buffer >>, [left]Offset >>, [[right]Source >>]Buffer >>, [right]Offset >>, [left]Byte Length]] { out <- No } { out <- Yes } } } _Slice=@String[left,right:out] { out <- [right]_Flat=[left] } _Slice=@String Cat[left,right:out] { out <- Eq String[left,right] } =@String Slice[left,right:out] { out <- [right]_Slice=[left] } _Flatten@String[string,dest,offset,count:out] { If[count] { out <- [_internal_array_copychunk[[string]Buffer >>, offset, dest, [dest]Length, count]]Length <<[[[dest]Length]+[count]] }{ out <- dest } } Flatten@String[string:out] { out <- string } _Flatten@String Slice[string,dest,offset,count:out] { out <- [[string]Source >>]_Flatten[dest, [[string]Offset >>]+[offset], count] } Flatten@String Slice[string:out] { If[[string]ByteLen >>] { out <- [[Build[String()]]Buffer <<[ [[string]Source >>]_Flatten[_internal_array_allocnaked[[string]ByteLen >>, UInt8()], [string]Offset >>, [string]ByteLen >>] ] ]Length <<[[string]Length >>] }{ out <- "" } } Print@String Slice[string:out] { out <- Print[Flatten[string]] } Append@String Slice[left,right:out] { out <- String Cat[left,right] } Slice@String Slice[string,slicepoint:left,right] { If[[slicepoint]>=[[string]Length]] { left <- string right <- "" }{ If[[slicepoint]<=[0]] { left <- "" right <- string }{ If[[[string]Length]=[[string]Byte Length]] { sliceoffset <- [[string]Offset >>]+[slicepoint] } { sliceoffset <- CPOff to BOff[[[string]Source >>]Buffer >>, 0i32, [string]Offset >>, slicepoint] } left <- String Slice[[string]Source >>, [string]Offset >>, slicepoint, [sliceoffset]-[[string]Offset >>]] right <- String Slice[[string]Source >>, sliceoffset, [[string]Length >>]-[slicepoint], [[string]Byte Length]-[[sliceoffset]-[[string]Offset >>]]] } } } Substring@String Slice[string,start,length:out] { If[[start]>=[[string]Length]] { out <- "" } { If[[length]<=[0]] { slength <- [[[string]Length]-[start]]+[length] } { If[[[start]+[length]] > [[string]Length]] { slength <- [[string]Length]-[start] } { slength <- Val[length] } } If[[[string]Length] = [[string]Byte Length]] { sliceoffset <- [[string]Offset >>]+[start] sbytelen <- Val[slength] }{ sliceoffset <- CPOff to BOff[[[string]Source >>]Buffer >>, 0i32, [string]Offset >>, start] sbytelen <- CPOff to BOff[[[string]Source >>]Buffer >>, 0i32, sliceoffset, slength] } out <- String Slice[[string]Source >>, sliceoffset, slength, sbytelen] } } Depth@String[string:out] { out <- 0 } Depth@String Slice[string:out] { out <- 0 } Depth@String Cat[string:out] { out <- Depth >>[string] } Blueprint String Cat { Left Right Length ByteLen Depth } String Cat[left,right:out] { out <- [[[[[Build[String Cat()] ]Left <<[left] ]Right <<[right] ]Length <<[ [[left]Length]+[[right]Length] ] ]ByteLen <<[ [[left]Byte Length]+[[right]Byte Length] ] ]Depth <<[ [1]+[Min[[left]Depth, [right]Depth]] ] } Append@String Cat[left,right:out] { ll <- [left]Left >> lr <- [left]Right >> If[[[ll]Depth] > [[lr]Depth]] { out <- String Cat[ll, Append[lr,right]] }{ out <- String Cat[left,right] } } Byte@String Cat[string,index:out,invalid] { leftlen <- [[string]Left >>]Byte Length If[[index]<[leftlen]] { out,invalid <- [[string]Left >>]Byte[index] }{ rindex <- [index]-[leftlen] ,invalid <- If[[rindex]<[[[string]Right >>]Byte Length]] { out,invalid <- [[string]Right >>]Byte[rindex] } } } Byte Length@String Cat[string:out] { out <- [string]ByteLen >> } Length@String Cat[string:out] { out <- [string]Length >> } _Flatten@String Cat[string,dest,offset,count:out] { left <- [string]Left >> If[[offset] < [[left]Byte Length]] { lcount <- Min[[left]Byte Length, count] ldest <- [left]_Flatten[dest, offset, lcount] rcount <- [count]-[lcount] }{ ldest <- Val[dest] rcount <- count } If[[[offset]+[count]]>[[left]Byte Length]] { right <- [string]Right >> roffset <- Max[0, [offset]-[[left]Byte Length]] out <- [right]_Flatten[ldest, roffset, Min[[right]Byte Length, rcount]] }{ out <- Val[ldest] } } Flatten@String Cat[string:out] { If[[string]ByteLen >>] { out <- [[Build[String()] ]Buffer << [ [[string]Right >>]_Flatten[ [[string]Left >>]_Flatten[_internal_array_allocnaked[[string]ByteLen >>, UInt8()], 0i32, [[string]Left >>]Byte Length], 0i32, [[string]Right >>]Byte Length]] ]Length << [[string]Length >>] }{ out <- "" } } Print@String Cat[string:out] { out <- Print[Flatten[string]] } Slice@String Cat[string,slicepoint:left,right] { llen <- [[string]Left >>]Length If[[slicepoint]=[llen]] { left <- [string]Left >> right <- [string]Right >> }{ If[[slicepoint]<[llen]] { left,lright <- [[string]Left >>]Slice[slicepoint] right <- String Cat[lright,[string]Right >>] }{ rleft,right <- [[string]Right >>]Slice[ [slicepoint]-[llen] ] left <- String Cat[[string]Left >>, rleft] } } } Substring@String Cat[string,start,length:out] { llen <- [[string]Left >>]Length If[[start] >= [llen]] { out <- [[string]Right >>]Substring[[start]-[llen],length] }{ If[[length] <= [0]] { slength <- [[[string]Length]-[start]]+[length] } { If[[[start]+[length]] > [[string]Length]] { slength <- [[string]Length]-[start] } { slength <- Val[length] } } If[[[start]+[slength]]<=[llen]] { out <- [[string]Left >>]Substring[start, slength] }{ new end <- [start]+[slength] If[[new end]=[[string]Length]] { right <- Right >>[string] } { right <- [[string]Right >>]Substring[0, [new end]-[[string]Length]] } If[[start]=[0]] { left <- Left >>[string] } { left <- [[string]Left >>]Substring[start, 0] } out <- String Cat[left, right] } } } =@String Cat[left,right:out] { out <- Eq String[left,right] } =Delim[string,delims,index:outindex,after,nomatch] { delim <- [delims]Index[index] If[[[string]Length]<[[delim]Length]] { try next <- Yes }{ check,mafter <- [string]Slice[[delim]Length] ,try next <- If[[check]=[delim]] { outindex <- index after <- Val[mafter] } } Val[try next] { ,nomatch <- [delims]Next[index] { outindex,after,nomatch <- =Delim[string,delims,~] } } } Match@String[string,cmp:num,no match,idx] { n <- [string]Length ,no match <- If[[string]=[[cmp]Substring[0, n]]] { num <- Val[n] idx <- 0 } } Match@String Slice[string,cmp:num,no match,idx] { n <- [string]Length ,no match <- If[[string]=[[cmp]Substring[0, n]]] { num <- Val[n] idx <- 0 } } _Partition@String[delim,string:matched,after,not found] { ,not found <- [string]_Find Flat[[delim]Buffer >>, 0, [delim]Byte Length] { //TODO: Translate byte offset to cp offset when necessary matched <- delim after <- [string]Substring[[~]+[[delim]Length], 0] } } _Partition@String Slice[delim,string:matched,after,not found] { ,not found <- [string]_Find Flat[[[delim]Source >>]Buffer >>, [delim]Offset >>, [delim]Byte Length] { //TODO: Translate byte offset to cp offset when necessary matched <- delim after <- [string]Substring[[~]+[[delim]Length], 0] } } Pattern@String[string:out] { out <- string } Pattern@String Slice[string:out] { out <- string } Pattern@String Cat[string:out] { out <- Flatten[string] } Partition[string,delims:before,matched,after,not found] { matched,after,not found <- _Partition[Pattern[delims],string] { dlen <- Length[~] } { alen <- Length[~] } blen <- [[string]Length]-[[dlen]+[alen]] If[blen] { before <- [string]Substring[0, blen] } { before <- "" } } Dict Type ID@String[string:out] { out <- ID[String()] } Dict Type ID@String Cat[string:out] { out <- ID[String()] } Dict Type ID@String Slice[string:out] { out <- ID[String()] } Dict Bits@String[string,index:out,invalid] { ,invalid <- [string]Byte[index] { out <- UInt32[~] } } Dict Bits@String Cat[string,index:out,invalid] { ,invalid <- [string]Byte[index] { out <- UInt32[~] } } Dict Bits@String Slice[string,index:out,invalid] { ,invalid <- [string]Byte[index] { out <- UInt32[~] } } _From Dict String[arr,el:out] { out <- [arr]Append[Trunc UInt8[el]] } From Dict Key@String[string,data:out] { out <- String[Fold[_From Dict String[?], Array[], data]] } String@String[string:out] { out <- string } String@String Cat[string:out] { out <- string } String@String Slice[string:out] { out <- string } _No Pattern Match[:out,no match] { no match <- Yes } _Iter Bytes Buf[buf,offset,first,last,func,if end:out,end,seekfout,seekout] { [buf]Index[offset] { out,nextf,no next,seekf,seek <- [func]Call[~] {} { If[[offset]<[last]] { out,end <- _Iter Bytes Buf[buf, [offset]+[1], first, last, nextf, no next] } { end <- [[()]Append[nextf]]Append[no next] } }{}{ newoff <- [offset]-[seek] If[[newoff]<[first]] { seekfout <- Val[seekf] seekout <- [first]-[newoff] }{ out,end <- _Iter Bytes Buf[buf, newoff, first, last, seekf, _No Pattern Match[?]] } } }{ end <- [[()]Append[func]]Append[if end] } } _Iter Bytes@String[string,func,start,if end:out,end,seekfunc,seek] { out,end,seekfunc,seek <- _Iter Bytes Buf[[string]Buffer >>, start, 0, [[string]Byte Length]-[1], func, if end] } _Iter Bytes@String Slice[string,func,start,if end:out,end,seekfunc,seek] { out,end,seekfunc,seek <- _Iter Bytes Buf[[[string]Source >>]Buffer >>, [[string]Offset >>]+[start], [string]Offset >>, [[[string]Byte Length]-[1]]+[[string]Offset >>], func, if end] } _Iter Bytes@String Cat[string,func,start,if end:out,end,seekfunc,seek] { llen <- [[string]Left >>]Byte Length If[[start]<[llen]] { out,,seekfunc,seek <- [[string]Left >>]_Iter Bytes[func, start, if end] {} { right off <- 0 right func <- [~]Index[0] right if end <- [~]Index[1] } }{ right off <- [start]-[llen] right func <- Val[func] right if end <- Val[if end] } Val[right off] { out,end,,rseek <- [[string]Right >>]_Iter Bytes[right func, ~, right if end] {} {} { out,end,seekfunc,seek <- [string]_Iter Bytes[~, [llen]-[rseek], _No Pattern Match[?]] } } } Iter Bytes[string,func,start:out,end] { out <- [string]_Iter Bytes[func, start, _No Pattern Match[?]] {} { out <- Call[[~]Index[1]] {} { end <- Yes } } { end <- Yes } } Replace[string,otoreplace,with:out] { toreplace <- Pattern[otoreplace] ,delim,after <-[string]Partition[toreplace] { wt <- Blueprint Of[with] If[ [[[wt]=[String()]] Or [[wt]=[String Slice()]]] Or [[wt]=[String Cat()]] ] { replacement <- with }{ ,,idx <- [toreplace]Match[delim] replacement <- [with]Index[idx] } out <- [[~]Append[replacement]]Append[Replace[after,toreplace,with]] } {} {} { out <- string } } _Join[list,delim,current,index:out] { [list]Next[index] { out <- _Join[list, delim, [[current]Append[delim]]Append[String[[list]Index[~]]], ~] }{ out <- current } } Join[list,delim:out] { [list]First { out <- _Join[list, delim, String[[list]Index[~]], ~] }{ out <- "" } } Starts With[thing,starts with:out] { out <- [[thing]Slice[[starts with]Length]] = [starts with] } Ends With[thing,ends with:out] { ,compare <- [thing]Slice[ [[thing]Length] - [[ends with]Length] ] out <- [compare] = [ends with] } If@String[str:yes,no] { yes,no <- If[[str]Length] } If@String Cat[str:yes,no] { yes,no <- If[[str]Length] } If@String Slice[str:yes,no] { yes,no <- If[[str]Length] } _Split[list,string,delim:out] { ,,rest <- [string]Partition[delim] { out <- _Split[[list]Append[~], rest, delim] } {} {} { out <- [list]Append[string] } } Split[string,delim:out] { If[string] { out <- _Split[(),string,delim] } { out <- () } } In[needle,haystack:out] { If[haystack] { out <- If[[[haystack]Slice[Length[needle]]]=[needle]] {} { [haystack]Slice[1] {} { out <- [needle]In[~] } } }{ out <- No } } Left Trim[string,trim:trimmed] { If[ [[string]Length] > [0] ] { first,rest <- [string]Slice[1] If[ [first]In[trim] ] { trimmed <- Left Trim[rest, trim] }{ trimmed <- string } }{ trimmed <- string } } Right Trim[string,trim:trimmed] { If[ [[string]Length] > [0] ] { rest,last <- [string]Slice[ [[string]Length] - [1]] If[ [last]In[trim] ] { trimmed <- Right Trim[rest, trim] }{ trimmed <- string } }{ trimmed <- string } } Trim[string,trim:trimmed] { left <- Left Trim[string, trim] trimmed <- Right Trim[left, trim] } Contains[haystack,needle:out] { [haystack]Partition[needle] { out <- Yes } {} {} { out <- No } } After[text,prefix:after,not found] { If[[text]Starts With[prefix]] { ,after <- [text]Slice[[prefix]Length] }{ not found <- text } }