lib: Update libs to use correctly ascii and code_point
[nit.git] / lib / binary / binary.nit
index 0e019f5..c15cb52 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Add reading and writing binary services
+# Read and write binary data with any `Reader` and `Writer`
 #
 # ~~~
 # var w = new FileWriter.open("/tmp/data.bin")
 # w.write "hello"
 # w.write_int64 123456789
-# w.write_byte 3
+# w.write_byte 3u8
 # w.write_float 1.25
 # w.write_double 1.234567
 # w.write_bits(true, false, true)
@@ -28,7 +28,7 @@
 # var r = new FileReader.open("/tmp/data.bin")
 # assert r.read(5) == "hello"
 # assert r.read_int64 == 123456789
-# assert r.read_byte == 3
+# assert r.read_byte == 3u8
 # assert r.read_float == 1.25
 # assert r.read_double == 1.234567
 #
@@ -45,10 +45,13 @@ in "C" `{
        #include <endian.h>
 
        // Android compatibility
+       #ifndef be32toh
+               #define be32toh(val) betoh32(val)
+               #define le32toh(val) letoh32(val)
+       #endif
+
        #ifndef be64toh
                #define be64toh(val) betoh64(val)
-       #endif
-       #ifndef le64toh
                #define le64toh(val) letoh64(val)
        #endif
 `}
@@ -67,7 +70,7 @@ redef abstract class Writer
        super BinaryStream
 
        # Write a boolean `value` on a byte, using 0 for `false` and 1 for `true`
-       fun write_bool(value: Bool) do write_byte if value then 1 else 0
+       fun write_bool(value: Bool) do write_byte if value then 1u8 else 0u8
 
        # Write up to 8 `Bool` in a byte
        #
@@ -78,9 +81,9 @@ redef abstract class Writer
        do
                assert bits.length <= 8
 
-               var int = 0
+               var int = 0u8
                for b in bits.length.times do
-                       if bits[b] then int += 2**b
+                       if bits[b] then int |= 1u8 << (7 - b)
                end
 
                write_byte int
@@ -94,7 +97,7 @@ redef abstract class Writer
        fun write_string(text: Text)
        do
                write text
-               write_byte 0x00
+               write_byte 0x00u8
        end
 
        # Write the length as a 64 bits integer, then the content of `text`
@@ -104,7 +107,7 @@ redef abstract class Writer
        # Compared to `write_string`, this method supports null bytes in `text`.
        fun write_block(text: Text)
        do
-               write_int64 text.length
+               write_int64 text.bytelen
                write text
        end
 
@@ -148,45 +151,61 @@ redef abstract class Reader
        super BinaryStream
 
        # Read a single byte and return `true` if its value is different than 0
-       fun read_bool: Bool do return read_byte != 0
+       #
+       # Returns `false` when an error is pending (`last_error != null`).
+       fun read_bool: Bool do return read_byte != 0u8
 
        # Get an `Array` of 8 `Bool` by reading a single byte
        #
        # To be used with `BinaryWriter::write_bits`.
+       #
+       # Returns an array of `false` when an error is pending (`last_error != null`).
        fun read_bits: Array[Bool]
        do
                var int = read_byte
                if int == null then return new Array[Bool]
-               return [for b in 8.times do int.bin_and(2**b) > 0]
+               var arr = new Array[Bool]
+               for i in [7 .. 0].step(-1) do
+                       arr.push(((int >> i) & 1u8) != 0u8)
+               end
+               return arr
        end
 
        # Read a null terminated string
        #
        # To be used with `Writer::write_string`.
+       #
+       # Returns a truncated string when an error is pending (`last_error != null`).
        fun read_string: String
        do
-               var buf = new FlatBuffer
+               var buf = new Bytes.empty
                loop
                        var byte = read_byte
-                       if byte == null or byte == 0x00 then return buf.to_s
-                       buf.chars.add byte.ascii
+                       if byte == null or byte == 0u8 then
+                               return buf.to_s
+                       end
+                       buf.add byte
                end
        end
 
        # Read the length as a 64 bits integer, then the content of the block
        #
        # To be used with `Writer::write_block`.
+       #
+       # Returns a truncated string when an error is pending (`last_error != null`).
        fun read_block: String
        do
                var length = read_int64
                if length == 0 then return ""
-               return read(length)
+               return read_bytes(length).to_s
        end
 
        # Read a floating point on 32 bits and return it as a `Float`
        #
        # Using this format may result in a loss of precision as it uses less bits
        # than Nit `Float`.
+       #
+       # Returns `0.0` when an error is pending (`last_error != null`).
        fun read_float: Float
        do
                if last_error != null then return 0.0
@@ -203,7 +222,7 @@ redef abstract class Reader
        end
 
        # Utility for `read_float`
-       private fun native_read_float(b0, b1, b2, b3: Int, big_endian: Bool): Float `{
+       private fun native_read_float(b0, b1, b2, b3: Byte, big_endian: Bool): Float `{
                union {
                        unsigned char b[4];
                        float val;
@@ -223,6 +242,8 @@ redef abstract class Reader
        `}
 
        # Read a floating point on 64 bits and return it as a `Float`
+       #
+       # Returns `0.0` when an error is pending (`last_error != null`).
        fun read_double: Float
        do
                if last_error != null then return 0.0
@@ -244,7 +265,7 @@ redef abstract class Reader
        end
 
        # Utility for `read_double`
-       private fun native_read_double(b0, b1, b2, b3, b4, b5, b6, b7: Int, big_endian: Bool): Float `{
+       private fun native_read_double(b0, b1, b2, b3, b4, b5, b6, b7: Byte, big_endian: Bool): Float `{
                union {
                        unsigned char b[8];
                        double val;
@@ -271,6 +292,8 @@ redef abstract class Reader
        #
        # Using this format may result in a loss of precision as the length of a
        # Nit `Int` may be less than 64 bits on some platforms.
+       #
+       # Returns `0` when an error is pending (`last_error != null`).
        fun read_int64: Int
        do
                if last_error != null then return 0
@@ -292,7 +315,7 @@ redef abstract class Reader
        end
 
        # Utility for `read_int64`
-       private fun native_read_int64(b0, b1, b2, b3, b4, b5, b6, b7: Int, big_endian: Bool): Int `{
+       private fun native_read_int64(b0, b1, b2, b3, b4, b5, b6, b7: Byte, big_endian: Bool): Int `{
                union {
                        unsigned char b[8];
                        int64_t val;
@@ -318,7 +341,7 @@ end
 
 redef class Int
        # Utility for `BinaryWriter`
-       private fun int64_byte_at(index: Int, big_endian: Bool): Int `{
+       private fun int64_byte_at(index: Int, big_endian: Bool): Byte `{
                union {
                        unsigned char bytes[8];
                        int64_t val;
@@ -337,7 +360,7 @@ end
 
 redef class Float
        # Utility for `BinaryWriter`
-       private fun float_byte_at(index: Int, big_endian: Bool): Int `{
+       private fun float_byte_at(index: Int, big_endian: Bool): Byte `{
                union {
                        unsigned char bytes[4];
                        float val;
@@ -354,7 +377,7 @@ redef class Float
        `}
 
        # Utility for `BinaryWriter`
-       private fun double_byte_at(index: Int, big_endian: Bool): Int `{
+       private fun double_byte_at(index: Int, big_endian: Bool): Byte `{
                union {
                        unsigned char bytes[8];
                        double val;