var myitems = _items
var itsitems = str._items
if myindex > length or itsindex > myindex then return false
- var its_index_from = str._indexFrom
+ var its_index_from = str._index_from
itsindex += its_index_from
while itsindex >= its_index_from do
if myitems[myindex] != itsitems[itsindex] then return false
return s.to_s
end
+ # Trims trailing and preceding white spaces
+ # A whitespace is defined as any character which ascii value is less than or equal to 32
+ fun trim: String
+ do
+ if self._length == 0 then return self.to_s
+ # find position of the first non white space char (ascii < 32) from the start of the string
+ var start_pos = 0
+ while self[start_pos].ascii <= 32 do
+ start_pos += 1
+ if start_pos == _length then return ""
+ end
+ # find position of the first non white space char from the end of the string
+ var end_pos = length - 1
+ while self[end_pos].ascii <= 32 do
+ end_pos -= 1
+ if end_pos == start_pos then return self[start_pos].to_s
+ end
+ return self.substring(start_pos, end_pos - start_pos + 1)
+ end
redef fun output
do
redef type OTHER: String
- readable var _indexFrom: Int
- readable var _indexTo: Int
+ # Index in _items of the start of the string
+ readable var _index_from: Int
+
+ # Indes in _items of the last item of the string
+ readable var _index_to: Int
################################################
# AbstractString specific methods #
#
redef fun [](index) do
assert index >= 0
- assert (index + _indexFrom) < (_indexFrom + _length)
- return items[index + _indexFrom]
+ # Check that the index (+ index_from) is not larger than indexTo
+ # In other terms, if the index is valid
+ assert (index + _index_from) <= _index_to
+ return _items[index + _index_from]
end
# Create a substring.
#
# "abcd".substring(1, 2) # --> "bc"
# "abcd".substring(-1, 2) # --> "a"
- # "abcd".substring(1, 0) # --> ""
- # "abcd".substring(2, 5) # --> "cd"
+ # "abcd".substring(1, 0) # --> ""
+ # "abcd".substring(2, 5) # --> "cd"
+ #
+ # A "from" index < 0 will be replaced by 0
+ # Unless a count value is > 0 at the same time
+ # In this case, from += count and count -= from
+ #
redef fun substring(from: Int, count: Int): String
do
assert count >= 0
from = 0
end
- var realFrom = _indexFrom + from
+ var realFrom = _index_from + from
- if (realFrom + count) > _indexTo then return new String.from_substring(realFrom, _indexTo, _items)
+ if (realFrom + count) > _index_to then return new String.from_substring(realFrom, _index_to, _items)
if count == 0 then return ""
# Create a substring from `self' beginning at the 'from' position
#
- # "abcd".substring(1) # --> "bcd"
- # "abcd".substring(-1) # --> "abcd"
- # "abcd".substring(2) # --> "cd"
+ # "abcd".substring_from(1) # --> "bcd"
+ # "abcd".substring_from(-1) # --> "abcd"
+ # "abcd".substring_from(2) # --> "cd"
+ #
+ # As with substring, a "from" index < 0 will be replaced by 0
+ #
redef fun substring_from(from: Int): String
do
if from > _length then return ""
if myindex > _length or itsindex > myindex then return false
- var itsindexfrom = str.indexFrom
+ var itsindexfrom = str.index_from
itsindex += itsindexfrom
- myindex += indexFrom
+ myindex += index_from
while itsindex >= itsindexfrom do
if myitems[myindex] != itsitems[itsindex] then return false
redef fun to_upper: String
do
var outstr = calloc_string(self._length + 1)
- var index = 0
+ var out_index = 0
var myitems = self._items
- var index_from = self._indexFrom
- var max = self._indexTo
+ var index_from = self._index_from
+ var max = self._index_to
while index_from <= max do
- outstr[index] = myitems[index_from].to_upper
- index += 1
+ outstr[out_index] = myitems[index_from].to_upper
+ out_index += 1
index_from += 1
end
redef fun to_lower : String
do
var outstr = calloc_string(self._length + 1)
- var index = 0
+ var out_index = 0
var myitems = self._items
- var index_from = self._indexFrom
- var max = self._indexTo
+ var index_from = self._index_from
+ var max = self._index_to
while index_from <= max do
- outstr[index] = myitems[index_from].to_lower
- index += 1
+ outstr[out_index] = myitems[index_from].to_lower
+ out_index += 1
index_from += 1
end
return new String.with_native(outstr, self._length)
end
+ redef fun trim: String
+ do
+ if self._length == 0 then return self
+ # find position of the first non white space char (ascii < 32) from the start of the string
+ var start_pos = self._index_from
+ while _items[start_pos].ascii <= 32 do
+ start_pos += 1
+ if start_pos == _index_to + 1 then return ""
+ end
+ # find position of the first non white space char from the end of the string
+ var end_pos = _index_to
+ while _items[end_pos].ascii <= 32 do
+ end_pos -= 1
+ if end_pos == start_pos then return _items[start_pos].to_s
+ end
+ start_pos -= index_from
+ end_pos -= index_from
+ return self.substring(start_pos, end_pos - start_pos + 1)
+ end
+
redef fun output
do
- var i = self._indexFrom
- while i < length do
+ var i = self._index_from
+ var imax = self._index_to
+ while i <= imax do
_items[i].output
i += 1
end
##################################################
# Creates a String object as a substring of another String
+ #
+ # From : index to start at
+ #
+ # To : Index to stop at (from + count -1)
+ #
private init from_substring(from: Int, to: Int, internalString: NativeString)
do
_items = internalString
- _indexFrom = from
- _indexTo = to
+ _index_from = from
+ _index_to = to
_length = to - from + 1
end
assert size >= 0
_items = nat
_length = size
- _indexFrom = 0
- _indexTo = size - 1
+ _index_from = 0
+ _index_to = _length - 1
end
# Create a new string from a null terminated char *.
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
+ 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
+
# Return a null terminated char *
fun to_cstring: NativeString
do
#return items
- if _indexFrom > 0 or _indexTo != items.cstring_length-1 then
- var newItems = calloc_string(length+1)
- self.items.copy_to(newItems, _length, _indexFrom, 0)
+ if _index_from > 0 or _index_to != items.cstring_length - 1 then
+ var newItems = calloc_string(_length + 1)
+ self.items.copy_to(newItems, _length, _index_from, 0)
newItems[length] = '\0'
return newItems
end
return _items
end
- redef fun ==(o)
+ redef fun ==(other)
do
- if not o isa String or o is null then return false
+ if not other isa String or other is null then return false
+
+ if self.object_id == other.object_id then return true
- if self.object_id == o.object_id then return true
+ var my_length = _length
- var l = _length
+ if other._length != my_length then return false
- if o._length != l then return false
+ var my_index = _index_from
+ var its_index = other._index_from
- var i = _indexFrom
- var j = o._indexFrom
- var max = l + _indexFrom
- var itsitems = o._items
+ var last_iteration = my_index + my_length
+
+ var itsitems = other._items
var myitems = self._items
- while i < max do
- if myitems[i] != itsitems[j] then return false
- i += 1
- j += 1
+ while my_index < last_iteration do
+ if myitems[my_index] != itsitems[its_index] then return false
+ my_index += 1
+ its_index += 1
end
return true
end
- redef fun <(s)
+ # The comparison between two strings is done on a lexicographical basis
+ # Eg : "aa" < "b" => true
+ redef fun <(other)
do
- if self.object_id == s.object_id then return false
+ if self.object_id == other.object_id then return false
+
+ var my_curr_char : Char
+ var its_curr_char : Char
+
+ var curr_id_self = self._index_from
+ var curr_id_other = other._index_from
- var c1 : Int
- var c2 : Int
- var currIdSelf = self._indexFrom
- var currIdOther = s._indexFrom
var my_items = self._items
- var its_items = s._items
+ var its_items = other._items
- var self_upper_bound = self._length + currIdSelf
- var other_upper_bound = s._length + currIdOther
+ var my_length = self._length
+ var its_length = other._length
- while currIdSelf < self_upper_bound and currIdOther < other_upper_bound do
- c1 = my_items[currIdSelf].ascii
- c2 = its_items[currIdOther].ascii
+ var max_iterations = curr_id_self + my_length
- if c1 < c2 then
- return true
- else if c2 < c1 then
+ while curr_id_self < max_iterations do
+ my_curr_char = my_items[curr_id_self]
+ its_curr_char = its_items[curr_id_other]
+
+ if my_curr_char != its_curr_char then
+ if my_curr_char < its_curr_char then return true
return false
end
- currIdSelf += 1
- currIdOther += 1
+ curr_id_self += 1
+ curr_id_other += 1
end
- if self._length < s._length then
- return true
- else
- return false
- end
+ return my_length < its_length
end
# The concatenation of `self' with `r'
fun +(s: String): String
do
- var newString = calloc_string(_length + s._length + 1)
+ var my_length = self._length
+ var its_length = s._length
+
+ var target_string = calloc_string(my_length + its_length + 1)
- self._items.copy_to(newString, _length, _indexFrom, 0)
- s._items.copy_to(newString, s._length, s._indexFrom, _length)
+ self._items.copy_to(target_string, my_length, _index_from, 0)
+ s._items.copy_to(target_string, its_length, s._index_from, my_length)
- newString[self._length + s._length] = '\0'
+ target_string[my_length + its_length] = '\0'
- return new String.with_native(newString, _length + s._length)
+ return new String.with_native(target_string, my_length + its_length)
end
# i repetitions of self
fun *(i: Int): String
do
assert i >= 0
- var r = calloc_string((_length * i) + 1)
- r[_length * i] = '\0'
+ var my_length = self._length
- var lastStr = new String.with_native(r, (_length * i))
+ var final_length = my_length * i
- while i > 0 do
- self._items.copy_to(r, _length, _indexFrom, _length*(i-1))
- i -= 1
+ var my_items = self._items
+
+ var target_string = calloc_string((final_length) + 1)
+
+ target_string[final_length] = '\0'
+
+ var current_last = 0
+
+ for iteration in [1 .. i] do
+ my_items.copy_to(target_string, my_length, 0, current_last)
+ current_last += my_length
end
- return lastStr
+ return new String.with_native(target_string, final_length)
end
redef fun to_s do return self
var h = 5381
var i = _length - 1
- var myitems = self.items
- var index_from = self._indexFrom
+ var myitems = _items
+ var strStart = _index_from
- i += index_from
+ i += strStart
- while i >= index_from do
+ while i >= strStart do
h = (h * 32) + h + self._items[i].ascii
i -= 1
end
if s isa String then
var sl = s.length
if _capacity < _length + sl then enlarge(_length + sl)
- s.items.copy_to(_items, sl, s._indexFrom, _length)
+ s.items.copy_to(_items, sl, s._index_from, _length)
_length += sl
else
super
_capacity = s.length + 1
_length = s.length
_items = calloc_string(_capacity)
- s.items.copy_to(_items, _length, s._indexFrom, 0)
+ s.items.copy_to(_items, _length, s._index_from, 0)
end
# Create a new empty string with a given capacity.