//[of]:imports //[c] import "base/types" import "base/memory" import "base/memory-allocator" import "text/string" //[cf] //[of]:structures //[c] public struct string buffer private p: string private used: size private buffer size: size end //[cf] //[c] //[of]:module initialization //[of]:initialize string buffer //[c] public func initialize string buffer the buffer1 = allocate memory (default size): string the buffer1 size = default size the buffer1 owner = nil the buffer2 = allocate memory (default size): string the buffer2 size = default size the buffer2 owner = nil end //[cf] //[of]:release string buffer //[c] public func release string buffer free memory (the buffer1) free memory (the buffer2) end //[cf] //[cf] //[of]:initialize - release //[of]:string buffer //[c] public equ string buffer (return s: string buffer) = initialize (s) //[cf] //[of]:temp string buffer //[c]Initializes a temporary buffer //[c]The module keep a string buffer allocated permanently //[c]to be reused. It reduces the number of allocations / deallocations. //[c] public func temp string buffer (return s: string buffer) if is nil (the buffer1 owner) p (s) = the buffer1 used (s) = 0 buffer size (s) = the buffer1 size the buffer1 owner = s elsif is nil (the buffer2 owner) p (s) = the buffer2 used (s) = 0 buffer size (s) = the buffer2 size the buffer2 owner = s else initialize (s) end end //[cf] //[c] //[of]:initialize (s) //[c] public func initialize (s: string buffer) p (s) = allocate memory (default size) : string used (s) = 0 buffer size (s) = default size end //[cf] //[of]:release (s) //[c]Releases the buffer //[c] public func release (s: string buffer) if s == the buffer1 owner the buffer1 = p (s) the buffer1 size = buffer size (s) the buffer1 owner = nil elsif s == the buffer2 owner the buffer2 = p (s) the buffer2 size = buffer size (s) the buffer2 owner = nil else free memory (p (s)) end end //[cf] //[cf] //[of]:conversion //[of]:new string (s) //[c]Create a new string from the content of the string buffer //[c] public func new string (s: string buffer) return new string (as string (s)) end //[cf] //[of]:as string (s) //[c]Convert the buffer to a string //[c] public func as string (s: string buffer) reserve (s, 1) p(s)[used(s)] = \0 return p (s) end //[cf] //[cf] //[of]:adding - removing //[of]:buffer (s, size) //[c]Appends an unitialized area //[c]Use this method if you want to drop a text yourself //[c]One more byte is automatically reserved for a terminating nul //[c]char. //[c] public func buffer (s: string buffer, size: size) reserve (s, size) def p = p (s) + used (s) used (s) += size return p end //[cf] //[c] //[of]:printf (string buffer, format, c1) public func printf (s: string buffer, fmt: string, c1: char) def values : [1] local printf arg values [0].char = c1 printf (s, fmt, values) end //[cf] //[of]:printf (string buffer, format, i1) public func printf (s: string buffer, fmt: string, i1: dword) def values : [1] local printf arg values [0].dword = i1 printf (s, fmt, values) end //[cf] //[of]:printf (string buffer, format, i1, i2) public func printf (s: string buffer, fmt: string, i1: dword, i2: dword) def values : [2] local printf arg values [0].dword = i1 values [1].dword = i2 printf (s, fmt, values) end //[cf] //[of]:printf (string buffer, format, s1) public func printf (s: string buffer, fmt: string, s1: string) def values : [1] local printf arg values [0].string = s1 printf (s, fmt, values) end //[cf] //[of]:printf (string buffer, format, s1, s2) public func printf (s: string buffer, fmt: string, s1: string, s2: string) def values : [2] local printf arg values [0].string = s1 values [1].string = s2 printf (s, fmt, values) end //[cf] //[of]:printf (string buffer, format, values) public func printf (s: string buffer, fmt: string, values: [] local printf arg) remove all (s) appendf (s, fmt, values) end //[cf] //[c] //[of]:appendf (string buffer, format, c1) //[c] public func appendf (s: string buffer, fmt: string, c1: char) def values : [1] local printf arg values [0].char = c1 appendf (s, fmt, values) end //[cf] //[of]:appendf (string buffer, format, i1) //[c] public func appendf (s: string buffer, fmt: string, i1: dword) def values : [1] local printf arg values [0].dword = i1 appendf (s, fmt, values) end //[cf] //[of]:appendf (string buffer, format, i1, i2) //[c] public func appendf (s: string buffer, fmt: string, i1: dword, i2: dword) def values : [2] local printf arg values [0].dword = i1 values [1].dword = i2 appendf (s, fmt, values) end //[cf] //[of]:appendf (string buffer, format, s1) //[c] public func appendf (s: string buffer, fmt: string, s1: string) def values : [1] local printf arg values [0].string = s1 appendf (s, fmt, values) end //[cf] //[of]:appendf (string buffer, format, s1, s2) //[c] public func appendf (s: string buffer, fmt: string, s1: string, s2: string) def values : [2] local printf arg values [0].string = s1 values [1].string = s2 appendf (s, fmt, values) end //[cf] //[of]:appendf (string buffer, format, values) //[c] public union printf arg string: string int: int dword: dword char: char end public func appendf (s: string buffer, fmt: string, values: [] local printf arg) def arg = values def p = fmt def c: char repeat c= p++[] if is nul (c) break elsif c==$% c = p++[] if c==$s s << (arg++[].string) elsif c==$i s << (arg++[].int) elsif c==$u s << (arg++[].dword) elsif c==$c s << (arg++[].char) else s << c end else s << c end end end //[cf] //[c] //[of]:append (s, char) //[c]Appends a single char //[c] public func append (s: string buffer, c: char) reserve (s, 1) p (s) [used (s)] = c ++ used (s) return s end //[cf] //[of]:append (s, string) //[c]Appends a string //[c] public func append (s: string buffer, str: string) def size = size (str) reserve (s, size) copy (p (s) + used (s), str, size) used (s) += size return s end //[cf] //[of]:append (s, string, size) //[c]Appends a sub string //[c] public func append (s: string buffer, str: string, size: size) reserve (s, size) copy (p (s) + used (s), str, size) used (s) += size return s end //[cf] //[of]:append (s, string buffer) //[c]Appends a string //[c] public func append (s: string buffer, str: string buffer) def size = size (str) reserve (s, size) copy (p (s) + used (s), base (str), size) used (s) += size return s end //[cf] //[of]:append (s, dword) //[c]Appends an integer //[c] public func append (s: string buffer, i: dword) def buf: [12] char def p = buf + 11 p[] = \0 if i== 0 (--p)[] = $0 else while i<>0 def r = i % 10 (--p)[] = $0 + r:char i /= 10 end end return append(s, p) end //[cf] //[of]:append (s, int) //[c]Appends an integer //[c] public func append (s: string buffer, i: int) if i < 0 append (s, $-) i -! end return append (s, i:dword) end //[cf] //[of]:append hexa (s, dword) //[c]Appends an integer //[c] public func append hexa (s: string buffer, i: dword) def buf: [12] char def p = buf + 11 p[] = \0 if i== 0 (--p)[] = $0 else while i<>0 def r = i & 15 (--p)[] = ((r<10) -> ($0 + r:char), ($A + (r-10):char)) i >>= 4 end end return append(s, p) end //[cf] //[c] //[of]:s << char //[c] public equ @shl (s:string buffer, c: char) = append (s, c) //[cf] //[of]:s << string //[c] public equ @shl (s:string buffer, str: string) = append (s, str) //[cf] //[of]:s << string buffer //[c] public equ @shl (s:string buffer, str: string buffer) = append (s, str) //[cf] //[of]:s << dword //[c] public equ @shl (s:string buffer, i: dword) = append (s, i) //[cf] //[of]:s << int //[c] public equ @shl (s:string buffer, i: int) = append (s, i) //[cf] //[c] //[of]:remove all (s) //[c]Removes content //[c] //[c] The buffer is not free in order to optimize the recycling of this //[c] string buffer. //[c] public equ remove all (s: string buffer) = used (s) = 0 //[cf] //[of]:remove (s, start, len) //[c]Removes a substring //[c] public func remove (s: string buffer, start: dword, len: dword) def limit = start + len // move the end to overlap the range to be removed move (p(s)+start, p(s)+limit, used(s)-limit) // update the used chars used (s) -= len end //[cf] //[cf] //[of]:accessing //[of]:base (s) //[c] public equ base (s: string buffer) = p (s) //[cf] //[of]:size (s) //[c] public equ size (s: string buffer) = used (s) //[cf] //[of]:s [int] //[c] public equ @at (s: string buffer, i: int) = p(s)[i] //[cf] //[of]:set size (s, size) //[c]Truncate the buffer. The given size must be lesser //[c]than the current size. //[c] public equ set size (s: string buffer, size: size) = used (s) = size //[cf] //[cf] //[of]:testing //[of]:is empty (s) //[c] public equ is empty (s: string buffer) = used (s) == 0 //[cf] //[of]:not empty (s) //[c] public equ not empty (s: string buffer) = used (s) <> 0 //[cf] //[cf] //[c] //[of]:private //[of]:reserve (s, size) //[c]Reserves a sufficient space //[c] func reserve (s: string buffer, l: size) // we always must have one more char if used (s) + l + 1 <= buffer size (s) return end // compute new size def new size = (used (s) + l + 1) * 5 / 4 // allocate new buffer def q = allocate memory (new size): string // copy the old buffer into the new one copy (q, p (s), used (s)) // free the old buffer free memory (p (s)) // update object buffer size (s) = new size p (s) = q end //[cf] //[of]:constants //[c] equ default size = 4096 //[cf] //[of]:temporary buffers //[c] def the buffer1 : string def the buffer1 size : size def the buffer1 owner : string buffer def the buffer2 : string def the buffer2 size : size def the buffer2 owner : string buffer //[cf] //[cf] //[c]