core :: FlatBuffer :: defaultinit
# Mutable strings of characters.
class FlatBuffer
super FlatText
super Buffer
redef fun chars do return new FlatBufferCharView(self)
redef fun bytes do return new FlatBufferByteView(self)
private var capacity = 0
redef fun fast_cstring do return _items.fast_cstring(0)
redef fun substrings do return new FlatSubstringsIter(self)
# Re-copies the `CString` into a new one and sets it as the new `Buffer`
#
# This happens when an operation modifies the current `Buffer` and
# the Copy-On-Write flag `written` is set at true.
private fun reset do
var nns = new CString(capacity)
if _byte_length != 0 then _items.copy_to(nns, _byte_length, 0, 0)
_items = nns
written = false
end
# Shifts the content of the buffer by `len` bytes to the right, starting at byte `from`
#
# Internal only, does not modify _byte_length or length, this is the caller's responsability
private fun rshift_bytes(from: Int, len: Int) do
var oit = _items
var nit = _items
var bt = _byte_length
if bt + len > capacity then
capacity = capacity * 2 + 2
nit = new CString(capacity)
oit.copy_to(nit, 0, 0, from)
end
oit.copy_to(nit, bt - from, from, from + len)
end
# Shifts the content of the buffer by `len` bytes to the left, starting at `from`
#
# Internal only, does not modify _byte_length or length, this is the caller's responsability
private fun lshift_bytes(from: Int, len: Int) do
var it = _items
it.copy_to(it, _byte_length - from, from, from - len)
end
redef fun []=(index, item)
do
assert index >= 0 and index <= _length
if written then reset
if index == _length then
add item
return
end
var it = _items
var ip = it.char_to_byte_index(index)
var c = it.char_at(ip)
var clen = c.u8char_len
var itemlen = item.u8char_len
var size_diff = itemlen - clen
if size_diff > 0 then
rshift_bytes(ip + clen, size_diff)
else if size_diff < 0 then
lshift_bytes(ip + clen, -size_diff)
end
_byte_length += size_diff
it.set_char_at(ip, item)
end
redef fun insert(s, pos) do
assert pos >= 0 and pos <= length
if pos == length then
append s
return
end
var slen = s.byte_length
enlarge(byte_length + slen)
var it = _items
var shpos = it.char_to_byte_index(pos)
rshift_bytes(shpos, slen)
s.copy_to_native(it, slen, 0, shpos)
length += s.length
byte_length += slen
end
redef fun insert_char(c, pos) do
assert pos >= 0 and pos <= length
if pos == length then
add c
return
end
var clen = c.u8char_len
enlarge(byte_length + clen)
var it = _items
var shpos = it.char_to_byte_index(pos)
rshift_bytes(shpos, clen)
it.set_char_at(shpos, c)
length += 1
byte_length += clen
end
redef fun add(c)
do
if written then reset
var clen = c.u8char_len
var bt = _byte_length
enlarge(bt + clen)
_items.set_char_at(bt, c)
_byte_length += clen
_length += 1
end
redef fun clear do
_byte_length = 0
_length = 0
if written then
_capacity = 16
reset
end
end
redef fun empty do return new Buffer
redef fun enlarge(cap)
do
var c = capacity
if cap <= c then return
if c <= 16 then c = 16
while c <= cap do c = c * 2
# The COW flag can be set at false here, since
# it does a copy of the current `Buffer`
written = false
var bln = _byte_length
var a = new CString(c)
if bln > 0 then
var it = _items
if bln > 0 then it.copy_to(a, bln, 0, 0)
end
_items = a
capacity = c
end
redef fun to_s
do
written = true
var bln = _byte_length
if bln == 0 then _items = new CString(1)
return new FlatString.full(_items, bln, 0, _length)
end
redef fun to_cstring
do
var bln = _byte_length
var new_native = new CString(bln + 1)
new_native[bln] = 0
if _length > 0 then _items.copy_to(new_native, bln, 0, 0)
return new_native
end
# Create a new empty string.
init do end
# Low-level creation a new buffer with given data.
#
# `_items` will be used as is, without copy, to store the characters of the buffer.
# Aliasing issues is the responsibility of the caller.
#
# If `_items` is shared, `written` should be set to true after the creation
# so that a modification will do a copy-on-write.
private init with_infos(items: CString, capacity, byte_length, length: Int)
do
self._items = items
self.capacity = capacity
self._byte_length = byte_length
self._length = length
end
# Create a new string copied from `s`.
init from(s: Text)
do
_items = new CString(s.byte_length)
for i in s.substrings do i._items.copy_to(_items, i._byte_length, first_byte, 0)
_byte_length = s.byte_length
_length = s.length
_capacity = _byte_length
end
# Create a new empty string with a given capacity.
init with_capacity(cap: Int)
do
assert cap >= 0
_items = new CString(cap)
capacity = cap
_byte_length = 0
end
redef fun append(s)
do
if s.is_empty then return
var sl = s.byte_length
var nln = _byte_length + sl
enlarge(nln)
if s isa FlatText then
s._items.copy_to(_items, sl, s.first_byte, _byte_length)
else
for i in s.substrings do append i
return
end
_byte_length = nln
_length += s.length
end
# Copies the content of self in `dest`
fun copy(start: Int, len: Int, dest: Buffer, new_start: Int)
do
var self_chars = self.chars
var dest_chars = dest.chars
for i in [0..len-1] do
dest_chars[new_start+i] = self_chars[start+i]
end
end
redef fun substring(from, count)
do
assert count >= 0
if from < 0 then from = 0
if (from + count) > _length then count = _length - from
if count <= 0 then return new Buffer
var its = _items
var bytefrom = its.char_to_byte_index(from)
var byteto = its.char_to_byte_index(count + from - 1)
byteto += its.char_at(byteto).u8char_len - 1
var byte_length = byteto - bytefrom + 1
var r_items = new CString(byte_length)
its.copy_to(r_items, byte_length, bytefrom, 0)
return new FlatBuffer.with_infos(r_items, byte_length, byte_length, count)
end
redef fun append_substring_impl(s, from, length) do
if length <= 0 then return
if not s isa FlatText then
super
return
end
var sits = s._items
var bytest = s.char_to_byte_index(from)
var bytend = s.char_to_byte_index(from + length - 1)
var btln = bytend - bytest + sits.char_at(bytend).u8char_len
enlarge(btln + _byte_length)
sits.copy_to(_items, btln, bytest, _byte_length)
_byte_length += btln
_length += length
end
redef fun remove_at(p, len) do
if len == null then len = 1
if len == 0 then return
var its = _items
var bst = char_to_byte_index(p)
var bend = char_to_byte_index(p + len - 1)
bend += its.char_at(bend).u8char_len
var blen = bend - bst
lshift_bytes(bend, bend - bst)
byte_length -= blen
length -= len
end
redef fun reverse
do
written = false
var ns = new FlatBuffer.with_capacity(capacity)
for i in chars.reverse_iterator do ns.add i
_items = ns._items
end
redef fun times(repeats)
do
var bln = _byte_length
var x = new FlatString.full(_items, bln, 0, _length)
for i in [1 .. repeats[ do
append(x)
end
end
redef fun upper
do
if written then reset
for i in [0 .. _length[ do self[i] = self[i].to_upper
end
redef fun lower
do
if written then reset
for i in [0 .. _length[ do self[i] = self[i].to_lower
end
end
lib/core/text/flat.nit:865,1--1163,3