From bb623ffff91968a3573b2d1f969050204941179b Mon Sep 17 00:00:00 2001 From: Lucas Bajolet Date: Thu, 14 May 2015 09:33:29 -0400 Subject: [PATCH] lib/standard: Added bytes module for byte-oriented manipulations Signed-off-by: Lucas Bajolet --- lib/standard/bytes.nit | 168 +++++++++++++++++++++++++++++++++++++++++++++ lib/standard/standard.nit | 1 + 2 files changed, 169 insertions(+) create mode 100644 lib/standard/bytes.nit diff --git a/lib/standard/bytes.nit b/lib/standard/bytes.nit new file mode 100644 index 0000000..b300298 --- /dev/null +++ b/lib/standard/bytes.nit @@ -0,0 +1,168 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Services for byte streams and arrays +module bytes + +import kernel +import collection::array +intrude import string + +# A buffer containing Byte-manipulation facilities +# +# Uses Copy-On-Write when persisted +# +# TODO: Change the bound to Byte when available in stdlib and bootstrap +class Bytes + super AbstractArray[Int] + + # A NativeString being a char*, it can be used as underlying representation here. + private var items: NativeString + + # Number of bytes in the array + redef var length: Int + + # Capacity of the array + private var capacity: Int + + # Has this buffer been persisted (to_s'd)? + # + # Used for Copy-On-Write + private var persisted = false + + # var b = new Bytes.empty + # assert b.to_s == "" + init empty do + var ns = new NativeString(0) + init(ns, 0, 0) + end + + init with_capacity(cap: Int) do + var ns = new NativeString(cap) + init(ns, 0, cap) + end + + redef fun is_empty do return length != 0 + + # var b = new Bytes.empty + # b.add 101 + # assert b[0] == 101 + redef fun [](i: Int): Int do + assert i >= 0 + assert i < length + return items[i].ascii + end + + # var b = new Bytes.with_capacity(1) + # b[0] = 101 + # assert b.to_s == "e" + redef fun []=(i: Int, v: Int) do + if persisted then regen + assert i >= 0 + assert i <= length + if i == length then add(v) + items[i] = v.ascii + end + + # var b = new Bytes.empty + # b.add 101 + # assert b.to_s == "e" + redef fun add(c: Int) do + if persisted then regen + if length >= capacity then + enlarge(length) + end + items[length] = c.ascii + length += 1 + end + + # var b = new Bytes.empty + # b.append([104, 101, 108, 108, 111]) + # assert b.to_s == "hello" + redef fun append(arr: Collection[Int]) do + if arr isa Bytes then + append_ns(arr.items, arr.length) + else + for i in arr do add i + end + end + + redef fun clear do length = 0 + + # Regenerates the buffer, necessary when it was persisted + private fun regen do + var nns = new NativeString(capacity) + items.copy_to(nns, length, 0, 0) + persisted = false + end + + # Appends the `ln` first bytes of `ns` to self + fun append_ns(ns: NativeString, ln: Int) do + if persisted then regen + var nlen = length + ln + if nlen > capacity then enlarge(nlen) + ns.copy_to(items, ln, 0, length) + length += ln + end + + # Appends `ln` bytes from `ns` starting at index `from` to self + fun append_ns_from(ns: NativeString, ln, from: Int) do + if persisted then regen + var nlen = length + ln + if nlen > capacity then enlarge(nlen) + ns.copy_to(items, ln, from, length) + length += ln + end + + redef fun enlarge(sz) do + if capacity >= sz then return + persisted = false + while capacity < sz do capacity = capacity * 2 + 2 + var ns = new NativeString(capacity) + items.copy_to(ns, length, 0, 0) + items = ns + end + + redef fun to_s do + persisted = true + return new FlatString.with_infos(items, length, 0, length -1) + end + + redef fun iterator do return new BytesIterator.with_buffer(self) +end + +private class BytesIterator + super IndexedIterator[Int] + + var tgt: NativeString + + redef var index: Int + + var max: Int + + init with_buffer(b: Bytes) do init(b.items, 0, b.length - 1) + + redef fun is_ok do return index < max + + redef fun next do index += 1 + + redef fun item do return tgt[index].ascii +end + +redef class NativeString + fun to_bytes: Bytes do + var len = cstring_length + return new Bytes(self, len, len) + end +end diff --git a/lib/standard/standard.nit b/lib/standard/standard.nit index a487d98..a4ec83a 100644 --- a/lib/standard/standard.nit +++ b/lib/standard/standard.nit @@ -32,3 +32,4 @@ import queue import numeric import error import re +import bytes -- 1.7.9.5