import math
import collection
+intrude import collection::array
`{
#include <stdio.h>
return self.chars.iterator
end
- # Is 'c' contained in self ?
- #
- # DEPRECATED : Use self.chars.has instead
- fun has(c: Char): Bool
- do
- return self.chars.has(c)
- end
# Gets an Array containing the chars of self
#
# As with substring, a `from` index < 0 will be replaced by 0
fun substring_from(from: Int): SELFTYPE
do
- if from > self.length then return empty
+ if from >= self.length then return empty
if from < 0 then from = 0
return substring(from, length - from)
end
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
end
end
+ # Escape string used in labels for graphviz
+ #
+ # assert ">><<".escape_to_dot == "\\>\\>\\<\\<"
+ fun escape_to_dot: String
+ do
+ return escape_more_to_c("|\{\}<>")
+ end
+
# Flat representation of self
fun flatten: FlatText is abstract
abstract class FlatText
super Text
- private var items: NativeString
+ # Underlying C-String (`char*`)
+ #
+ # Warning : Might be void in some subclasses, be sure to check
+ # if set before using it.
+ private var items: NativeString is noinit
# Real items, used as cache for to_cstring is called
private var real_items: nullable NativeString = null
fun insert_at(s: String, pos: Int): SELFTYPE is abstract
+ redef fun substrings: Iterator[String] is abstract
+
# Returns a reversed version of self
#
# assert "hello".reversed == "olleh"
return new_str.to_s
end
+
+ # Returns a capitalized `self`
+ #
+ # Letters that follow a letter are lowercased
+ # Letters that follow a non-letter are upcased.
+ #
+ # SEE : `Char::is_letter` for the definition of letter.
+ #
+ # assert "jAVASCRIPT".capitalized == "Javascript"
+ # assert "i am root".capitalized == "I Am Root"
+ # assert "ab_c -ab0c ab\nc".capitalized == "Ab_C -Ab0C Ab\nC"
+ fun capitalized: SELFTYPE do
+ if length == 0 then return self
+
+ var buf = new FlatBuffer.with_capacity(length)
+
+ var curr = chars[0].to_upper
+ var prev = curr
+ buf[0] = curr
+
+ for i in [1 .. length[ do
+ prev = curr
+ curr = self[i]
+ if prev.is_letter then
+ buf[i] = curr.to_lower
+ else
+ buf[i] = curr.to_upper
+ end
+ end
+
+ return buf.to_s
+ end
end
private class FlatSubstringsIter
super String
# Index in _items of the start of the string
- private var index_from: Int
+ private var index_from: Int is noinit
# Indes in _items of the last item of the string
- private var index_to: Int
+ private var index_to: Int is noinit
redef var chars: SequenceRead[Char] = new FlatStringCharView(self)
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
# assert b == "hello world!"
fun lower is abstract
+ # Capitalizes each word in `self`
+ #
+ # Letters that follow a letter are lowercased
+ # Letters that follow a non-letter are upcased.
+ #
+ # SEE: `Char::is_letter` for the definition of a letter.
+ #
+ # var b = new FlatBuffer.from("jAVAsCriPt")"
+ # b.capitalize
+ # assert b == "Javascript"
+ # b = new FlatBuffer.from("i am root")
+ # b.capitalize
+ # assert b == "I Am Root"
+ # b = new FlatBuffer.from("ab_c -ab0c ab\nc")
+ # b.capitalize
+ # assert b == "Ab_C -Ab0C Ab\nC"
+ fun capitalize do
+ if length == 0 then return
+ var c = self[0].to_upper
+ self[0] = c
+ var prev: Char = c
+ for i in [1 .. length[ do
+ prev = c
+ c = self[i]
+ if prev.is_letter then
+ self[i] = c.to_lower
+ else
+ self[i] = c.to_upper
+ end
+ end
+ end
+
redef fun hash
do
if is_dirty then hash_cache = null
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
+ if length == 0 then items = new NativeString(1)
+ 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
fun to_s_with_length(length: Int): FlatString
do
assert length >= 0
- return new FlatString.with_infos(self, length, 0, length - 1)
+ var str = new FlatString.with_infos(self, length, 0, length - 1)
+ return str
end
fun to_s_with_copy: FlatString
var length = cstring_length
var new_self = calloc_string(length + 1)
copy_to(new_self, length, 0, 0)
- return new FlatString.with_infos(new_self, length, 0, length - 1)
+ var str = new FlatString.with_infos(new_self, length, 0, length - 1)
+ new_self[length] = '\0'
+ str.real_items = new_self
+ return str
end
end
end
redef class Sys
- var _args_cache: nullable Sequence[String]
+ private var args_cache: nullable Sequence[String]
# The arguments of the program as given by the OS
fun program_args: Sequence[String]
#
# Note: it caching is not usefull, see `alpha_comparator`
class CachedAlphaComparator
- super Comparator[Object]
+ super Comparator
+ redef type COMPARED: Object
private var cache = new HashMap[Object, String]
# see `alpha_comparator`
private class AlphaComparator
- super Comparator[Object]
+ super Comparator
redef fun compare(a, b) do return a.to_s <=> b.to_s
end
# var a = [1, 2, 3, 10, 20]
# alpha_comparator.sort(a)
# assert a == [1, 10, 2, 20, 3]
-fun alpha_comparator: Comparator[Object] do return once new AlphaComparator
+fun alpha_comparator: Comparator do return once new AlphaComparator
# The arguments of the program as given by the OS
fun args: Sequence[String]