1 # This file is part of NIT ( http://www.nitlanguage.org ).
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 # Services for byte streams and arrays
19 import collection
::array
22 # A buffer containing Byte-manipulation facilities
24 # Uses Copy-On-Write when persisted
26 # TODO: Change the bound to Byte when available in stdlib and bootstrap
28 super AbstractArray[Int]
30 # A NativeString being a char*, it can be used as underlying representation here.
31 private var items
: NativeString
33 # Number of bytes in the array
36 # Capacity of the array
37 private var capacity
: Int
39 # Has this buffer been persisted (to_s'd)?
41 # Used for Copy-On-Write
42 private var persisted
= false
44 # var b = new Bytes.empty
47 var ns
= new NativeString(0)
51 init with_capacity
(cap
: Int) do
52 var ns
= new NativeString(cap
)
56 redef fun is_empty
do return length
!= 0
58 # var b = new Bytes.empty
67 # var b = new Bytes.with_capacity(1)
69 # assert b.to_s == "e"
70 redef fun []=(i
, v
) do
71 if persisted
then regen
74 if i
== length
then add
(v
)
78 # var b = new Bytes.empty
80 # assert b.to_s == "e"
82 if persisted
then regen
83 if length
>= capacity
then
86 items
[length
] = c
.ascii
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
) do
95 append_ns
(arr
.items
, arr
.length
)
101 redef fun clear
do length
= 0
103 # Regenerates the buffer, necessary when it was persisted
105 var nns
= new NativeString(capacity
)
106 items
.copy_to
(nns
, length
, 0, 0)
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
)
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
)
128 redef fun enlarge
(sz
) do
129 if capacity
>= sz
then return
131 while capacity
< sz
do capacity
= capacity
* 2 + 2
132 var ns
= new NativeString(capacity
)
133 items
.copy_to
(ns
, length
, 0, 0)
139 return new FlatString.with_infos
(items
, length
, 0, length
-1)
142 redef fun iterator
do return new BytesIterator.with_buffer
(self)
145 private class BytesIterator
146 super IndexedIterator[Int]
148 var tgt
: NativeString
154 init with_buffer
(b
: Bytes) do init(b
.items
, 0, b
.length
- 1)
156 redef fun is_ok
do return index
< max
158 redef fun next
do index
+= 1
160 redef fun item
do return tgt
[index
].ascii
163 redef class NativeString
164 fun to_bytes
: Bytes do
165 var len
= cstring_length
166 return new Bytes(self, len
, len
)