core: revamp `CString::to_s` services
authorAlexis Laferrière <alexis.laf@xymus.net>
Sat, 24 Dec 2016 12:57:51 +0000 (07:57 -0500)
committerAlexis Laferrière <alexis.laf@xymus.net>
Tue, 27 Dec 2016 19:06:35 +0000 (14:06 -0500)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

lib/core/text/abstract_text.nit
lib/core/text/flat.nit

index ba667df..38eceaf 100644 (file)
@@ -2295,48 +2295,34 @@ do
 end
 
 redef class CString
-       # 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
-
-       # Get a `String` from `length` bytes at `self`
-       #
-       # 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`
+       # Get a `String` from the data at `self` (with unsafe options)
        #
-       # The default value of `length` is the number of bytes before
-       # the first null character.
+       # The default behavior is the safest and equivalent to `to_s`.
        #
-       # 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`.
+       # Options:
        #
-       # /!\: 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 `byte_length` to the number of bytes to use as data.
+       #   Otherwise, this method searches for a terminating null byte.
        #
-       # 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 `char_length` to the number of Unicode character in the string.
+       #   Otherwise, the data is read to count the characters.
+       #   Ignored if `clean == true`.
        #
-       # /!\: 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 `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`.
        #
-       # 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
+       # * 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
 
        # 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
 
index 2c29d90..ac006db 100644 (file)
@@ -1308,37 +1308,44 @@ private class FlatBufferCharIterator
 end
 
 redef class CString
-       redef fun to_s
-       do
-               return to_s_with_length(cstring_length)
-       end
 
-       redef fun to_s_with_length(length)
-       do
-               assert length >= 0
-               return clean_utf8(length)
-       end
+       # Get a `String` from the data at `self` copied into Nit memory
+       #
+       # Require: `self` is a null-terminated string.
+       redef fun to_s do return to_s_unsafe
 
-       redef fun to_s_full(byte_length, unilen) do
-               return new FlatString.full(self, byte_length, 0, unilen)
-       end
+       # Get a `String` from `byte_length` bytes at `self` copied into Nit memory
+       #
+       # The string is cleaned.
+       fun to_s_with_length(byte_length: Int): String do return to_s_unsafe(byte_length)
 
-       redef fun to_s_unsafe(len) do
-               if len == null then len = cstring_length
-               return new FlatString.with_infos(self, len, 0)
-       end
+       redef fun to_s_unsafe(byte_length, char_length, copy, clean)
+       do
+               byte_length = byte_length or else cstring_length
+               clean = clean or else true
+               copy = copy or else true
+
+               # Clean?
+               var str = null
+               if clean then
+                       str = clean_utf8(byte_length)
+                       char_length = str.length
+               else
+                       char_length = char_length or else utf8_length(0, byte_length)
+               end
 
-       redef fun to_s_with_copy do return to_s_with_copy_and_length(cstring_length)
+               # Copy? (if not already copied by `clean_utf8`)
+               if copy and (str == null or str.items == self) then
+                       var new_cstr = new CString(byte_length + 1)
+                       copy_to(new_cstr, byte_length, 0, 0)
+                       new_cstr[byte_length] = 0u8
+                       str = new FlatString.full(new_cstr, byte_length, 0, char_length)
+               end
+
+               if str == null then
+                       str = new FlatString.full(self, byte_length, 0, char_length)
+               end
 
-       # Get a `String` from `length` bytes at `self` copied into Nit memory
-       fun to_s_with_copy_and_length(length: Int): String
-       do
-               var r = clean_utf8(length)
-               if r.items != self then return r
-               var new_self = new CString(length + 1)
-               copy_to(new_self, length, 0, 0)
-               var str = new FlatString.with_infos(new_self, length, 0)
-               new_self[length] = 0u8
                return str
        end