core :: FlatString :: defaultinit
# Immutable strings of characters.
abstract class FlatString
super FlatText
super String
# Index at which `self` begins in `_items`, inclusively
redef var first_byte is noinit
redef fun chars do return new FlatStringCharView(self)
redef fun bytes do return new FlatStringByteView(self)
redef fun to_cstring do
var blen = _byte_length
var new_items = new CString(blen + 1)
_items.copy_to(new_items, blen, _first_byte, 0)
new_items[blen] = 0
return new_items
end
redef fun reversed do
var b = new FlatBuffer.with_capacity(_byte_length + 1)
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
return s
end
redef fun fast_cstring do return _items.fast_cstring(_first_byte)
redef fun substring(from, count)
do
if count <= 0 then return ""
if from < 0 then
count += from
if count <= 0 then return ""
from = 0
end
var ln = _length
if (count + from) > ln then count = ln - from
if count <= 0 then return ""
var end_index = from + count - 1
return substring_impl(from, count, end_index)
end
private fun substring_impl(from, count, end_index: Int): String do
var cache = _position
var dfrom = (cache - from).abs
var dend = (end_index - from).abs
var bytefrom: Int
var byteto: Int
if dfrom < dend then
bytefrom = char_to_byte_index(from)
byteto = char_to_byte_index(end_index)
else
byteto = char_to_byte_index(end_index)
bytefrom = char_to_byte_index(from)
end
var its = _items
byteto += its.length_of_char_at(byteto) - 1
var s = new FlatString.full(its, byteto - bytefrom + 1, bytefrom, count)
return s
end
redef fun empty do return "".as(FlatString)
redef fun to_upper
do
var outstr = new FlatBuffer.with_capacity(self._byte_length + 1)
var mylen = _length
var pos = 0
while pos < mylen do
outstr.add(chars[pos].to_upper)
pos += 1
end
return outstr.to_s
end
redef fun to_lower
do
var outstr = new FlatBuffer.with_capacity(self._byte_length + 1)
var mylen = _length
var pos = 0
while pos < mylen do
outstr.add(chars[pos].to_lower)
pos += 1
end
return outstr.to_s
end
redef fun output
do
for i in chars do i.output
end
##################################################
# String Specific Methods #
##################################################
# Low-level creation of a new string with minimal 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 new with_infos(items: CString, byte_length, from: Int)
do
var len = items.utf8_length(from, byte_length)
if byte_length == len then return new ASCIIFlatString.full_data(items, byte_length, from, len)
return new UnicodeFlatString.full_data(items, byte_length, from, len)
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 new full(items: CString, byte_length, from, length: Int)
do
if byte_length == length then return new ASCIIFlatString.full_data(items, byte_length, from, length)
return new UnicodeFlatString.full_data(items, byte_length, from, length)
end
redef fun ==(other)
do
if not other isa FlatText then return super
if self.object_id == other.object_id then return true
var my_length = _byte_length
if other._byte_length != my_length then return false
var my_index = _first_byte
var its_index = other.first_byte
var last_iteration = my_index + my_length
var its_items = other._items
var my_items = self._items
while my_index < last_iteration do
if my_items[my_index] != its_items[its_index] then return false
my_index += 1
its_index += 1
end
return true
end
redef fun <(other)
do
if not other isa FlatText then return super
if self.object_id == other.object_id then return false
var myits = _items
var itsits = other._items
var mbt = _byte_length
var obt = other.byte_length
var minln = if mbt < obt then mbt else obt
var mst = _first_byte
var ost = other.first_byte
for i in [0 .. minln[ do
var my_curr_char = myits[mst]
var its_curr_char = itsits[ost]
if my_curr_char > its_curr_char then return false
if my_curr_char < its_curr_char then return true
mst += 1
ost += 1
end
return mbt < obt
end
redef fun +(o) do
var s = o.to_s
var slen = s.byte_length
var mlen = _byte_length
var nlen = mlen + slen
var mits = _items
var mifrom = _first_byte
if s isa FlatText then
var sits = s._items
var sifrom = s.first_byte
var ns = new CString(nlen + 1)
mits.copy_to(ns, mlen, mifrom, 0)
sits.copy_to(ns, slen, sifrom, mlen)
return new FlatString.full(ns, nlen, 0, _length + o.length)
else
abort
end
end
redef fun *(i) do
var mybtlen = _byte_length
var new_byte_length = mybtlen * i
var mylen = _length
var newlen = mylen * i
var its = _items
var fb = _first_byte
var ns = new CString(new_byte_length + 1)
ns[new_byte_length] = 0
var offset = 0
while i > 0 do
its.copy_to(ns, mybtlen, fb, offset)
offset += mybtlen
i -= 1
end
return new FlatString.full(ns, new_byte_length, 0, newlen)
end
redef fun hash
do
if hash_cache == null then
# djb2 hash algorithm
var h = 5381
var i = _first_byte
var my_items = _items
var max = last_byte
while i <= max do
h = (h << 5) + h + my_items[i].to_i
i += 1
end
hash_cache = h
end
return hash_cache.as(not null)
end
redef fun substrings do return new FlatSubstringsIter(self)
end
lib/core/text/flat.nit:408,1--659,3