if iter.item.ascii > 32 then break
iter.next
end
- if iter.index == length then return self.empty
+ if iter.index < 0 then return self.empty
return self.substring(0, iter.index + 1)
end
redef fun to_cstring: NativeString
do
- if real_items != null then return real_items.as(not null)
- if index_from > 0 or index_to != items.cstring_length - 1 then
+ if real_items != null then
+ return real_items.as(not null)
+ else
var newItems = calloc_string(length + 1)
self.items.copy_to(newItems, length, index_from, 0)
newItems[length] = '\0'
self.real_items = newItems
return newItems
end
- return items
end
redef fun ==(other)
curr_pos = pos + tgt.index_from
end
- redef fun is_ok do return curr_pos >= 0
+ redef fun is_ok do return curr_pos >= target.index_from
redef fun item do return target_items[curr_pos]
# Specific implementations MUST set this to `true` in order to invalidate caches
protected var is_dirty = true
+ # Copy-On-Write flag
+ #
+ # If the `Buffer` was to_s'd, the next in-place altering
+ # operation will cause the current `Buffer` to be re-allocated.
+ #
+ # The flag will then be set at `false`.
+ protected var written = false
+
# Modifies the char contained at pos `index`
#
# DEPRECATED : Use self.chars.[]= instead
redef fun substrings do return new FlatSubstringsIter(self)
+ # Re-copies the `NativeString` 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 NativeString(capacity)
+ items.copy_to(nns, length, 0, 0)
+ items = nns
+ written = false
+ end
+
redef fun [](index)
do
assert index >= 0
add(item)
return
end
+ if written then reset
assert index >= 0 and index < length
items[index] = item
end
redef fun clear do
is_dirty = true
+ if written then reset
length = 0
end
var c = capacity
if cap <= c then return
while c <= cap do c = c * 2 + 2
+ # The COW flag can be set at false here, since
+ # it does a copy of the current `Buffer`
+ written = false
var a = calloc_string(c+1)
if length > 0 then items.copy_to(a, length, 0, 0)
items = a
redef fun to_s: String
do
- return to_cstring.to_s_with_length(length)
+ written = true
+ return new FlatString.with_infos(items, length, 0, length - 1)
end
redef fun to_cstring
redef fun reverse
do
+ written = false
var ns = calloc_string(capacity)
var si = length - 1
var ni = 0
redef fun upper
do
+ if written then reset
var it = items
var id = length - 1
while id >= 0 do
redef fun lower
do
+ if written then reset
var it = items
var id = length - 1
while id >= 0 do
else
for j in tmp.substrings do
var s = j.as(FlatString)
- s.items.copy_to(ns, tpl, s.index_from, off)
- off += tpl
+ var slen = s.length
+ s.items.copy_to(ns, slen, s.index_from, off)
+ off += slen
end
end
i += 1