lib: Split collections into readable and writable
authorJean Privat <jean@pryen.org>
Wed, 10 Jun 2009 13:29:20 +0000 (09:29 -0400)
committerJean Privat <jean@pryen.org>
Wed, 10 Jun 2009 13:29:20 +0000 (09:29 -0400)
Map ->
  MapRead (r)
  Map (rw)
IndexedCollection ->
  IndexedCollectionRead (r)
  IndexedCollection (rw)
AbstractArray ->
  AbstractArrayRead (r)
  AbstractArray (rw)
String ->
  String (ro)
  Buffer (rw)

Signed-off-by: Jean Privat <jean@pryen.org>

32 files changed:
lib/opts.nit
lib/standard/abstract_collection.nit
lib/standard/array.nit
lib/standard/exec.nit
lib/standard/file.nit
lib/standard/hash.nit
lib/standard/list.nit
lib/standard/stream.nit
lib/standard/string.nit
src/compiling/compiling.nit
src/compiling/compiling_global.nit
src/compiling/compiling_methods.nit
src/metamodel/partial_order.nit
src/metamodel/static_type.nit
src/nitc.nit
src/nitdoc.nit
src/parser/lexer.nit
src/parser/xss/lexer.xss
src/syntax/mmbuilder.nit
src/utils.nit
tests/bench_string_append.nit
tests/example_objet.nit
tests/example_point.nit
tests/example_procedural_string.nit
tests/example_string.nit
tests/example_time.nit
tests/sav/test_symbol.sav
tests/shootout_nsieve.nit
tests/test_create_more.nit
tests/test_isa.nit
tests/test_refinement.nit
tests/test_string_long.nit

index b9e5ceb..81b9a98 100644 (file)
@@ -57,14 +57,14 @@ class Option
        # A pretty print for this help
        meth pretty(off: Int): String
        do
-               var text = "  "
+               var text = new Buffer.from("  ")
                text.append(_names.join(", "))
                text.append("  ")
                var rest = off - text.length
                if rest > 0 then text.append(" " * rest)
                text.append(helptext)
                #text.append(pretty_default)
-               return text
+               return text.to_s
        end
 
        meth pretty_default: String
index 2ece03d..8f0a11d 100644 (file)
@@ -227,6 +227,17 @@ special SimpleCollection[E]
        redef meth remove_all(item) do remove(item)
 end
 
+interface MapRead[K, E]
+special Collection[E]
+       # Get the item at `key'.
+       meth [](key: K): E is abstract
+
+       # Is there an item at `key'.
+       meth has_key(key: K): Bool is abstract
+
+       redef meth iterator: MapIterator[K, E] is abstract
+end
+
 # Maps are associative collections: `key' -> `item'.
 #
 # The main operator over maps is [].
@@ -241,15 +252,10 @@ end
 #     map.has_key(u3)    # -> false
 interface Map[K, E]
 special RemovableCollection[E]
-       # Get the item at `key'.    
-       meth [](key: K): E is abstract
-
+special MapRead[K, E]
        # Set the`item' at `key'.
        meth []=(key: K, item: E) is abstract
 
-       # Is there an item at `key'.
-       meth has_key(key: K): Bool is abstract
-
        # Remove the item at `key'
        meth remove_at(key: K) is abstract
 
@@ -263,8 +269,6 @@ special RemovableCollection[E]
                        i.next
                end
        end
-
-       redef meth iterator: MapIterator[K, E] is abstract
 end
 
 # Iterators for Map.
@@ -274,35 +278,55 @@ special Iterator[E]
        meth key: K is abstract
 
        # Set a new `item' at `key'.
-       meth item=(item: E) is abstract
+       #meth item=(item: E) is abstract
 end
 
 # Indexed collection are ordoned collections.
 # The first item is 0. The last is `length'-1.
-interface IndexedCollection[E]
-special Map[Int, E]
-special SimpleCollection[E]
+interface IndexedCollectionRead[E]
+special MapRead[Int, E]
        # Get the first item.
        # Is equivalent with `self'[0].
-       redef meth first 
-       do 
+       redef meth first
+       do
                assert not_empty: not is_empty
-               return self[0] 
+               return self[0]
        end
        
-       # Set the first item.
-       # Is equivalent with `self'[0] = `item'.
-       meth first=(item: E)
-       do self[0] = item end
-
        # Get the last item.
        # Is equivalent with `self'[`length'-1].
        meth last: E
-       do 
+       do
                assert not_empty: not is_empty
-               return self[length-1] 
+               return self[length-1]
        end
 
+       # Return the index of the first occurence of `item'.
+       # Return -1 if `item' is not found
+       meth index_of(item: E): Int
+       do
+               var i = iterator
+               while i.is_ok do
+                       if i.item == item then return i.index
+                       i.next
+               end
+               return -1
+       end
+
+       redef meth iterator: IndexedIterator[E] is abstract
+end
+
+# Indexed collection are ordoned collections.
+# The first item is 0. The last is `length'-1.
+interface IndexedCollection[E]
+special IndexedCollectionRead[E]
+special Map[Int, E]
+special SimpleCollection[E]
+       # Set the first item.
+       # Is equivalent with `self'[0] = `item'.
+       meth first=(item: E)
+       do self[0] = item end
+
        # Set the last item.
        # Is equivalent with `self'[length-1] = `item'.
        meth last=(item: E) 
@@ -334,19 +358,6 @@ special SimpleCollection[E]
        # The second item become the first.
        meth shift: E is abstract
 
-       # Return the index of the first occurence of `item'.
-       # Return -1 if `item' is not found
-       meth index_of(item: E): Int
-       do
-               var i = iterator
-               while i.is_ok do
-                       if i.item == item then return i.index
-                       i.next
-               end
-               return -1
-       end
-
-       redef meth iterator: IndexedIterator[E] is abstract
 end
 
 # Iterators on indexed collections.
@@ -386,7 +397,7 @@ class CoupleMapIterator[K, E]
 special MapIterator[K, E]
        redef meth item do return _iter.item.second
        
