tests: fix test errors for engine nitc
[nit.git] / lib / standard / string.nit
index f62f988..4010b81 100644 (file)
 # another product.
 
 # Basic manipulations of strings of characters
-package string
+module string
 
 intrude import collection # FIXME should be collection::array
-import hash
 
 `{
 #include <stdio.h>
@@ -38,10 +37,10 @@ abstract class AbstractString
 
        # Create a substring.
        #
-       #     assert "abcd".substring(1, 2)         ==  "bc"
-       #     assert "abcd".substring(-1, )         ==  "a"
-       #     assert "abcd".substring(1, 0)         ==  ""
-       #     assert "abcd".substring(2, 5)         ==  "cd"
+       #     assert "abcd".substring(1, 2)      ==  "bc"
+       #     assert "abcd".substring(-1, 2)     ==  "a"
+       #     assert "abcd".substring(1, 0)      ==  ""
+       #     assert "abcd".substring(2, 5)      ==  "cd"
        #
        # A `from` index < 0 will be replaced by 0.
        # Unless a `count` value is > 0 at the same time.
@@ -66,9 +65,9 @@ abstract class AbstractString
 
        # Create a substring from `self` beginning at the `from` position
        #
-       #     assert "abcd".substring_from(1)        ==  "bcd"
-       #     assert "abcd".substring_from(-1)       ==  "abcd"
-       #     assert "abcd".substring_from(2)       ==  "cd"
+       #     assert "abcd".substring_from(1)    ==  "bcd"
+       #     assert "abcd".substring_from(-1)   ==  "abcd"
+       #     assert "abcd".substring_from(2)    ==  "cd"
        #
        # As with substring, a `from` index < 0 will be replaced by 0
        fun substring_from(from: Int): String
@@ -100,8 +99,9 @@ abstract class AbstractString
 
        # Is this string prefixed by `prefix`?
        #
-       #     assert "abcd".has_prefix("ab")         ==  true
-       #     assert "abcbc".has_prefix("bc")        ==  false
+       #     assert "abcd".has_prefix("ab")           ==  true
+       #     assert "abcbc".has_prefix("bc")          ==  false
+       #     assert "ab".has_prefix("abcd")           ==  false
        fun has_prefix(prefix: String): Bool do return has_substring(prefix,0)
 
        # Is this string suffixed by `suffix`?
@@ -124,7 +124,7 @@ abstract class AbstractString
        #
        #     assert "123".to_f        == 123.0
        #     assert "-1".to_f         == -1.0
-       #     assert "-1.2e-3".to_f    == -1.2e-3
+       #     assert "-1.2e-3".to_f    == -0.0012
        fun to_f: Float
        do
                # Shortcut
@@ -239,6 +239,122 @@ abstract class AbstractString
                        i += 1
                end
        end
+
+       # Mangle a string to be a unique string only made of alphanumeric characters
+       fun to_cmangle: String
+       do
+               var res = new Buffer
+               var underscore = false
+               for c in self do
+                       if (c >= 'a' and c <= 'z') or (c >='A' and c <= 'Z') then
+                               res.add(c)
+                               underscore = false
+                               continue
+                       end
+                       if underscore then
+                               res.append('_'.ascii.to_s)
+                               res.add('d')
+                       end
+                       if c >= '0' and c <= '9' then
+                               res.add(c)
+                               underscore = false
+                       else if c == '_' then
+                               res.add(c)
+                               underscore = true
+                       else
+                               res.add('_')
+                               res.append(c.ascii.to_s)
+                               res.add('d')
+                               underscore = false
+                       end
+               end
+               return res.to_s
+       end
+
+       # Escape " \ ' and non printable characters using the rules of literal C strings and characters
+       #
+       #     assert "abAB12<>&".escape_to_c         == "abAB12<>&"
+       #     assert "\n\"'\\".escape_to_c         == "\\n\\\"\\'\\\\"
+       fun escape_to_c: String
+       do
+               var b = new Buffer
+               for c in self do
+                       if c == '\n' then
+                               b.append("\\n")
+                       else if c == '\0' then
+                               b.append("\\0")
+                       else if c == '"' then
+                               b.append("\\\"")
+                       else if c == '\'' then
+                               b.append("\\\'")
+                       else if c == '\\' then
+                               b.append("\\\\")
+                       else if c.ascii < 32 then
+                               b.append("\\{c.ascii.to_base(8, false)}")
+                       else
+                               b.add(c)
+                       end
+               end
+               return b.to_s
+       end
+
+       # Escape additionnal characters
+       # The result might no be legal in C but be used in other languages
+       #
+       #     assert "ab|\{\}".escape_more_to_c("|\{\}") == "ab\\|\\\{\\\}"
+       fun escape_more_to_c(chars: String): String
+       do
+               var b = new Buffer
+               for c in escape_to_c do
+                       if chars.has(c) then
+                               b.add('\\')
+                       end
+                       b.add(c)
+               end
+               return b.to_s
+       end
+
+       # Escape to c plus braces
+       #
+       #     assert "\n\"'\\\{\}".escape_to_nit      == "\\n\\\"\\'\\\\\\\{\\\}"
+       fun escape_to_nit: String do return escape_more_to_c("\{\}")
+
+       # Return a string where Nit escape sequences are transformed.
+       #
+       # Example:
+       #     var s = "\\n"
+       #     assert s.length        ==  2
+       #     var u = s.unescape_nit
+       #     assert u.length        ==  1
+       #     assert u[0].ascii      ==  10 # (the ASCII value of the "new line" character)
+       fun unescape_nit: String
+       do
+               var res = new Buffer.with_capacity(self.length)
+               var was_slash = false
+               for c in self do
+                       if not was_slash then
+                               if c == '\\' then
+                                       was_slash = true
+                               else
+                                       res.add(c)
+                               end
+                               continue
+                       end
+                       was_slash = false
+                       if c == 'n' then
+                               res.add('\n')
+                       else if c == 'r' then
+                               res.add('\r')
+                       else if c == 't' then
+                               res.add('\t')
+                       else if c == '0' then
+                               res.add('\0')
+                       else
+                               res.add(c)
+                       end
+               end
+               return res.to_s
+       end
 end
 
 # Immutable strings of characters.
@@ -405,35 +521,6 @@ class String
                _length = to - from + 1
        end
 
-       # Create a new string from a given char *.
-       private init with_native(nat: NativeString, size: Int)
-       do
-               assert size >= 0
-               _items = nat
-               _length = size
-               _index_from = 0
-               _index_to = _length - 1
-       end
-
-       # Create a new string from a null terminated char *.
-       private init from_cstring(str: NativeString)
-       do
-               with_native(str,str.cstring_length)
-       end
-
-       # Creates a new Nit String from an existing CString
-       # Pretty much equals to from_cstring but copies instead
-       # of passing a reference
-       # Avoids manual/automatic dealloc problems when dealing with native C code
-       private init copy_from_native(str: NativeString)
-       do
-               var temp_length = str.cstring_length
-               var new_str = calloc_string(temp_length + 1)
-               str.copy_to(new_str, temp_length, 0, 0)
-               new_str[temp_length] = '\0'
-               with_native(new_str, temp_length)
-       end
-
        private init with_infos(items: NativeString, len: Int, from: Int, to: Int)
        do
                self._items = items
@@ -483,7 +570,7 @@ class String
 
        # The comparison between two strings is done on a lexicographical basis
        #
-       #     assert "aa" < "b"      ==  true
+       #     assert ("aa" < "b")      ==  true
        redef fun <(other)
        do
                if self.object_id == other.object_id then return false