# 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>
# 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.
# 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
# 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`?
#
# 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
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.
_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
# 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