# Gets a view on the bytes of the Text object
#
# ~~~
- # assert "hello".bytes.to_a == [104u8, 101u8, 108u8, 108u8, 111u8]
+ # assert "hello".bytes.to_a == [104, 101, 108, 108, 111]
# ~~~
- fun bytes: SequenceRead[Byte] is abstract
+ fun bytes: SequenceRead[Int] is abstract
# Number of characters contained in self.
#
# assert "0x64".to_i == 100
# assert "0b1100_0011".to_i== 195
# assert "--12".to_i == 12
+ # assert "+45".to_i == 45
# ~~~
#
# REQUIRE: `self`.`is_int`
else if c == ':' or c == ' ' or c == '#' then
b.add('\\')
b.add(c)
- else if c.code_point < 32 or c == ';' or c == '|' or c == '\\' or c == '=' then
+ else if c.code_point < 32 or c == ';' or c == '|' or c == '\\' then
b.append("?{c.code_point.to_base(16)}")
else
b.add(c)
if c == '%' then
if i + 2 >= length then
# What follows % has been cut off
- buf[l] = '%'.ascii
+ buf[l] = u'%'
else
i += 1
var hex_s = substring(i, 2)
if hex_s.is_hex then
var hex_i = hex_s.to_hex
- buf[l] = hex_i.to_b
+ buf[l] = hex_i
i += 1
else
# What follows a % is not Hex
- buf[l] = '%'.ascii
+ buf[l] = u'%'
i -= 1
end
end
- else buf[l] = c.ascii
+ else buf[l] = c.code_point
i += 1
l += 1
# Abstract class for the SequenceRead compatible
# views on the bytes of any Text
private abstract class StringByteView
- super SequenceRead[Byte]
+ super SequenceRead[Int]
type SELFTYPE: Text
redef fun to_s do
var nslen = byte_to_s_len
var ns = new CString(nslen + 1)
- ns[nslen] = 0u8
+ ns[nslen] = 0
native_byte_to_s(ns, nslen + 1)
return ns.to_s_unsafe(nslen, copy=false, clean=false)
end
# ~~~
# assert 12.34.to_s == "12.34"
# assert (-0120.030).to_s == "-120.03"
+ # assert (-inf).to_s == "-inf"
+ # assert (nan).to_s == "nan"
# ~~~
#
# see `to_precision` for a custom precision.
redef fun to_s do
- var str = to_precision( 3 )
- if is_inf != 0 or is_nan then return str
- var len = str.length
+ var str = to_precision(3)
+ return adapt_number_of_decimal(str, false)
+ end
+
+ # Return the representation of `self`, with scientific notation
+ #
+ # Adpat the number of decimals as needed from 1 to a maximum of 6
+ # ~~~
+ # assert 12.34.to_sci == "1.234e+01"
+ # assert 123.45.to_sci.to_f.to_sci == "1.2345e+02"
+ # assert 0.001234.to_sci == "1.234e-03"
+ # assert (inf).to_sci == "inf"
+ # assert (nan).to_sci == "nan"
+ # ~~~
+ fun to_sci: String
+ do
+ var is_inf_or_nan = check_inf_or_nan
+ if is_inf_or_nan != null then return is_inf_or_nan
+ return adapt_number_of_decimal(return_from_specific_format("%e".to_cstring), true)
+ end
+
+ # Return the `string_number` with the adapted number of decimal (i.e the fonction remove the useless `0`)
+ # `is_expo` it's here to specifi if the given `string_number` is in scientific notation
+ private fun adapt_number_of_decimal(string_number: String, is_expo: Bool): String
+ do
+ # check if `self` does not need an adaptation of the decimal
+ if is_inf != 0 or is_nan then return string_number
+ var len = string_number.length
+ var expo_value = ""
+ var numeric_value = ""
for i in [0..len-1] do
- var j = len-1-i
- var c = str.chars[j]
- if c == '0' then
- continue
- else if c == '.' then
- return str.substring( 0, j+2 )
- else
- return str.substring( 0, j+1 )
+ var j = len - 1 - i
+ var c = string_number.chars[j]
+ if not is_expo then
+ if c == '0' then
+ continue
+ else if c == '.' then
+ numeric_value = string_number.substring( 0, j + 2)
+ break
+ else
+ numeric_value = string_number.substring( 0, j + 1)
+ break
+ end
+ else if c == 'e' then
+ expo_value = string_number.substring( j, len - 1 )
+ is_expo = false
end
end
- return str
+ return numeric_value + expo_value
+ end
+
+ # Return a string representation of `self` in fonction if it is not a number or infinity.
+ # Return `null` if `self` is not a not a number or an infinity
+ private fun check_inf_or_nan: nullable String
+ do
+ if is_nan then return "nan"
+
+ var isinf = self.is_inf
+ if isinf == 1 then
+ return "inf"
+ else if isinf == -1 then
+ return "-inf"
+ end
+ return null
end
# `String` representation of `self` with the given number of `decimals`
# ~~~
fun to_precision(decimals: Int): String
do
- if is_nan then return "nan"
+ var is_inf_or_nan = check_inf_or_nan
+ if is_inf_or_nan != null then return is_inf_or_nan
+ return return_from_specific_format("%.{decimals}f".to_cstring)
+ end
- var isinf = self.is_inf
- if isinf == 1 then
- return "inf"
- else if isinf == -1 then
- return "-inf"
- end
+ # Returns the hexadecimal (`String`) representation of `self` in exponential notation
+ #
+ # ~~~
+ # assert 12.345.to_hexa_exponential_notation == "0x1.8b0a3d70a3d71p+3"
+ # assert 12.345.to_hexa_exponential_notation.to_f == 12.345
+ # ~~~
+ fun to_hexa_exponential_notation: String
+ do
+ return return_from_specific_format("%a".to_cstring)
+ 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)
+ # Return the representation of `self`, with the specific given c `format`.
+ private fun return_from_specific_format(format: CString): String
+ do
+ var size = to_precision_size_with_format(format)
+ var cstr = new CString(size + 1)
+ to_precision_fill_with_format(format, size + 1, cstr)
+ return cstr.to_s_unsafe(byte_length = size, copy = false)
end
- # 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);
+ # The lenght of `self` in the specific given c `format`
+ private fun to_precision_size_with_format(format: CString): Int`{
+ return snprintf(NULL, 0, format, self);
`}
- # Fill `cstr` with `self` and `nb` decimals
- private fun to_precision_fill(nb, size: Int, cstr: CString) `{
- snprintf(cstr, size, "%.*f", (int)nb, self);
+ # Fill `cstr` with `self` in the specific given c `format`
+ private fun to_precision_fill_with_format(format: CString, size: Int, cstr: CString) `{
+ snprintf(cstr, size, format, self);
`}
end
# Returns a sequence with the UTF-8 bytes of `self`
#
# ~~~
- # assert 'a'.bytes == [0x61u8]
- # assert 'ま'.bytes == [0xE3u8, 0x81u8, 0xBEu8]
+ # assert 'a'.bytes == [0x61]
+ # assert 'ま'.bytes == [0xE3, 0x81, 0xBE]
# ~~~
- fun bytes: SequenceRead[Byte] do return to_s.bytes
+ fun bytes: SequenceRead[Int] do return to_s.bytes
# Is `self` an UTF-16 surrogate pair ?
fun is_surrogate: Bool do