lib: add module date
[nit.git] / lib / standard / bytes.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Services for byte streams and arrays
16 module bytes
17
18 import kernel
19 import collection::array
20 intrude import string
21
22 # A buffer containing Byte-manipulation facilities
23 #
24 # Uses Copy-On-Write when persisted
25 #
26 # TODO: Change the bound to Byte when available in stdlib and bootstrap
27 class Bytes
28 super AbstractArray[Int]
29
30 # A NativeString being a char*, it can be used as underlying representation here.
31 private var items: NativeString
32
33 # Number of bytes in the array
34 redef var length: Int
35
36 # Capacity of the array
37 private var capacity: Int
38
39 # Has this buffer been persisted (to_s'd)?
40 #
41 # Used for Copy-On-Write
42 private var persisted = false
43
44 # var b = new Bytes.empty
45 # assert b.to_s == ""
46 init empty do
47 var ns = new NativeString(0)
48 init(ns, 0, 0)
49 end
50
51 init with_capacity(cap: Int) do
52 var ns = new NativeString(cap)
53 init(ns, 0, cap)
54 end
55
56 redef fun is_empty do return length != 0
57
58 # var b = new Bytes.empty
59 # b.add 101
60 # assert b[0] == 101
61 redef fun [](i: Int): Int do
62 assert i >= 0
63 assert i < length
64 return items[i].ascii
65 end
66
67 # var b = new Bytes.with_capacity(1)
68 # b[0] = 101
69 # assert b.to_s == "e"
70 redef fun []=(i: Int, v: Int) do
71 if persisted then regen
72 assert i >= 0
73 assert i <= length
74 if i == length then add(v)
75 items[i] = v.ascii
76 end
77
78 # var b = new Bytes.empty
79 # b.add 101
80 # assert b.to_s == "e"
81 redef fun add(c: Int) do
82 if persisted then regen
83 if length >= capacity then
84 enlarge(length)
85 end
86 items[length] = c.ascii
87 length += 1
88 end
89
90 # var b = new Bytes.empty
91 # b.append([104, 101, 108, 108, 111])
92 # assert b.to_s == "hello"
93 redef fun append(arr: Collection[Int]) do
94 if arr isa Bytes then
95 append_ns(arr.items, arr.length)
96 else
97 for i in arr do add i
98 end
99 end
100
101 redef fun clear do length = 0
102
103 # Regenerates the buffer, necessary when it was persisted
104 private fun regen do
105 var nns = new NativeString(capacity)
106 items.copy_to(nns, length, 0, 0)
107 persisted = false
108 end
109
110 # Appends the `ln` first bytes of `ns` to self
111 fun append_ns(ns: NativeString, ln: Int) do
112 if persisted then regen
113 var nlen = length + ln
114 if nlen > capacity then enlarge(nlen)
115 ns.copy_to(items, ln, 0, length)
116 length += ln
117 end
118
119 # Appends `ln` bytes from `ns` starting at index `from` to self
120 fun append_ns_from(ns: NativeString, ln, from: Int) do
121 if persisted then regen
122 var nlen = length + ln
123 if nlen > capacity then enlarge(nlen)
124 ns.copy_to(items, ln, from, length)
125 length += ln
126 end
127
128 redef fun enlarge(sz) do
129 if capacity >= sz then return
130 persisted = false
131 while capacity < sz do capacity = capacity * 2 + 2
132 var ns = new NativeString(capacity)
133 items.copy_to(ns, length, 0, 0)
134 items = ns
135 end
136
137 redef fun to_s do
138 persisted = true
139 return new FlatString.with_infos(items, length, 0, length -1)
140 end
141
142 redef fun iterator do return new BytesIterator.with_buffer(self)
143 end
144
145 private class BytesIterator
146 super IndexedIterator[Int]
147
148 var tgt: NativeString
149
150 redef var index: Int
151
152 var max: Int
153
154 init with_buffer(b: Bytes) do init(b.items, 0, b.length - 1)
155
156 redef fun is_ok do return index < max
157
158 redef fun next do index += 1
159
160 redef fun item do return tgt[index].ascii
161 end
162
163 redef class NativeString
164 fun to_bytes: Bytes do
165 var len = cstring_length
166 return new Bytes(self, len, len)
167 end
168 end