#
# assert "abAB12<>&".escape_to_c == "abAB12<>&"
# assert "\n\"'\\".escape_to_c == "\\n\\\"\\'\\\\"
+ #
+ # Most non-printable characters (bellow ASCII 32) are escaped to an octal form `\nnn`.
+ # Three digits are always used to avoid following digits to be interpreted as an element
+ # of the octal sequence.
+ #
+ # assert "{0.ascii}{1.ascii}{8.ascii}{31.ascii}{32.ascii}".escape_to_c == "\\000\\001\\010\\037 "
+ #
+ # The exceptions are the common `\t` and `\n`.
fun escape_to_c: String
do
var b = new FlatBuffer
var c = chars[i]
if c == '\n' then
b.append("\\n")
+ else if c == '\t' then
+ b.append("\\t")
else if c == '\0' then
- b.append("\\0")
+ b.append("\\000")
else if c == '"' then
b.append("\\\"")
else if c == '\'' then
else if c == '\\' then
b.append("\\\\")
else if c.ascii < 32 then
- b.append("\\{c.ascii.to_base(8, false)}")
+ b.add('\\')
+ var oct = c.ascii.to_base(8, false)
+ # Force 3 octal digits since it is the
+ # maximum allowed in the C specification
+ if oct.length == 1 then
+ b.add('0')
+ b.add('0')
+ else if oct.length == 2 then
+ b.add('0')
+ end
+ b.append(oct)
else
b.add(c)
end
# Real items, used as cache for to_cstring is called
private var real_items: nullable NativeString = null
+ # Returns a char* starting at position `index_from`
+ #
+ # WARNING: If you choose to use this service, be careful of the following.
+ #
+ # Strings and NativeString 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.
+ # (Failure to do so will most certainly result in long and painful debugging hours)
+ #
+ # The only safe use of this pointer is if it is ephemeral (e.g. read in a C function
+ # then immediately return).
+ #
+ # 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.
+ private fun fast_cstring: NativeString is abstract
+
redef var length: Int = 0
redef fun output
return native.to_s_with_length(self.length)
end
+ redef fun fast_cstring do return items.fast_cstring(index_from)
+
redef fun substring(from, count)
do
assert count >= 0
private var capacity: Int = 0
+ redef fun fast_cstring do return items.fast_cstring(0)
+
redef fun substrings do return new FlatSubstringsIter(self)
# Re-copies the `NativeString` into a new one and sets it as the new `Buffer`
# Creates a new NativeString with a capacity of `length`
new(length: Int) is intern
+ # Returns a char* starting at `index`.
+ #
+ # WARNING: Unsafe for extern code, use only for temporary
+ # pointer manipulation purposes (e.g. write to file or such)
+ fun fast_cstring(index: Int): NativeString is intern
+
# Get char at `index`.
fun [](index: Int): Char is intern