-       redef meth item=(e) do _iter.item.second = e
+       #redef meth item=(e) do _iter.item.second = e
 
        redef meth key do return _iter.item.first
 
index 78beeb3..1f90388 100644 (file)
@@ -17,60 +17,13 @@ package array
 
 import abstract_collection
 
-# Resizeable one dimention array of objects.
-class AbstractArray[E]
-special IndexedCollection[E]
-       meth enlarge(cap: Int) is abstract
-
+# One dimention array of objects.
+class AbstractArrayRead[E]
+special IndexedCollectionRead[E]
        # The current length
        redef readable attr _length: Int = 0
-       
-       redef meth is_empty do return _length == 0
-
-       redef meth push(item) do add(item)
-       
-       redef meth pop
-       do
-               assert not_empty: not is_empty
-               var r = last
-               _length -= 1
-               return r
-       end
-
-       redef meth shift
-       do
-               assert not_empty: not is_empty
-               var r = first
-               var i = 1
-               var l = length
-               while i < l do
-                       self[i-1] = self[i]
-                       i += 1
-               end
-               _length = l - 1
-               return r
-       end
 
-       redef meth unshift(item)
-       do
-               var i = length - 1
-               while i > 0 do
-                       self[i+1] = self[i]
-                       i -= 1
-               end
-               self[0] = item
-       end
-
-       meth insert(item: E, pos: Int)
-       do
-               enlarge(length + 1)
-               copy_to(pos, length-pos, self, pos + 1)
-               self[pos] = item
-       end
-
-       redef meth add(item) do self[length] = item
-
-       redef meth clear do _length = 0
+       redef meth is_empty do return _length == 0
 
        redef meth has(item)
        do
@@ -149,30 +102,6 @@ special IndexedCollection[E]
                return result
        end
 
