//[of]:imports //[c] import "base/types" import "base/memory" import "base/memory-allocator" import "text/string" //[cf] //[of]:structures //[c] public struct memory buffer private p: [] byte private used: size private buffer size: size end //[cf] //[c] //[of]:initialize - release //[of]:memory buffer //[c] public equ memory buffer (return s: memory buffer) = initialize (s) //[cf] //[c] //[of]:initialize (b) //[c] public func initialize (s: memory buffer) p (s) = allocate memory (default size): [] byte used (s) = 0 buffer size (s) = default size end //[cf] //[of]:release (b) //[c] public func release (s: memory buffer) free memory (p (s)) end //[cf] //[cf] //[of]:adding - removing //[of]:buffer (b, size) //[c]Appends a unitialized area //[c] //[c]Use this method if you want to drop a text yourself. //[c]One more byte is automatically reserved for a terminating nul char. //[c] public func buffer (s: memory buffer, size: size) reserve (s, size) def p = p(s) + used(s) used (s) += size return p end //[cf] //[c] //[of]:append (b, buf, size) //[c]Appends a byte array //[c] public func append (s: memory buffer, buf: [] byte, size: size) reserve (s, size) copy (p(s) + used(s), buf, size) used (s) += size return s end //[cf] //[of]:append (b, char) //[c]Appends a single char //[c] public func append (s: memory buffer, c: char) reserve (s, 1) (p(s) + used (s)) : [] char [] = c ++ used (s) return s end //[cf] //[of]:append (b, string) //[c]Appends a string //[c] public func append (s: memory buffer, str: string) def size = size (str) + 1 reserve (s, size) copy (p(s) + used(s), str, size) used (s) += size return s end //[cf] //[of]:append (b, string, size) //[c]Appends a sub string //[c] public func append (s: memory buffer, str: string, size: size) reserve (s, size + 1) copy (p(s) + used(s), str, size) used (s) += size + 1 (p(s) + used (s) - 1) : [] char [] = nul char return s end //[cf] //[of]:append (b, dword) //[c]Appends a dword //[c] public func append (s: memory buffer, i: dword) def size = sizeof dword reserve (s, size) (p(s) + used (s)) : [] dword [] = i used (s) += size return s end //[cf] //[of]:append (b, word) //[c]Appends a word //[c] public func append (s: memory buffer, i: word) def size = sizeof word reserve (s, size) (p(s) + used (s)) : [] word [] = i used (s) += size return s end //[cf] //[of]:append (b, byte) //[c]Appends a byte //[c] public func append (s: memory buffer, i: byte) def size = sizeof byte reserve (s, size) (p(s) + used (s)) : [] byte [] = i used (s) += size return s end //[cf] //[c] //[of]:b << char //[c] public equ @shl (s:memory buffer, c: char) = append (s, c) //[cf] //[of]:b << string //[c] public equ @shl (s:memory buffer, str: string) = append (s, str) //[cf] //[of]:b << dword //[c] public equ @shl (s:memory buffer, i: dword) = append (s, i) //[cf] //[of]:b << word //[c] public equ @shl (s:memory buffer, i: word) = append (s, i) //[cf] //[of]:b << byte //[c] public equ @shl (s:memory buffer, i: byte) = append (s, i) //[cf] //[c] //[of]:remove all (b) //[c] public equ remove all (s: memory buffer) = used (s) = 0 //[cf] //[of]:remove (b, start, len) //[c]Removes a subsequence //[c] public func remove (s: memory buffer, start: int, len: int) 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 (b) public equ base (s: memory buffer) = p (s) //[cf] //[of]:size (b) public equ size (s: memory buffer) = used (s) //[cf] //[of]:b [int] public equ @at (s: memory buffer, i: int) = p(s)[i] //[cf] //[cf] //[c] //[of]:private //[of]:constants //[c] equ default size = 4096 //[cf] //[of]:reserve (b, size) //[c] func reserve (s: memory buffer, l: size) // Reserve a sufficient space // 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): [] byte // 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] //[cf]