# 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")
var int = 0
for b in bits.length.times do
- if bits[b] then int += 2**b
+ if bits[b] then int |= 1 << (7 - b)
end
write_byte int
# Compared to `write_string`, this method supports null bytes in `text`.
fun write_block(text: Text)
do
- write_int64 text.length
+ write_int64 text.byte_length
write text
end
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 > 0
# 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]
+ if int < 0 then return new Array[Bool]
+ var arr = new Array[Bool]
+ for i in [7 .. 0].step(-1) do
+ arr.push(((int >> i) & 1) != 0)
+ 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 == 0x00 then return buf.to_s
- buf.chars.add byte.ascii
+ if byte <= 0 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
var b3 = read_byte
# Check for error, `last_error` is set by `read_byte`
- if b0 == null or b1 == null or b2 == null or b3 == null then return 0.0
+ if b0 < 0 or b1 < 0 or b2 < 0 or b3 < 0 then return 0.0
return native_read_float(b0, b1, b2, b3, big_endian)
end
`}
# 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
var b7 = read_byte
# Check for error, `last_error` is set by `read_byte`
- if b0 == null or b1 == null or b2 == null or b3 == null or
- b4 == null or b5 == null or b6 == null or b7 == null then return 0.0
+ if b0 < 0 or b1 < 0 or b2 < 0 or b3 < 0 or
+ b4 < 0 or b5 < 0 or b6 < 0 or b7 < 0 then return 0.0
return native_read_double(b0, b1, b2, b3, b4, b5, b6, b7, big_endian)
end
#
# 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
var b7 = read_byte
# Check for error, `last_error` is set by `read_byte`
- if b0 == null or b1 == null or b2 == null or b3 == null or
- b4 == null or b5 == null or b6 == null or b7 == null then return 0
+ if b0 < 0 or b1 < 0 or b2 < 0 or b3 < 0 or
+ b4 < 0 or b5 < 0 or b6 < 0 or b7 < 0 then return 0
return native_read_int64(b0, b1, b2, b3, b4, b5, b6, b7, big_endian)
end