-       redef meth remove(item) do remove_at(index_of(item))
-
-       redef meth remove_all(item)
-       do
-               var i = index_of(item)
-               while i >= 0 do
-                       remove_at(i)
-                       i = index_of_from(item, i)
-               end
-       end
-
-       redef meth remove_at(i)
-       do
-               var l = length
-               if i >= 0 and i < l then
-                       var j = i + 1
-                       while j < l do
-                               self[j-1] = self[j]
-                               j += 1
-                       end             
-                       _length = l - 1 
-               end
-       end
-
        protected meth copy_to(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
        do
                # TODO native one
@@ -211,7 +140,83 @@ special IndexedCollection[E]
                return true
        end
 end
-       
+
+# Resizeable one dimention array of objects.
+class AbstractArray[E]
+special AbstractArrayRead[E]
+special IndexedCollection[E]
+       meth enlarge(cap: Int) is abstract
+
+       redef meth push(item) do add(item)
+
+       redef meth pop
+       do
+               assert not_empty: not is_empty
+               var r = last
+               _length -= 1
+               return r
+       end
+
+       redef meth shift
+       do
+               assert not_empty: not is_empty
+               var r = first
+               var i = 1
+               var l = length
+               while i < l do
+                       self[i-1] = self[i]
+                       i += 1
+               end
+               _length = l - 1
+               return r
+       end
+
+       redef meth unshift(item)
+       do
+               var i = length - 1
+               while i > 0 do
+                       self[i+1] = self[i]
+                       i -= 1
+               end
+               self[0] = item
+       end
+
+       meth insert(item: E, pos: Int)
+       do
+               enlarge(length + 1)
+               copy_to(pos, length-pos, self, pos + 1)
+               self[pos] = item
+       end
+
+       redef meth add(item) do self[length] = item
+
+       redef meth clear do _length = 0
+
+       redef meth remove(item) do remove_at(index_of(item))
+
+       redef meth remove_all(item)
+       do
+               var i = index_of(item)
+               while i >= 0 do
+                       remove_at(i)
+                       i = index_of_from(item, i)
+               end
+       end
+
+       redef meth remove_at(i)
+       do
+               var l = length
+               if i >= 0 and i < l then
+                       var j = i + 1
+                       while j < l do
+                               self[j-1] = self[j]
+                               j += 1
+                       end
+                       _length = l - 1
+               end
+       end
+end
+
 # Resizeable one dimention array of objects.
 #
 # Arrays have a literal representation.
@@ -312,13 +317,13 @@ class ArrayIterator[E]
 special IndexedIterator[E]
        redef meth item do return _array[_index]
 
-       redef meth item=(e) do _array[_index] = e
+       # redef meth item=(e) do _array[_index] = e
 
        redef meth is_ok do return _index < _array.length
 
        redef meth next do _index += 1
 
-       init(a: AbstractArray[E])
+       init(a: AbstractArrayRead[E])
        do
                assert not_nil: a != null
                _array = a
@@ -326,7 +331,7 @@ special IndexedIterator[E]
        end
 
        redef readable attr _index: Int = 0
-       attr _array: AbstractArray[E]
+       attr _array: AbstractArrayRead[E]
 end
 
 # Others collections ##########################################################
@@ -397,7 +402,7 @@ end
 
 # Associative arrays implemented with an array of (key, value) pairs.
 class ArrayMap[K, E]
-special CoupleMap[K, E] 
+special CoupleMap[K, E]
 
        # O(n)
        redef meth [](key)
@@ -418,7 +423,7 @@ special CoupleMap[K, E]
                        _items[i].second = item
                else
                        _items.push(new Couple[K,E](key, item))
-               end                
+               end
        end
 
        # O(n)
@@ -511,12 +516,12 @@ special CoupleMap[K, E]
 
        # The last positive result given by a index(1) call
        attr _last_index: Int = 0
-       
+
        # Where is the `key' in `_item'?
        # return -1 if not found
        private meth index(key: K): Int
        do
-               var l = _last_index 
+               var l = _last_index
                if l < _items.length and _items[l].first == key then return l
 
                var i = 0
@@ -532,7 +537,7 @@ special CoupleMap[K, E]
 
        # A new empty map.
        init
-       do 
+       do
                _items = new Array[Couple[K,E]]
        end
 end
index c98a39c..72dd195 100644 (file)
@@ -61,7 +61,7 @@ class Process
        # Internal code to handle execusion
        protected init execute(command: String, arguments: Array[String], pipeflags: Int)
        do
-               var args = new String
+               var args = new Buffer
                var l = 1 # Number of elements in args
                args.append(command)
                if arguments != null then
@@ -71,7 +71,7 @@ class Process
                        end
                        l += arguments.length
                end
-               _data = basic_exec_execute(command.to_cstring, args.to_cstring, l, pipeflags)
+               _data = basic_exec_execute(command.to_cstring, args.to_s.to_cstring, l, pipeflags)
        end
        
        attr _data: NativeProcess
index 7dbf17a..e6df753 100644 (file)
@@ -242,7 +242,7 @@ redef class String
        meth mkdir
        do
                var dirs = self.split_with("/")
-               var path = new String
+               var path = new Buffer
                if dirs.is_empty then return
                if dirs[0].is_empty then
                        # it was a starting /
@@ -252,7 +252,7 @@ redef class String
                        if d.is_empty then continue
                        path.append(d)
                        path.add('/')
-                       path.to_cstring.file_mkdir
+                       path.to_s.to_cstring.file_mkdir
                end
        end
 end
index 9d68891..af4ebd3 100644 (file)
@@ -336,11 +336,11 @@ special MapIterator[K, V]
                return _node.second
        end
 
-       redef meth item=(value)
-       do
-               assert is_ok
-               _node.second = value
-       end
+       #redef meth item=(value)
+       #do
+       #       assert is_ok
+       #       _node.second = value
+       #end
 
        redef meth key
        do
index 5ab2cf3..97caba4 100644 (file)
@@ -245,7 +245,7 @@ class ListIterator[E]
 special IndexedIterator[E]
        redef meth item do return _node.item
 
-       redef meth item=(e) do _node.item = e
+       # redef meth item=(e) do _node.item = e
 
        redef meth is_ok do return not _node == null
 
index 9046044..3204e84 100644 (file)
@@ -30,7 +30,7 @@ special IOS
        # Read at most i bytes
        meth read(i: Int): String
        do
-               var s = new String.with_capacity(i)
+               var s = new Buffer.with_capacity(i)
                while i > 0 and not eof do
                        var c = read_char
                        if c >= 0 then
@@ -38,31 +38,31 @@ special IOS
                                i -= 1
                        end
                end
-               return s
+               return s.to_s
        end
 
        # Read a string until the end of the line.
        meth read_line: String
        do
                assert not eof
-               var s = new String
+               var s = new Buffer
                append_line_to(s)
-               return s
+               return s.to_s
        end
 
        # Read all the stream until the eof.
        meth read_all: String
        do
-               var s = ""
+               var s = new Buffer
                while not eof do
                        var c = read_char
                        if c >= 0 then s.add(c.ascii)
                end
-               return s
+               return s.to_s
        end
 
        # Read a string until the end of the line and append it to `s'.
-       meth append_line_to(s: String)
+       meth append_line_to(s: Buffer)
        do
                while true do
                        var x = read_char
@@ -109,13 +109,13 @@ special IStream
 
        redef meth read(i)
        do
-               var s = new String.with_capacity(i)
+               var s = new Buffer.with_capacity(i)
                var j = _buffer_pos
                var k = _buffer.length
                while i > 0 do
                        if j >= k then
                                fill_buffer
-                               if eof then return s
+                               if eof then return s.to_s
                                j = _buffer_pos
                                k = _buffer.length
                        end
@@ -126,12 +126,12 @@ special IStream
                        end
                end
                _buffer_pos = j
-               return s
+               return s.to_s
        end
 
        redef meth read_all
        do
-               var s = ""
+               var s = new Buffer
                while not eof do
                        var j = _buffer_pos
                        var k = _buffer.length
@@ -142,7 +142,7 @@ special IStream
                        _buffer_pos = j
                        fill_buffer
                end
-               return s
+               return s.to_s
        end   
 
        redef meth append_line_to(s)
@@ -184,7 +184,7 @@ special IStream
        redef meth eof do return _buffer_pos >= _buffer.length and end_reached
 
        # The buffer
-       attr _buffer: String = null
+       attr _buffer: Buffer = null
 
        # The current position in the buffer
        attr _buffer_pos: Int = 0
@@ -198,7 +198,7 @@ special IStream
        # Allocate a `_buffer' for a given `capacity'.
        protected meth prepare_buffer(capacity: Int)
        do
-               _buffer = new String.with_capacity(capacity)
+               _buffer = new Buffer.with_capacity(capacity)
                _buffer_pos = 0 # need to read
        end
 end
index a9ebc63..3b0065c 100644 (file)
@@ -20,88 +20,86 @@ intrude import array
 # String                                                                      #
 ###############################################################################
 
-# Strings are arrays of characters.
-class String
-special AbstractArray[Char]
-special Comparable
-special StringCapable
-       
-       redef type OTHER: String
+abstract class AbstractString
+special AbstractArrayRead[Char]
+       readable private attr _items: NativeString
 
        redef meth [](index) do return _items[index]
 
-       redef meth []=(index, item)
+       # Create a substring.
+       #
+       # "abcd".substring(1, 2)        # --> "bc"
+       # "abcd".substring(-1, 2)       # --> "a"
+       # "abcd".substring(1, 0)     # --> ""
+       # "abcd".substring(2, 5)     # --> "cd"
+       meth substring(from: Int, count: Int): String
        do
-               if index == length then
-                       add(item)
-                       return
+               assert count >= 0
+               count += from
+               if from < 0 then from = 0
+               if count > length then count = length
+               if from < count then
+                       var r = new Buffer.with_capacity(count - from)
+                       while from < count do
+                               r.push(_items[from])
+                               from += 1
+                       end
+                       return r.to_s
+               else
+                       return ""
                end
-               assert index >= 0 and index < length
-               _items[index] = item
-       end
-
-       redef meth add(c)
-       do
-               if _capacity <= length then enlarge(length + 5)
-               _items[length] = c
-               _length += 1
        end
 
-       redef meth enlarge(cap)
+       # Create a substring with the string beginning at the 'from' position
+       #
+       # "abcd".substring(1)   # --> "bcd"
+       # "abcd".substring(-1)  # --> "abcd"
+       # "abcd".substring(2)     # --> "cd"
+       meth substring_from(from: Int): String
        do
-               var c = _capacity
-               if cap <= c then return
-               while c <= cap do c = c * 2 + 2
-               var a = calloc_string(c)
-               _items.copy_to(a, length, 0, 0)
-               _items = a
-               _capacity = c
+               assert from < length
+               return substring(from, length - from)
        end
 
-       redef meth append(s)
+       # is this string a substring of the 'of' string from pos 'pos'
+       #
+       # "bc".is_substring("abcd",1)   # --> true
+       # "bc".is_substring("abcd",2)   # --> false
+       meth has_substring(str: String, pos: Int): Bool
        do
-               if s isa String then
-                       var sl = s.length
-                       if _capacity < length + sl then enlarge(length + sl)
-                       s.items.copy_to(_items, sl, 0, length)
-                       _length += sl
-               else
-                       super
+               var itsindex = str.length - 1
+               var myindex = pos + itsindex
+               var myitems = _items
+               var itsitems = str._items
+               if myindex > length or itsindex > myindex  then return false
+               while itsindex > 0 do
+                       if myitems[myindex] != itsitems[itsindex] then return false
+                       myindex -= myindex
+                       itsindex -= itsindex
                end
+               return true
        end
 
-       # The concatenation of `self' with `r'
-       meth +(s: String): String
-       do
-               var r = new String.with_capacity(length + s.length)
-               r.append(self)
-               r.append(s)
-               return r
-       end
-       
-       # i repetitions of self
-       meth *(i: Int): String
-       do
-               assert i >= 0
-               var r = new String.with_capacity(length * i)
-               while i > 0 do
-                       r.append(self)
-                       i -= 1
-               end
-               return r
-       end
+       # Is this string prefixed by 'prefix'
+       #
+       # "abc".is_prefix("abcd")       # --> true
+       # "bc".is_prefix("abcd")        # --> false
+       meth has_prefix(prefix: String): Bool do return has_substring(prefix,0)
 
-       # Clone.
-       redef meth to_s: String do return new String.from(self)
+       # Is this string suffixed by 'suffix'
+       #
+       # "abcd".has_suffix("abc")      # --> false
+       # "abcd".has_suffix("bcd")      # --> true
+       meth has_suffix(suffix: String): Bool do return has_substring(suffix, length - suffix.length)
 
        # If `self' contains only digits, return the corresponding integer
        meth to_i: Int
        do
                # Shortcut
-               return to_cstring.atoi
+               return to_s.to_cstring.atoi
        end
 
-       # If `self' contains only digits and alpha <= 'f', return the corresponding integer. 
+       # If `self' contains only digits and alpha <= 'f', return the corresponding integer.
        meth to_hex: Int do return a_to(16)
 
        # If `self' contains only digits and letters, return the corresponding integer in a given base
@@ -109,7 +107,7 @@ special StringCapable
        do
                var i = 0
                var neg = false
-               
+
                for c in self
                do
                        var v = c.to_i
@@ -132,79 +130,185 @@ special StringCapable
                end
        end
 
+       # String to upper case
+       meth to_upper: String
+       do
+               var s = new Buffer.with_capacity(length)
+               for i in self do s.add(i.to_upper)
+               return s.to_s
+       end
+
+       # String to lower case
+       meth to_lower : String
+       do
+               var s = new Buffer.with_capacity(length)
+               for i in self do s.add(i.to_lower)
+               return s.to_s
+       end
+
+
+       redef meth output
+       do
+               var i = 0
+               while i < length do
+                       _items[i].output
+                       i += 1
+               end
+       end
+end
+
+
+class String
+special Comparable
+special AbstractString
+       redef type OTHER: String
+
+       # Create a new string from a given char *.
+       init with_native(nat: NativeString, size: Int)
+       do
+               assert size >= 0
+               _items = nat
+               _length = size
+       end
+
+       # Create a new string from a null terminated char *.
+       init from_cstring(str: NativeString)
+       do
+               var size = str.cstring_length
+               _items = str
+               _length = size
+       end
+
        # Return a null terminated char *
        meth to_cstring: NativeString
        do
-               self[length] = '\0'
-               _length -= 1
                return _items
        end
 
-       # Create a substring.
-       #
-       # "abcd".substring(1, 2)        # --> "bc"
-       # "abcd".substring(-1, 2)       # --> "a"
-       # "abcd".substring(1, 0)     # --> ""
-       # "abcd".substring(2, 5)     # --> "cd"
-       meth substring(from: Int, count: Int): String
+       redef meth ==(o)
        do
-               assert count >= 0
-               count += from
-               if from < 0 then from = 0
-               if count > length then count = length
-               if from < count then
-                       var r = new String.with_capacity(count - from)
-                       while from < count do
-                               r.push(_items[from])
-                               from += 1
+               if not o isa String or o is null then return false
+               assert o isa String
+               var l = length
+               if o.length != l then return false
+               var i = 0
+               var it = _items
+               var oit = o._items
+               while i < l do
+                       if it[i] != oit[i] then return false
+                       i += 1
+               end
+               return true
+       end
+
+       redef meth <(s)
+       do
+               var i = 0
+               var l1 = length
+               var l2 = s.length
+               var n1 = _items
+               var n2 = s._items
+               while i < l1 and i < l2 do
+                       var c1 = n1[i].ascii
+                       var c2 = n2[i].ascii
+                       if c1 < c2 then
+                               return true
+                       else if c2 < c1 then
+                               return false
                        end
-                       return r
+                       i += 1
+               end
+               if l1 < l2 then
+                       return true
                else
-                       return ""
+                       return false
                end
        end
 
-       # Create a substring with the string beginning at the 'from' position
-       #
-       # "abcd".substring(1)   # --> "bcd"
-       # "abcd".substring(-1)  # --> "abcd"
-       # "abcd".substring(2)     # --> "cd"
-       meth substring_from(from: Int): String
+       # The concatenation of `self' with `r'
+       meth +(s: String): String
        do
-               assert from < length
-               return substring(from, length - from)
+               var r = new Buffer.with_capacity(length + s.length)
+               r.append(self)
+               r.append(s)
+               return r.to_s
        end
 
-       # is this string a substring of the 'of' string from pos 'pos'
-       #
-       # "bc".is_substring("abcd",1)   # --> true
-       # "bc".is_substring("abcd",2)   # --> false
-       meth has_substring(str: String, pos: Int): Bool
+       # i repetitions of self
+       meth *(i: Int): String
        do
-               var itsindex = str.length - 1
-               var myindex = pos + itsindex
-               var myitems = _items
-               var itsitems = str._items
-               if myindex > length or itsindex > myindex  then return false
-               while itsindex > 0 do
-                       if myitems[myindex] != itsitems[itsindex] then return false
-                       myindex -= myindex
-                       itsindex -= itsindex
+               assert i >= 0
+               var r = new Buffer.with_capacity(length * i)
+               while i > 0 do
+                       r.append(self)
+                       i -= 1
                end
-               return true
+               return r.to_s
        end
 
-       # Is this string prefixed by 'prefix'
-       #
-       # "abc".is_prefix("abcd")       # --> true
-       # "bc".is_prefix("abcd")        # --> false
-       meth has_prefix(prefix: String): Bool do return has_substring(prefix,0)
+       redef meth to_s do return self
+end
 
-       # Is this string suffixed by 'suffix'
-       #
-       # "abcd".has_suffix("abc")      # --> false
-       # "abcd".has_suffix("bcd")      # --> true
-       meth has_suffix(suffix: String): Bool do return has_substring(suffix, length - suffix.length)
+# Strings are arrays of characters.
+class Buffer
+special AbstractString
+special Comparable
+special StringCapable
+special AbstractArray[Char]
+
+       redef type OTHER: String
+
+       redef meth []=(index, item)
+       do
+               if index == length then
+                       add(item)
+                       return
+               end
+               assert index >= 0 and index < length
+               _items[index] = item
+       end
+
+       redef meth add(c)
+       do
+               if _capacity <= length then enlarge(length + 5)
+               _items[length] = c
+               _length += 1
+       end
+
+       redef meth enlarge(cap)
+       do
+               var c = _capacity
+               if cap <= c then return
+               while c <= cap do c = c * 2 + 2
+               var a = calloc_string(c+1)
+               _items.copy_to(a, length, 0, 0)
+               _items = a
+               _capacity = c
+       end
+
+       redef meth append(s)
+       do
+               if s isa String then
+                       var sl = s.length
+                       if _capacity < length + sl then enlarge(length + sl)
+                       s.items.copy_to(_items, sl, 0, length)
+                       _length += sl
+               else
+                       super
+               end
+       end
+
+       redef meth to_s: String
+       do
+               var l = length
+               var a = calloc_string(l+1)
+               _items.copy_to(a, l, 0, 0)
+
+               # Ensure the afterlast byte is '\0' to nul-terminated char *
+               a[length] = '\0'
+
+               return new String.with_native(a, length)
+       end
 
        redef meth <(s)
        do
@@ -247,54 +351,15 @@ special StringCapable
        do
                assert cap >= 0
                # _items = new NativeString.calloc(cap)
-               _items = calloc_string(cap)
+               _items = calloc_string(cap+1)
                _capacity = cap
                _length = 0
        end
 
-       # Create a new string from a given char *.
-       init with_native(nat: NativeString, size: Int)
-       do
-               assert size >= 0
-               _items = nat
-               _capacity = size
-               _length = size
-       end
-
-       # Create a new string from a null terminated char *.
-       init from_cstring(str: NativeString)
-       do
-               var size = str.cstring_length
-               _items = str
-               _capacity = size + 1 # Since there is a trailing \n
-               _length = size
-       end
-
-       # Create a string of `count' chararter `c'
-       init filled_with(c: Char, count: Int)
-       do
-               with_capacity(count)
-               var i = 0
-               while i < count do
-                       _items[i] = c
-                       i += 1
-               end
-               _length = count
-       end
-
-       redef meth output
-       do
-               var i = 0
-               while i < length do
-                       _items[i].output
-                       i += 1
-               end
-       end
-
        redef meth ==(o)
        do
-               if not o isa String or o is null then return false
-               assert o isa String
+               if not o isa Buffer or o is null then return false
+               assert o isa Buffer
                var l = length
                if o.length != l then return false
                var i = 0
@@ -307,23 +372,6 @@ special StringCapable
                return true
        end
 
-       # String to upper case
-       meth to_upper: String
-       do
-               var s = new String.with_capacity(length)
-               for i in self do s.add(i.to_upper)
-               return s
-       end
-
-       # String to lower case
-       meth to_lower : String
-       do
-               var s = new String.with_capacity(length)
-               for i in self do s.add(i.to_lower)
-               return s
-       end
-
-       readable private attr _items: NativeString 
        readable private attr _capacity: Int 
 end
 
@@ -342,7 +390,7 @@ redef class Object
        meth inspect: String
        do
                var r = inspect_head
-               r.add('>')
+               # r.add('>')
                return r
        end
 
@@ -371,7 +419,7 @@ redef class Bool
 end
 
 redef class Int
-       meth fill_string(s: String, base: Int, signed: Bool)
+       meth fill_buffer(s: Buffer, base: Int, signed: Bool)
        # Fill `s' with the digits in base 'base' of `self' (and with the '-' sign if 'signed' and negative).
        # assume < to_c max const of char
        do
@@ -405,9 +453,9 @@ redef class Int
        meth to_base(base: Int, signed: Bool): String
        do
                var l = digit_count(base)
-               var s = new String.filled_with(' ', l)
-               fill_string(s, base, signed)
-               return s
+               var s = new Buffer.from(" " * l)
+               fill_buffer(s, base, signed)
+               return s.to_s
        end
 end
 
@@ -433,9 +481,9 @@ end
 redef class Char
        redef meth to_s
        do
-               var s = new String.with_capacity(1)
+               var s = new Buffer.with_capacity(1)
                s[0] = self
-               return s
+               return s.to_s
        end
 end
 
@@ -443,9 +491,9 @@ redef class Collection[E]
        # Concatenate elements.
        redef meth to_s
        do
-               var s = new String
+               var s = new Buffer
                for e in self do if e != null then s.append(e.to_s)
-               return s
+               return s.to_s
        end
 
        # Concatenate and separate each elements with `sep'. 
@@ -453,7 +501,7 @@ redef class Collection[E]
        do
                if is_empty then return ""
                
-               var s = new String # Result
+               var s = new Buffer # Result
 
                # Concat first item
                var i = iterator
@@ -468,7 +516,23 @@ redef class Collection[E]
                        if e != null then s.append(e.to_s)
                        i.next
                end
-               return s
+               return s.to_s
+       end
+end
+
+redef class Array[E]
+       # Fast implementation
+       redef meth to_s
+       do
+               var s = new Buffer
+               var i = 0
+               var l = length
+               while i < l do
+                       var e = self[i]
+                       if e != null then s.append(e.to_s)
+                       i += 1
+               end
+               return s.to_s
        end
 end
 
@@ -478,7 +542,7 @@ redef class Map[K,V]
        do
                if is_empty then return ""
                
-               var s = new String # Result
+               var s = new Buffer # Result
 
                # Concat first item
                var i = iterator
@@ -495,7 +559,7 @@ redef class Map[K,V]
                        if e != null then s.append("{k}{couple_sep}{e}")
                        i.next
                end
-               return s
+               return s.to_s
        end
 end
 
index a74118b..5af27e8 100644 (file)
@@ -48,7 +48,7 @@ redef class MMSrcModule
                        if (native_name + "_nit.h").file_exists then
                                includes.add("-I {native_name.dirname}")
                        end
-                       native_name.append("_nit.c")
+                       native_name += "_nit.c"
                        if native_name.file_exists then files.add(native_name)
                end
 
@@ -103,7 +103,7 @@ redef class MMSrcModule
                v.global_analysis = ga
                v.add_decl("#include <nit_common.h>")
                var native_name = filename.strip_extension(".nit")
-               native_name.append("_nit.h")
+               native_name += ("_nit.h")
                if native_name.file_exists then v.add_decl("#include <{native_name.basename("")}>")
                declare_class_tables_to_c(v)
                compile_mod_to_c(v)
index 65c6ca0..f883907 100644 (file)
@@ -421,7 +421,7 @@ redef class MMSrcModule
                for c in local_classes do
                        c.compile_tables_to_c(v)
                end
-               var s = "classtable_t TAG2VFT[4] = \{NULL"
+               var s = new Buffer.from("classtable_t TAG2VFT[4] = \{NULL")
                for t in ["Int","Char","Bool"] do
                        if has_global_class_named(t.to_symbol) then
                                s.append(", (const classtable_t)VFT_{t}")
@@ -430,7 +430,7 @@ redef class MMSrcModule
                        end
                end
                s.append("};")
-               v.add_instr(s)
+               v.add_instr(s.to_s)
        end
 
        # Declare class table (for _sep.h)
index 4556ba2..1253a51 100644 (file)
@@ -73,12 +73,12 @@ redef class CompilerVisitor
        # Generate an fprintf to display an error location
        meth printf_locate_error(node: PNode): String
        do
-               var s = "fprintf(stderr, \""
+               var s = new Buffer.from("fprintf(stderr, \"")
                if nmc != null then s.append(" in %s")
                s.append(" (%s:%d)\\n\", ")
                if nmc != null then s.append("LOCATE_{nmc.method.cname}, ")
                s.append("LOCATE_{module.name}, {node.line_number});")
-               return s
+               return s.to_s
        end
 
        redef init(module: MMSrcModule)
@@ -1194,7 +1194,7 @@ redef class AStringFormExpr
        do
                var len = 0
                var str = string_text
-               var res = new String
+               var res = new Buffer
                var i = 0
                while i < str.length do
                        var c = str[i]
@@ -1210,7 +1210,7 @@ redef class AStringFormExpr
                        res.add(c)
                        i = i + 1
                end
-               _cstring = res
+               _cstring = res.to_s
                _cstring_length = len
        end
 end
index 42a0525..4960a51 100644 (file)
@@ -68,7 +68,7 @@ special Collection[E]
        # Return a dot representation
        meth to_dot: String
        do
-               var s = new String
+               var s = new Buffer
                s.append(to_dot_header)
                for e in _elements do
                        s.append(to_dot_node(e.value))
@@ -77,7 +77,7 @@ special Collection[E]
                        end
                end
                s.append("}\n")
-               return s
+               return s.to_s
        end
 
        # Called to display the header
index 627fe9e..6cf53b7 100644 (file)
@@ -122,7 +122,7 @@ class MMSignature
 
        redef meth to_s
        do
-               var s: String
+               var s = new Buffer
                if _params != null and _params.length > 0 then
                        var tmp: String
                        var a = new Array[String].with_capacity(_params.length)
@@ -132,14 +132,12 @@ class MMSignature
                                #a.add("{pn}: {p}")
                                a.add(p.to_s)
                        end
-                       s = "({a.join(",")})"
-               else
-                       s = ""
+                       s.append("({a.join(",")})")
                end
                if _return_type != null then
                        s.append(": {_return_type}")
                end
-               return s
+               return s.to_s
        end
 
        # Adapt the signature to a different receiver
index 57ce45e..5c65f1f 100644 (file)
@@ -57,7 +57,7 @@ special AbstractCompiler
                                compdir = ".nit_compile"
                        end
                end
-               compdir.append(ext_prefix)
+               compdir += ext_prefix
 
                clibdir = opt_clibdir.value
                if clibdir == null then
index 9f55979..30d29da 100644 (file)
@@ -425,7 +425,7 @@ special MMEntity
 
        redef meth prototype_head(dctx)
        do
-               var res = ""
+               var res = new Buffer
                var intro_class = known_intro_class(dctx)
                var is_redef = local_class != intro_class
 
@@ -444,12 +444,13 @@ special MMEntity
                                res.append(" {intro_class.module.html_link(dctx)}::")
                        end
                end
-               return res
+               return res.to_s
        end
 
        redef meth prototype_body(dctx)
        do
-               var res = signature.to_html(dctx)
+               var res = new Buffer
+               res.append(signature.to_html(dctx))
                var s = self
                if s.node != null then
                        if s.node isa ADeferredMethPropdef then
@@ -458,7 +459,7 @@ special MMEntity
                                res.append(" is intern")
                        end
                end
-               return res
+               return res.to_s
        end
 
        redef meth need_doc(dctx)
@@ -675,11 +676,11 @@ redef class ADoc
        # Html transcription of the doc
        meth to_html: String
        do
-               var res = new String
+               var res = new Buffer
                for c in n_comment do
                        res.append(c.text.substring_from(1))
                end
-               return res
+               return res.to_s
        end
 
        # Oneliner transcription of the doc
@@ -726,19 +727,19 @@ special MMEntity
 
        redef meth prototype_head(dctx)
        do
-               var res = ""
+               var res = new Buffer
                var ki = known_intro(dctx)
                var is_redef = ki != self
                if is_redef then res.append("redef ")
                if global.visibility_level == 3 then res.append("private ")
                res.append("class ")
                if is_redef then res.append("{ki.module.html_link(dctx)}::")
-               return res
+               return res.to_s
        end
 
        redef meth prototype_body(dctx)
        do
-               var res = ""
+               var res = new Buffer
                if arity > 0 then
                        res.append("[")
                        for i in [0..arity[ do
@@ -749,7 +750,7 @@ special MMEntity
                        end
                        res.append("]")
                end
-               return res
+               return res.to_s
        end
 
        # Extract the doc of a class
@@ -1105,7 +1106,7 @@ redef class MMSignature
        # Htlm transcription of the signature (with nested links)
        meth to_html(dctx: DocContext): String
        do
-               var res = new String
+               var res = new Buffer
                if arity > 0 then
                        res.append("(")
                        res.append(self[0].html_link(dctx))
@@ -1119,7 +1120,7 @@ redef class MMSignature
                        res.append(": ")
                        res.append(return_type.html_link(dctx))
                end
-               return res
+               return res.to_s
        end
 end
 
@@ -1135,7 +1136,8 @@ end
 redef class MMTypeGeneric
        redef meth html_link(dctx)
        do
-               var res = local_class.html_link(dctx)
+               var res = new Buffer
+               res.append(local_class.html_link(dctx))
                res.append("[")
                res.append(params[0].html_link(dctx))
                for i in [1..params.length[ do
@@ -1143,7 +1145,7 @@ redef class MMTypeGeneric
                        res.append(params[i].html_link(dctx))
                end
                res.append("]")
-               return res
+               return res.to_s
        end
 end
 
index 8a7fb3d..bc2de48 100644 (file)
@@ -1320,7 +1320,7 @@ class Lexer
        attr _stream: IStream
 
        # Pushback buffer to store unread character
-       attr _stream_buf: String
+       attr _stream_buf: Buffer
 
        # Number of character stored in the pushback buffer
        attr _stream_pos: Int
@@ -1338,7 +1338,7 @@ class Lexer
        attr _eof: Bool = false
 
        # Current working text read from the input stream
-       attr _text: String
+       attr _text: Buffer
 
        # Constante state values
        private meth state_initial: Int do return 0 end
@@ -1347,10 +1347,10 @@ class Lexer
        init(stream: IStream, fname: String)
        do
                _filename = fname
-               _text = new String
+               _text = new Buffer
                _stream = stream
                _stream_pos = -1
-               _stream_buf = new String
+               _stream_buf = new Buffer
                build_goto_table
                build_accept_table
        end
index f3b3247..d962dce 100644 (file)
@@ -34,7 +34,7 @@ class Lexer
        attr _stream: IStream
 
        # Pushback buffer to store unread character
-       attr _stream_buf: String
+       attr _stream_buf: Buffer
 
        # Number of character stored in the pushback buffer
        attr _stream_pos: Int
@@ -52,7 +52,7 @@ class Lexer
        attr _eof: Bool = false
 
        # Current working text read from the input stream
-       attr _text: String
+       attr _text: Buffer
 
 $ foreach {lexer_data/state}
        # Constante state values
@@ -63,10 +63,10 @@ $ end foreach
        init(stream: IStream, fname: String)
        do
                _filename = fname
-               _text = new String
+               _text = new Buffer
                _stream = stream
                _stream_pos = -1
-               _stream_buf = new String
+               _stream_buf = new Buffer
                build_goto_table
                build_accept_table
        end
index 038ab90..b59eaa9 100644 (file)
@@ -1055,7 +1055,7 @@ end
 # Visitor used to build a full method name from multiple tokens
 private class MethidAccumulator
 special Visitor
-       readable attr _name: String 
+       readable attr _name: Buffer = new Buffer
        redef meth visit(n)
        do
                if n isa Token then
@@ -1064,11 +1064,6 @@ special Visitor
                        n.visit_all(self)
                end
        end
-
-       init
-       do
-               _name = new String
-       end
 end
 
 redef class PMethid
@@ -1079,7 +1074,7 @@ redef class PMethid
        do
                var accumulator = new MethidAccumulator
                accumulator.visit(self)
-               _name = accumulator.name.to_symbol
+               _name = accumulator.name.to_s.to_symbol
                super
        end
 end
index 1aa727f..f8dbfbd 100644 (file)
@@ -22,7 +22,7 @@ package utils
 meth cmangle(symbols: Symbol...): String
 do
        var table = once cmangle_table
-       var res = new String
+       var res = new Buffer
        for sym in symbols do
                if not res.is_empty then
                        res.add('_')
@@ -52,7 +52,7 @@ do
                        end
                end
        end
-       return res
+       return res.to_s
 end
 
 # Build the table that associates character to mangle to string
index 1856a7a..9f5944f 100644 (file)
@@ -22,7 +22,7 @@ end
 var s = "*"
 var i = 0
 while i < n do
-       var s2 = "Je dis «"
+       var s2 = new Buffer.from("Je dis «")
        s2.append(s)
        s2.append("» et redis «")
        s2.append(s)
@@ -30,7 +30,7 @@ while i < n do
        s2.append(s)
        s2.append(s)
        s2.append("».\n")
-       s = s2
+       s = s2.to_s
        i = i + 1
 end
 print("Je dis «Je dis".search_all_in(s).length)
index db8bc4f..cc22a7c 100644 (file)
@@ -101,9 +101,9 @@ private
        do
                # Les variables sont déclarées par "var", leur portée va de leur
                # déclaration jusqu'au "end" correspondant
-               var s: String           # Là où on calcule le résultat
+               var s = new Buffer              # Là où on calcule le résultat
                # Les chaînes littérales sont déclarées avec des guillemets
-               s = "*** Entrepôt "     # On initialise "s"
+               s.append("*** Entrepôt ")       # On initialise "s"
                # puis on concatène des chaînes à "s"
                s.append(_nom_)         # la méthode "append" concatène
                s.append(" ***\n")
@@ -124,7 +124,7 @@ private
                        s.add('\n')     # "add" ajoute un caractère à la fin.
                        # Comme en C, les caractères sont entre simples cotes.
                end
-               return s
+               return s.to_s
        end
 
 
@@ -218,12 +218,13 @@ private
                # Si une expression est passée comme valeur initiale d'une
                # variable, le type statique de la variable est implicitement
                # celui de l'expression.
-               var s = "* Rayon : "
+               var s = new Buffer
+               s.append("* Rayon : ")
                # Ici, le type statique de s est implicitement String
 
                s.append(_rubrique)
                s.add('\n')
-               return s
+               return s.to_s
        end
 
        meth cherche_produit(n: String): Produit
@@ -244,7 +245,8 @@ private
 
        redef meth to_s: String
        do
-               var s = to_s_head
+               var s = new Buffer
+               s.append(to_s_head)
                # Les boucles en NIT sont des structures puissantes, toutefois
                # la manipulation des itérateurs peut être facilité par la
                # structure "for in"
@@ -261,7 +263,7 @@ private
                        s.append(p.to_s)
                        s.add('\n')
                end
-               return s
+               return s.to_s
        end
 
 
index c2363c2..3ab94cb 100644 (file)
@@ -47,11 +47,7 @@ private
 
        redef meth to_s: String
        do
-               var s = "("
-               s.append(_x.to_s)
-               s.add(':')
-               s.append(_y.to_s)
-               s.add(')')
+               var s = "({_x}:{_y})"
                return s
        end
 
index 126fb85..35b7879 100644 (file)
 
 meth first_word(s: String): String
 do
-       var result = new String
+       var result = new Buffer
        var i = 0
        while i < s.length and s[i] != ' ' do
                result.add(s[i])
                i = i + 1
        end
-       return result
+       return result.to_s
 end
 
 print(first_word("Hello world!"))
index 5371270..006efff 100644 (file)
@@ -27,7 +27,7 @@ printn("The value of a is: ", a, ".\n")
 # Second way: Build a string and display it.
 # Pro: Eiffel way (rigourous).
 # Con: Eiffel way (heavy).
-var s = "The value of a is: "
+var s = new Buffer.from("The value of a is: ")
 s.append(a.to_s)
 s.append(".\n")
 printn(s)
index ae694d6..9c47159 100644 (file)
@@ -39,9 +39,7 @@ class Time
        # The quantity of tyme in human readable form (h:m)
        redef meth to_s: String
        do
-               var s = hour.to_s               # Get the h
-               s.add(':')
-               s.append((_min % 60).to_s)      # Append the m
+               var s = "{hour}:{min%60}"
                return s
        end
 
index 5ce0902..bc74ec5 100644 (file)
@@ -3,7 +3,7 @@ TotoTataToto1
 false
 false
 true
-false
+true
 2
 false
 false
index a9a3923..0e2542b 100644 (file)
@@ -17,7 +17,7 @@
 meth nsieve(n: Int): Int
 do
        var count = 0
-       var array = new String.with_capacity(n)
+       var array = new Buffer.with_capacity(n)
        for i in [0..n[ do
                array[i] = 'o'
        end
index 1b0fd1c..c1a0252 100644 (file)
@@ -47,9 +47,9 @@ class A
        do
                var s = _num.to_s
                if _attribute == null then
-                       s.add('\n')
+                       s += "\n"
                else
-                       s.append(_attribute.to_s)
+                       s += _attribute.to_s
                end
                return s
        end
index 5b5ff3b..318a945 100644 (file)
@@ -28,7 +28,7 @@ print("string:")
 a = "Bonjour"
 print(not a isa Int)
 print(a isa String)
-print(a isa AbstractArray[Char])
+print(a isa AbstractArrayRead[Char])
 print(not a isa Iterator[Int])
 print(not a isa Discrete)
 print(a isa Object)
index 4f39f68..ad05e55 100644 (file)
@@ -70,7 +70,7 @@ do
     print(a)
 end
 
-var b = "ab"
+var b = new Buffer.from("ab")
 do
     print(b)
     b.add('c')
index 0429f07..94324a3 100644 (file)
@@ -16,8 +16,8 @@
 
 
 var s = "Bonjour !\n"
-var r = new String.with_capacity(50)
-var r2 = ""
+var r = new Buffer.with_capacity(50)
+var r2 = new Buffer
 
 var i = 0
 while i < 5000 do