X-Git-Url: http://nitlanguage.org diff --git a/lib/core/text/abstract_text.nit b/lib/core/text/abstract_text.nit index 02f2539..3f37a81 100644 --- a/lib/core/text/abstract_text.nit +++ b/lib/core/text/abstract_text.nit @@ -83,6 +83,9 @@ abstract class Text # implementation of an empty string. protected fun empty: SELFTYPE is abstract + # Returns a copy of `self` as a Buffer + fun to_buffer: Buffer is abstract + # Gets the first char of the Text # # DEPRECATED : Use self.chars.first instead @@ -136,7 +139,7 @@ abstract class Text end # Return a null terminated char * - fun to_cstring: NativeString is abstract + fun to_cstring: CString is abstract # The index of the last occurrence of an element starting from pos (in reverse order). # @@ -149,6 +152,12 @@ abstract class Text # DEPRECATED : Use self.chars.last_index_of_from instead fun last_index_of_from(item: Char, pos: Int): Int do return chars.last_index_of_from(item, pos) + # Concatenates `o` to `self` + # + # assert "hello" + "world" == "helloworld" + # assert "" + "hello" + "" == "hello" + fun +(o: Text): SELFTYPE is abstract + # Gets an iterator on the chars of self # # DEPRECATED : Use self.chars.iterator instead @@ -780,17 +789,17 @@ abstract class Text if pos == null then pos = 0 if ln == null then ln = length - pos if ln < 6 then return 0xFFFD.code_point - var cp = from_utf16_digit(pos + 2) - if cp < 0xD800 then return cp.code_point - if cp > 0xDFFF then return cp.code_point - if cp > 0xDBFF then return 0xFFFD.code_point + var cp = from_utf16_digit(pos + 2).to_u32 + if cp < 0xD800u32 then return cp.code_point + if cp > 0xDFFFu32 then return cp.code_point + if cp > 0xDBFFu32 then return 0xFFFD.code_point if ln == 6 then return 0xFFFD.code_point if ln < 12 then return 0xFFFD.code_point cp <<= 16 - cp += from_utf16_digit(pos + 8) - var cplo = cp & 0xFFFF - if cplo < 0xDC00 then return 0xFFFD.code_point - if cplo > 0xDFFF then return 0xFFFD.code_point + cp += from_utf16_digit(pos + 8).to_u32 + var cplo = cp & 0xFFFFu32 + if cplo < 0xDC00u32 then return 0xFFFD.code_point + if cplo > 0xDFFFu32 then return 0xFFFD.code_point return cp.from_utf16_surr.code_point end @@ -834,15 +843,16 @@ abstract class Text # Decode `self` from percent (or URL) encoding to a clear string # - # Replace invalid use of '%' with '?'. + # Invalid '%' are not decoded. # # assert "aBc09-._~".from_percent_encoding == "aBc09-._~" # assert "%25%28%29%3c%20%3e".from_percent_encoding == "%()< >" # assert ".com%2fpost%3fe%3dasdf%26f%3d123".from_percent_encoding == ".com/post?e=asdf&f=123" # assert "%25%28%29%3C%20%3E".from_percent_encoding == "%()< >" - # assert "incomplete %".from_percent_encoding == "incomplete ?" - # assert "invalid % usage".from_percent_encoding == "invalid ? usage" + # assert "incomplete %".from_percent_encoding == "incomplete %" + # assert "invalid % usage".from_percent_encoding == "invalid % usage" # assert "%c3%a9%e3%81%82%e3%81%84%e3%81%86".from_percent_encoding == "éあいう" + # assert "%1 %A %C3%A9A9".from_percent_encoding == "%1 %A éA9" fun from_percent_encoding: String do var len = byte_length @@ -857,7 +867,7 @@ abstract class Text # If no transformation is needed, return self as a string if not has_percent then return to_s - var buf = new NativeString(len) + var buf = new CString(len) var i = 0 var l = 0 while i < length do @@ -865,7 +875,7 @@ abstract class Text if c == '%' then if i + 2 >= length then # What follows % has been cut off - buf[l] = '?'.ascii + buf[l] = '%'.ascii else i += 1 var hex_s = substring(i, 2) @@ -875,7 +885,7 @@ abstract class Text i += 1 else # What follows a % is not Hex - buf[l] = '?'.ascii + buf[l] = '%'.ascii i -= 1 end end @@ -885,7 +895,7 @@ abstract class Text l += 1 end - return buf.to_s_unsafe(l) + return buf.to_s_unsafe(l, copy=false) end # Escape the characters `<`, `>`, `&`, `"`, `'` and `/` as HTML/XML entity references. @@ -1099,15 +1109,15 @@ abstract class Text # Copies `n` bytes from `self` at `src_offset` into `dest` starting at `dest_offset` # - # Basically a high-level synonym of NativeString::copy_to + # Basically a high-level synonym of CString::copy_to # # REQUIRE: `n` must be large enough to contain `len` bytes # - # var ns = new NativeString(8) + # var ns = new CString(8) # "Text is String".copy_to_native(ns, 8, 2, 0) - # assert ns.to_s_unsafe(8) == "xt is St" + # assert ns.to_s_with_length(8) == "xt is St" # - fun copy_to_native(dest: NativeString, n, src_offset, dest_offset: Int) do + fun copy_to_native(dest: CString, n, src_offset, dest_offset: Int) do var mypos = src_offset var itspos = dest_offset while n > 0 do @@ -1151,23 +1161,125 @@ abstract class Text end return retarr.reversed end + + # Concatenates self `i` times + # + #~~~nit + # assert "abc" * 4 == "abcabcabcabc" + # assert "abc" * 1 == "abc" + # assert "abc" * 0 == "" + # var b = new Buffer + # b.append("天地") + # b = b * 4 + # assert b == "天地天地天地天地" + #~~~ + fun *(i: Int): SELFTYPE is abstract + + # Insert `s` at `pos`. + # + #~~~nit + # assert "helloworld".insert_at(" ", 5) == "hello world" + # var b = new Buffer + # b.append("Hello世界") + # b = b.insert_at(" beautiful ", 5) + # assert b == "Hello beautiful 世界" + #~~~ + fun insert_at(s: String, pos: Int): SELFTYPE is abstract + + # Returns a reversed version of self + # + # assert "hello".reversed == "olleh" + # assert "bob".reversed == "bob" + # assert "".reversed == "" + fun reversed: SELFTYPE is abstract + + # A upper case version of `self` + # + # assert "Hello World!".to_upper == "HELLO WORLD!" + fun to_upper: SELFTYPE is abstract + + # A lower case version of `self` + # + # assert "Hello World!".to_lower == "hello world!" + fun to_lower : SELFTYPE is abstract + + # Takes a camel case `self` and converts it to snake case + # + # assert "randomMethodId".to_snake_case == "random_method_id" + # + # The rules are the following: + # + # An uppercase is always converted to a lowercase + # + # assert "HELLO_WORLD".to_snake_case == "hello_world" + # + # An uppercase that follows a lowercase is prefixed with an underscore + # + # assert "HelloTheWORLD".to_snake_case == "hello_the_world" + # + # An uppercase that follows an uppercase and is followed by a lowercase, is prefixed with an underscore + # + # assert "HelloTHEWorld".to_snake_case == "hello_the_world" + # + # All other characters are kept as is; `self` does not need to be a proper CamelCased string. + # + # assert "=-_H3ll0Th3W0rld_-=".to_snake_case == "=-_h3ll0th3w0rld_-=" + fun to_snake_case: SELFTYPE is abstract + + # Takes a snake case `self` and converts it to camel case + # + # assert "random_method_id".to_camel_case == "randomMethodId" + # + # If the identifier is prefixed by an underscore, the underscore is ignored + # + # assert "_private_field".to_camel_case == "_privateField" + # + # If `self` is upper, it is returned unchanged + # + # assert "RANDOM_ID".to_camel_case == "RANDOM_ID" + # + # If there are several consecutive underscores, they are considered as a single one + # + # assert "random__method_id".to_camel_case == "randomMethodId" + fun to_camel_case: SELFTYPE is abstract + + # Returns a capitalized `self` + # + # Letters that follow a letter are lowercased + # Letters that follow a non-letter are upcased. + # + # If `keep_upper = true`, already uppercase letters are not lowercased. + # + # 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" + # assert "preserve my ACRONYMS".capitalized(keep_upper=true) == "Preserve My ACRONYMS" + fun capitalized(keep_upper: nullable Bool): SELFTYPE do + if length == 0 then return self + + var buf = new Buffer.with_cap(length) + buf.capitalize(keep_upper=keep_upper, src=self) + return buf.to_s + end end # All kinds of array-based text representations. abstract class FlatText super Text - # Underlying C-String (`char*`) + # Underlying CString (`char*`) # - # Warning : Might be void in some subclasses, be sure to check + # Warning: Might be void in some subclasses, be sure to check # if set before using it. - var items: NativeString is noinit + var items: CString is noinit # Returns a char* starting at position `first_byte` # # WARNING: If you choose to use this service, be careful of the following. # - # Strings and NativeString are *ideally* always allocated through a Garbage Collector. + # Strings and CString are *ideally* always allocated through a Garbage Collector. # Since the GC tracks the use of the pointer for the beginning of the char*, it may be # deallocated at any moment, rendering the pointer returned by this function invalid. # Any access to freed memory may very likely cause undefined behaviour or a crash. @@ -1178,7 +1290,7 @@ abstract class FlatText # # As always, do not modify the content of the String in C code, if this is what you want # copy locally the char* as Nit Strings are immutable. - fun fast_cstring: NativeString is abstract + fun fast_cstring: CString is abstract redef var length = 0 @@ -1247,157 +1359,25 @@ abstract class String redef fun to_s do return self redef fun clone do return self - # Concatenates `o` to `self` - # - # assert "hello" + "world" == "helloworld" - # assert "" + "hello" + "" == "hello" - fun +(o: Text): SELFTYPE is abstract - # Concatenates self `i` times - # - # assert "abc" * 4 == "abcabcabcabc" - # assert "abc" * 1 == "abc" - # assert "abc" * 0 == "" - fun *(i: Int): SELFTYPE is abstract - - # Insert `s` at `pos`. - # - # assert "helloworld".insert_at(" ", 5) == "hello world" - fun insert_at(s: String, pos: Int): SELFTYPE is abstract - - redef fun substrings is abstract - - # Returns a reversed version of self - # - # assert "hello".reversed == "olleh" - # assert "bob".reversed == "bob" - # assert "".reversed == "" - fun reversed: SELFTYPE is abstract - - # A upper case version of `self` - # - # assert "Hello World!".to_upper == "HELLO WORLD!" - fun to_upper: SELFTYPE is abstract - - # A lower case version of `self` - # - # assert "Hello World!".to_lower == "hello world!" - fun to_lower : SELFTYPE is abstract - - # Takes a camel case `self` and converts it to snake case - # - # assert "randomMethodId".to_snake_case == "random_method_id" - # - # The rules are the following: - # - # An uppercase is always converted to a lowercase - # - # assert "HELLO_WORLD".to_snake_case == "hello_world" - # - # An uppercase that follows a lowercase is prefixed with an underscore - # - # assert "HelloTheWORLD".to_snake_case == "hello_the_world" - # - # An uppercase that follows an uppercase and is followed by a lowercase, is prefixed with an underscore - # - # assert "HelloTHEWorld".to_snake_case == "hello_the_world" - # - # All other characters are kept as is; `self` does not need to be a proper CamelCased string. - # - # assert "=-_H3ll0Th3W0rld_-=".to_snake_case == "=-_h3ll0th3w0rld_-=" - fun to_snake_case: SELFTYPE - do - if self.is_lower then return self + redef fun to_buffer do return new Buffer.from_text(self) - var new_str = new Buffer.with_cap(self.length) - var prev_is_lower = false - var prev_is_upper = false - - for i in [0..length[ do - var char = chars[i] - if char.is_lower then - new_str.add(char) - prev_is_lower = true - prev_is_upper = false - else if char.is_upper then - if prev_is_lower then - new_str.add('_') - else if prev_is_upper and i+1 < length and chars[i+1].is_lower then - new_str.add('_') - end - new_str.add(char.to_lower) - prev_is_lower = false - prev_is_upper = true - else - new_str.add(char) - prev_is_lower = false - prev_is_upper = false - end - end - - return new_str.to_s - end - - # Takes a snake case `self` and converts it to camel case - # - # assert "random_method_id".to_camel_case == "randomMethodId" - # - # If the identifier is prefixed by an underscore, the underscore is ignored - # - # assert "_private_field".to_camel_case == "_privateField" - # - # If `self` is upper, it is returned unchanged - # - # assert "RANDOM_ID".to_camel_case == "RANDOM_ID" - # - # If there are several consecutive underscores, they are considered as a single one - # - # assert "random__method_id".to_camel_case == "randomMethodId" - fun to_camel_case: SELFTYPE - do + redef fun to_camel_case do if self.is_upper then return self - var new_str = new Buffer - var is_first_char = true - var follows_us = false - - for i in [0..length[ do - var char = chars[i] - if is_first_char then - new_str.add(char) - is_first_char = false - else if char == '_' then - follows_us = true - else if follows_us then - new_str.add(char.to_upper) - follows_us = false - else - new_str.add(char) - end - end - + var new_str = new Buffer.with_cap(length) + new_str.append self + new_str.camel_case 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. - # - # If `keep_upper = true`, already uppercase letters are not lowercased. - # - # 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" - # assert "preserve my ACRONYMS".capitalized(keep_upper=true) == "Preserve My ACRONYMS" - fun capitalized(keep_upper: nullable Bool): SELFTYPE do - if length == 0 then return self + redef fun to_snake_case do + if self.is_lower then return self - var buf = new Buffer.with_cap(length) - buf.capitalize(keep_upper=keep_upper, src=self) - return buf.to_s + var new_str = new Buffer.with_cap(self.length) + new_str.append self + new_str.snake_case + return new_str.to_s end end @@ -1411,6 +1391,13 @@ abstract class Buffer # Returns an instance of a subclass of `Buffer` with `i` base capacity new with_cap(i: Int) is abstract + # Returns an instance of a subclass of `Buffer` with `t` as content + new from_text(t: Text) do + var ret = new Buffer.with_cap(t.byte_length) + ret.append t + return ret + end + redef type SELFTYPE: Buffer is fixed # Copy-On-Write flag @@ -1426,6 +1413,8 @@ abstract class Buffer # DEPRECATED : Use self.chars.[]= instead fun []=(index: Int, item: Char) is abstract + redef fun to_buffer do return clone + #~~~nit # var b = new Buffer # b.append("Buffer!") @@ -1583,11 +1572,152 @@ abstract class Buffer # NOTE: Use only if sure about `from` and `length`, no checks # or bound recalculation is done fun append_substring_impl(s: Text, from, length: Int) do - var pos = from - for i in [0 .. length[ do - self.add s[pos] + var max = from + length + for i in [from .. max[ do add s[i] + end + + redef fun *(i) do + var ret = new Buffer.with_cap(byte_length * i) + for its in [0 .. i[ do ret.append self + return ret + end + + redef fun insert_at(s, pos) do + var obuf = new Buffer.with_cap(byte_length + s.byte_length) + obuf.append_substring(self, 0, pos) + obuf.append s + obuf.append_substring(self, pos, length - pos) + return obuf + end + + # Inserts `s` at position `pos` + # + #~~~nit + # var b = new Buffer + # b.append "美しい世界" + # b.insert(" nit ", 3) + # assert b == "美しい nit 世界" + #~~~ + fun insert(s: Text, pos: Int) is abstract + + # Inserts `c` at position `pos` + # + #~~~nit + # var b = new Buffer + # b.append "美しい世界" + # b.insert_char(' ', 3) + # assert b == "美しい 世界" + #~~~ + fun insert_char(c: Char, pos: Int) is abstract + + # Removes a substring from `self` at position `pos` + # + # NOTE: `length` defaults to 1, expressed in chars + # + #~~~nit + # var b = new Buffer + # b.append("美しい 世界") + # b.remove_at(3) + # assert b == "美しい世界" + # b.remove_at(1, 2) + # assert b == "美世界" + #~~~ + fun remove_at(pos: Int, length: nullable Int) is abstract + + redef fun reversed do + var ret = clone + ret.reverse + return ret + end + + redef fun to_upper do + var ret = clone + ret.upper + return ret + end + + redef fun to_lower do + var ret = clone + ret.lower + return ret + end + + redef fun to_snake_case do + var ret = clone + ret.snake_case + return ret + end + + # Takes a camel case `self` and converts it to snake case + # + # SEE: `to_snake_case` + fun snake_case do + if self.is_lower then return + var prev_is_lower = false + var prev_is_upper = false + + var i = 0 + while i < length do + var char = chars[i] + if char.is_lower then + prev_is_lower = true + prev_is_upper = false + else if char.is_upper then + if prev_is_lower then + insert_char('_', i) + i += 1 + else if prev_is_upper and i + 1 < length and self[i + 1].is_lower then + insert_char('_', i) + i += 1 + end + self[i] = char.to_lower + prev_is_lower = false + prev_is_upper = true + else + prev_is_lower = false + prev_is_upper = false + end + i += 1 + end + end + + redef fun to_camel_case + do + var new_str = clone + new_str.camel_case + return new_str + end + + # Takes a snake case `self` and converts it to camel case + # + # SEE: `to_camel_case` + fun camel_case do + if is_upper then return + + var underscore_count = 0 + + var pos = 1 + while pos < length do + var char = self[pos] + if char == '_' then + underscore_count += 1 + else if underscore_count > 0 then + pos -= underscore_count + remove_at(pos, underscore_count) + self[pos] = char.to_upper + underscore_count = 0 + end pos += 1 end + if underscore_count > 0 then remove_at(pos - underscore_count - 1, underscore_count) + end + + redef fun capitalized(keep_upper) do + if length == 0 then return self + + var buf = new Buffer.with_cap(byte_length) + buf.capitalize(keep_upper=keep_upper, src=self) + return buf end end @@ -1613,8 +1743,8 @@ redef class Object # User readable representation of `self`. fun to_s: String do return inspect - # The class name of the object in NativeString format. - private fun native_class_name: NativeString is intern + # The class name of the object in CString format. + private fun native_class_name: CString is intern # The class name of the object. # @@ -1650,13 +1780,13 @@ redef class Bool end redef class Byte - # C function to calculate the length of the `NativeString` to receive `self` + # C function to calculate the length of the `CString` to receive `self` private fun byte_to_s_len: Int `{ return snprintf(NULL, 0, "0x%02x", self); `} - # C function to convert an nit Int to a NativeString (char*) - private fun native_byte_to_s(nstr: NativeString, strlen: Int) `{ + # C function to convert an nit Int to a CString (char*) + private fun native_byte_to_s(nstr: CString, strlen: Int) `{ snprintf(nstr, strlen, "0x%02x", self); `} @@ -1666,17 +1796,17 @@ redef class Byte # assert (-123).to_b.to_s == "0x85" redef fun to_s do var nslen = byte_to_s_len - var ns = new NativeString(nslen + 1) + var ns = new CString(nslen + 1) ns[nslen] = 0u8 native_byte_to_s(ns, nslen + 1) - return ns.to_s_unsafe(nslen) + return ns.to_s_unsafe(nslen, copy=false, clean=false) end end redef class Int # Wrapper of strerror C function - private fun strerror_ext: NativeString `{ return strerror((int)self); `} + private fun strerror_ext: CString `{ return strerror((int)self); `} # Returns a string describing error number fun strerror: String do return strerror_ext.to_s @@ -1705,13 +1835,13 @@ redef class Int end end - # C function to calculate the length of the `NativeString` to receive `self` + # C function to calculate the length of the `CString` to receive `self` private fun int_to_s_len: Int `{ return snprintf(NULL, 0, "%ld", self); `} - # C function to convert an nit Int to a NativeString (char*) - private fun native_int_to_s(nstr: NativeString, strlen: Int) `{ + # C function to convert an nit Int to a CString (char*) + private fun native_int_to_s(nstr: CString, strlen: Int) `{ snprintf(nstr, strlen, "%ld", self); `} @@ -1785,35 +1915,23 @@ redef class Float return "-inf" end - if decimals == 0 then return self.to_i.to_s - var f = self - for i in [0..decimals[ do f = f * 10.0 - if self > 0.0 then - f = f + 0.5 - else - f = f - 0.5 - end - var i = f.to_i - if i == 0 then return "0." + "0"*decimals - - # Prepare both parts of the float, before and after the "." - var s = i.abs.to_s - var sl = s.length - var p1 - var p2 - if sl > decimals then - # Has something before the "." - p1 = s.substring(0, sl-decimals) - p2 = s.substring(sl-decimals, decimals) - else - p1 = "0" - p2 = "0"*(decimals-sl) + s - end + var size = to_precision_size(decimals) + var cstr = new CString(size+1) + to_precision_fill(decimals, size+1, cstr) + return cstr.to_s_unsafe(byte_length=size, copy=false) + end - if i < 0 then p1 = "-" + p1 + # Required string length to hold `self` with `nb` decimals + # + # The length does not include the terminating null byte. + private fun to_precision_size(nb: Int): Int `{ + return snprintf(NULL, 0, "%.*f", (int)nb, self); + `} - return p1 + "." + p2 - end + # Fill `cstr` with `self` and `nb` decimals + private fun to_precision_fill(nb, size: Int, cstr: CString) `{ + snprintf(cstr, size, "%.*f", (int)nb, self); + `} end redef class Char @@ -1856,9 +1974,9 @@ redef class Char # assert 'x'.to_s == "x" redef fun to_s do var ln = u8char_len - var ns = new NativeString(ln + 1) + var ns = new CString(ln + 1) u8char_tos(ns, ln) - return ns.to_s_unsafe(ln) + return ns.to_s_unsafe(ln, copy=false, clean=false) end # Returns `self` escaped to UTF-16 @@ -1901,7 +2019,7 @@ redef class Char return buf.to_s end - private fun u8char_tos(r: NativeString, len: Int) `{ + private fun u8char_tos(r: CString, len: Int) `{ r[len] = '\0'; switch(len){ case 1: @@ -2105,7 +2223,7 @@ redef class Sys private fun native_argc: Int is intern # Second argument of the main C function. - private fun native_argv(i: Int): NativeString is intern + private fun native_argv(i: Int): CString is intern end # Comparator that efficienlty use `to_s` to compare things @@ -2165,49 +2283,40 @@ do return sys.program_args end -redef class NativeString - # Get a `String` from the data at `self` copied into Nit memory - # - # Require: `self` is a null-terminated string. - fun to_s_with_copy: String is abstract +redef class CString - # Get a `String` from `length` bytes at `self` + # Get a `String` from the data at `self` (with unsafe options) # - # The result may point to the data at `self` or - # it may make a copy in Nit controlled memory. - # This method should only be used when `self` was allocated by the Nit GC, - # or when manually controlling the deallocation of `self`. - fun to_s_with_length(length: Int): String is abstract - - # Get a `String` from the raw `length` bytes at `self` + # The default behavior is the safest and equivalent to `to_s`. # - # The default value of `length` is the number of bytes before - # the first null character. + # Options: # - # The created `String` points to the data at `self`. - # This method should be used when `self` was allocated by the Nit GC, - # or when manually controlling the deallocation of `self`. + # * Set `byte_length` to the number of bytes to use as data. + # Otherwise, this method searches for a terminating null byte. # - # /!\: This service does not clean the items for compliance with UTF-8, - # use only when the data has already been verified as valid UTF-8. - fun to_s_unsafe(length: nullable Int): String is abstract - - # Get a `String` from the raw `byte_length` bytes at `self` with `unilen` Unicode characters + # * Set `char_length` to the number of Unicode character in the string. + # Otherwise, the data is read to count the characters. + # Ignored if `clean == true`. # - # The created `String` points to the data at `self`. - # This method should be used when `self` was allocated by the Nit GC, - # or when manually controlling the deallocation of `self`. + # * If `copy == true`, the default, copies the data at `self` in the + # Nit GC allocated memory. Otherwise, the return may still point to + # the data at `self`. # - # /!\: This service does not clean the items for compliance with UTF-8, - # use only when the data has already been verified as valid UTF-8. + # * If `clean == true`, the default, the string is cleaned of invalid UTF-8 + # characters. If cleaning is necessary, the data is copied into Nit GC + # managed memory, whether or not `copy == true`. + # Don't clean only when the data has already been verified as valid UTF-8, + # other library services rely on UTF-8 compliant characters. + fun to_s_unsafe(byte_length, char_length: nullable Int, copy, clean: nullable Bool): String is abstract + + # Retro-compatibility service use by execution engines # - # SEE: `abstract_text::Text` for more info on the difference - # between `Text::byte_length` and `Text::length`. - fun to_s_full(byte_length, unilen: Int): String is abstract + # TODO remove this method at the next c_src regen. + private fun to_s_full(byte_length, char_length: Int): String do return to_s_unsafe(byte_length, char_length, false, false) # Copies the content of `src` to `self` # - # NOTE: `self` must be large enough to withold `self.byte_length` bytes + # NOTE: `self` must be large enough to contain `self.byte_length` bytes fun fill_from(src: Text) do src.copy_to_native(self, src.byte_length, 0, 0) end