lib/standard/string: Added redef for substrings in String
[nit.git] / lib / standard / string.nit
index d41ab1a..b20ed23 100644 (file)
@@ -16,6 +16,7 @@ module string
 
 import math
 import collection
+intrude import collection::array
 
 `{
 #include <stdio.h>
@@ -156,13 +157,6 @@ abstract class Text
                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
        #
@@ -630,6 +624,14 @@ abstract class Text
                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
 
@@ -657,7 +659,11 @@ end
 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
@@ -733,6 +739,8 @@ abstract class String
 
        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"
@@ -824,6 +832,38 @@ abstract class String
 
                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
@@ -849,10 +889,10 @@ class FlatString
        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)
 
@@ -1271,6 +1311,38 @@ abstract class Buffer
        #     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
@@ -1358,6 +1430,7 @@ class FlatBuffer
        redef fun to_s: String
        do
                written = true
+               if length == 0 then items = new NativeString(1)
                return new FlatString.with_infos(items, length, 0, length - 1)
        end
 
@@ -1978,7 +2051,8 @@ extern class NativeString `{ char* `}
        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
@@ -1986,7 +2060,10 @@ extern class NativeString `{ char* `}
                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
 
@@ -1996,7 +2073,7 @@ interface StringCapable
 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]
@@ -2044,7 +2121,8 @@ end
 #
 # 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]
 
@@ -2062,7 +2140,7 @@ end
 
 # 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
 
@@ -2074,7 +2152,7 @@ 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]