protected fun first_byte: Int do return 0
# Last byte of the NativeString
- protected fun last_byte: Int do return _bytelen - 1
+ protected fun last_byte: Int do return first_byte + _bytelen - 1
# Cache of the latest position (char) explored in the string
var position: Int = 0
# Index of the character `index` in `_items`
fun char_to_byte_index(index: Int): Int do
- var ln = length
- assert index >= 0
- assert index < ln
+ var dpos = index - _position
+ var b = _bytepos
+
+ if dpos == 0 then return b
+ if dpos == 1 then
+ b += _items.length_of_char_at(b)
+ _bytepos = b
+ _position = index
+ return b
+ end
+ if dpos == -1 then
+ b = _items.find_beginning_of_char_at(b - 1)
+ _bytepos = b
+ _position = index
+ return b
+ end
+ var ln = _length
var pos = _position
# Find best insertion point
var delta_begin = index
var ns_i: Int
var my_i: Int
- if min == delta_begin then
- ns_i = first_byte
- my_i = 0
- else if min == delta_cache then
+ if min == delta_cache then
ns_i = _bytepos
my_i = pos
+ else if min == delta_begin then
+ ns_i = first_byte
+ my_i = 0
else
ns_i = its.find_beginning_of_char_at(last_byte)
- my_i = length - 1
+ my_i = _length - 1
end
ns_i = its.char_to_byte_index_cached(index, my_i, ns_i)
end
pos += 1
end
- var s = new FlatString.with_infos(nits, nlen, 0, nlen - 1)
+ var s = new FlatString.with_infos(nits, nlen, 0)
return s
end
end
pos += 1
end
- return nns.to_s_with_length(nlen)
+ return nns.to_s_unsafe(nlen)
end
- redef fun [](index) do return _items.char_at(char_to_byte_index(index))
+ redef fun [](index) do
+ assert index >= 0 and index < _length
+ return fetch_char_at(index)
+ end
+
+ # Gets a `Char` at `index` in `self`
+ #
+ # WARNING: Use at your own risks as no bound-checking is done
+ fun fetch_char_at(index: Int): Char do
+ var i = char_to_byte_index(index)
+ var items = _items
+ var b = items[i]
+ if b & 0x80u8 == 0x00u8 then return b.ascii
+ return items.char_at(i)
+ end
# If `self` contains only digits and alpha <= 'f', return the corresponding integer.
#
# Index at which `self` begins in `_items`, inclusively
redef var first_byte is noinit
- # Index at which `self` ends in `_items`, inclusively
- redef var last_byte is noinit
-
redef var chars = new FlatStringCharView(self) is lazy
redef var bytes = new FlatStringByteView(self) is lazy
- redef var length is lazy do
- if _bytelen == 0 then return 0
- return _items.utf8_length(_first_byte, _last_byte)
- end
-
redef var to_cstring is lazy do
var blen = _bytelen
var new_items = new NativeString(blen + 1)
return new_items
end
- redef fun reversed
- do
+ redef fun reversed do
var b = new FlatBuffer.with_capacity(_bytelen + 1)
- for i in [length - 1 .. 0].step(-1) do
- b.add self[i]
+ var i = _length - 1
+ while i >= 0 do
+ b.add self.fetch_char_at(i)
+ i -= 1
end
var s = b.to_s.as(FlatString)
- s.length = self.length
+ s._length = self._length
return s
end
do
var outstr = new FlatBuffer.with_capacity(self._bytelen + 1)
- var mylen = length
+ var mylen = _length
var pos = 0
while pos < mylen do
do
var outstr = new FlatBuffer.with_capacity(self._bytelen + 1)
- var mylen = length
+ var mylen = _length
var pos = 0
while pos < mylen do
#
# `_items` will be used as is, without copy, to retrieve the characters of the string.
# Aliasing issues is the responsibility of the caller.
- private init with_infos(items: NativeString, bytelen, from, to: Int)
+ private init with_infos(items: NativeString, bytelen, from: Int)
do
self._items = items
self._bytelen = bytelen
_first_byte = from
- _last_byte = to
_bytepos = from
+ _length = _items.utf8_length(_first_byte, last_byte)
end
# Low-level creation of a new string with all the data.
#
# `_items` will be used as is, without copy, to retrieve the characters of the string.
# Aliasing issues is the responsibility of the caller.
- private init full(items: NativeString, bytelen, from, to, length: Int)
+ private init full(items: NativeString, bytelen, from, length: Int)
do
self._items = items
- self.length = length
+ self._length = length
self._bytelen = bytelen
_first_byte = from
- _last_byte = to
_bytepos = from
end
var ns = new NativeString(nlen + 1)
mits.copy_to(ns, mlen, mifrom, 0)
sits.copy_to(ns, slen, sifrom, mlen)
- return new FlatString.full(ns, nlen, 0, nlen - 1, length + o.length)
+ return new FlatString.full(ns, nlen, 0, _length + o.length)
else
abort
end
redef fun *(i) do
var mybtlen = _bytelen
var new_bytelen = mybtlen * i
- var mylen = length
+ var mylen = _length
var newlen = mylen * i
var its = _items
var fb = _first_byte
offset += mybtlen
i -= 1
end
- return new FlatString.full(ns, new_bytelen, 0, new_bytelen - 1, newlen)
+ return new FlatString.full(ns, new_bytelen, 0, newlen)
end
var i = _first_byte
var my_items = _items
- var max = _last_byte
+ var max = last_byte
while i <= max do
h = (h << 5) + h + my_items[i].to_i
var curr_pos: Int
- init do max = target.length - 1
+ init do max = target._length - 1
redef fun is_ok do return curr_pos <= max
curr_pos += tgt._first_byte
end
- redef fun is_ok do return curr_pos <= target._last_byte
+ redef fun is_ok do return curr_pos <= target.last_byte
redef fun item do return target_items[curr_pos]
redef fun [](index)
do
- # Check that the index (+ _first_byte) is not larger than _last_byte
+ # Check that the index (+ _first_byte) is not larger than last_byte
# In other terms, if the index is valid
- assert index >= 0
- var target = self.target
+ var target = _target
+ assert index >= 0 and index < target._bytelen
var ind = index + target._first_byte
- assert ind <= target._last_byte
return target._items[ind]
end
redef var bytes = new FlatBufferByteView(self) is lazy
- redef var length = 0
-
private var char_cache: Int = -1
private var byte_cache: Int = -1
redef fun []=(index, item)
do
- assert index >= 0 and index <= length
+ assert index >= 0 and index <= _length
if written then reset
is_dirty = true
- if index == length then
+ if index == _length then
add item
return
end
lshift_bytes(ip + clen, -size_diff)
end
_bytelen += size_diff
- bytepos += size_diff
it.set_char_at(ip, item)
end
enlarge(bt + clen)
_items.set_char_at(bt, c)
_bytelen += clen
- length += 1
+ _length += 1
end
redef fun clear do
is_dirty = true
if written then reset
_bytelen = 0
- length = 0
+ _length = 0
end
redef fun empty do return new Buffer
written = true
var bln = _bytelen
if bln == 0 then _items = new NativeString(1)
- return new FlatString.full(_items, bln, 0, bln - 1, length)
+ return new FlatString.full(_items, bln, 0, _length)
end
redef fun to_cstring
var bln = _bytelen
var new_native = new NativeString(bln + 1)
new_native[bln] = 0u8
- if length > 0 then _items.copy_to(new_native, bln, 0, 0)
+ if _length > 0 then _items.copy_to(new_native, bln, 0, 0)
real_items = new_native
is_dirty = false
end
self._items = items
self.capacity = capacity
self._bytelen = bytelen
- self.length = length
+ self._length = length
end
# Create a new string copied from `s`.
for i in substrings do i.as(FlatString)._items.copy_to(_items, i._bytelen, 0, 0)
end
_bytelen = s.bytelen
- length = s.length
+ _length = s.length
_capacity = _bytelen
written = true
end
return
end
_bytelen = nln
- length += s.length
+ _length += s.length
end
# Copies the content of self in `dest`
do
assert count >= 0
if from < 0 then from = 0
- if (from + count) > length then count = length - from
+ 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)
redef fun times(repeats)
do
var bln = _bytelen
- var x = new FlatString.full(_items, bln, 0, bln - 1, length)
+ var x = new FlatString.full(_items, bln, 0, _length)
for i in [1 .. repeats[ do
append(x)
end
redef fun upper
do
if written then reset
- for i in [0 .. length[ do self[i] = self[i].to_upper
+ 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
+ for i in [0 .. _length[ do self[i] = self[i].to_lower
end
end
redef fun append(s)
do
var s_length = s.length
- if target.capacity < s.length then enlarge(s_length + target.length)
+ if target.capacity < s.length then enlarge(s_length + target._length)
for i in s do target.add i
end
var curr_pos: Int
- init do max = target.length - 1
+ init do max = target._length - 1
redef fun index do return curr_pos
end
redef fun to_s_full(bytelen, unilen) do
- return new FlatString.full(self, bytelen, 0, bytelen - 1, unilen)
+ return new FlatString.full(self, bytelen, 0, unilen)
+ end
+
+ redef fun to_s_unsafe(len) do
+ if len == null then len = cstring_length
+ return new FlatString.with_infos(self, len, 0)
end
# Returns `self` as a new String.
if r.items != self then return r
var new_self = new NativeString(length + 1)
copy_to(new_self, length, 0, 0)
- var str = new FlatString.with_infos(new_self, length, 0, length - 1)
+ var str = new FlatString.with_infos(new_self, length, 0)
new_self[length] = 0u8
str.to_cstring = new_self
return str
var end_length = len
var pos = 0
var chr_ln = 0
- while pos < len do
+ var rem = len
+ while rem > 0 do
+ while rem >= 4 do
+ var i = fetch_4_chars(pos)
+ if i & 0x80808080 != 0 then break
+ pos += 4
+ chr_ln += 4
+ rem -= 4
+ end
+ if rem == 0 then break
var b = self[pos]
+ if b & 0x80u8 == 0x00u8 then
+ pos += 1
+ chr_ln += 1
+ rem -= 1
+ continue
+ end
var nxst = length_of_char_at(pos)
var ok_st: Bool
if nxst == 1 then
replacements.add pos
end_length += 2
pos += 1
+ rem -= 1
chr_ln += 1
continue
end
end_length += 2
pos += 1
chr_ln += 1
+ rem -= 1
continue
end
- pos += c.u8char_len
+ var clen = c.u8char_len
+ pos += clen
+ rem -= clen
chr_ln += 1
end
var ret = self
end
copy_to(ret, len - old_repl, old_repl, off)
end
- return new FlatString.full(ret, end_length, 0, end_length - 1, chr_ln)
+ return new FlatString.full(ret, end_length, 0, chr_ln)
end
# Sets the next bytes at position `pos` to the value of `c`, encoded in UTF-8
var ns = new NativeString(nslen + 1)
ns[nslen] = 0u8
native_int_to_s(ns, nslen + 1)
- return new FlatString.full(ns, nslen, 0, nslen - 1, nslen)
+ return new FlatString.full(ns, nslen, 0, nslen)
end
end
# Fast implementation
redef fun plain_to_s
do
- var l = length
+ var l = _length
if l == 0 then return ""
var its = _items.as(not null)
var first = its[0]
end
i += 1
end
- return new FlatString.with_infos(ns, sl, 0, sl - 1)
+ return new FlatString.with_infos(ns, sl, 0)
end
end
end
i += 1
end
- return new FlatString.with_infos(ns, sl, 0, sl - 1)
+ return new FlatString.with_infos(ns, sl, 0)
end
end