util/dbuffer.lua

Thu, 07 Apr 2022 18:11:33 +0100

author
Matthew Wild <mwild1@gmail.com>
date
Thu, 07 Apr 2022 18:11:33 +0100
changeset 0
89e39cd5a7cd
permissions
-rw-r--r--

Initial commit

0
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 local queue = require "util.queue";
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 local s_byte, s_sub = string.byte, string.sub;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4 local dbuffer_methods = {};
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5 local dynamic_buffer_mt = { __name = "dbuffer", __index = dbuffer_methods };
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 function dbuffer_methods:write(data)
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8 if self.max_size and #data + self._length > self.max_size then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 return nil;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 local ok = self.items:push(data);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 if not ok then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 self:collapse();
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 ok = self.items:push(data);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 if not ok then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 return nil;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19 self._length = self._length + #data;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20 return true;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 function dbuffer_methods:read_chunk(requested_bytes)
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24 local chunk, consumed = self.items:peek(), self.front_consumed;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25 if not chunk then return; end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26 local chunk_length = #chunk;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27 local remaining_chunk_length = chunk_length - consumed;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28 if not requested_bytes then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 requested_bytes = remaining_chunk_length;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31 if remaining_chunk_length <= requested_bytes then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 self.front_consumed = 0;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33 self._length = self._length - remaining_chunk_length;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34 self.items:pop();
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35 assert(#chunk:sub(consumed + 1, -1) == remaining_chunk_length);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 return chunk:sub(consumed + 1, -1), remaining_chunk_length;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38 local end_pos = consumed + requested_bytes;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39 self.front_consumed = end_pos;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40 self._length = self._length - requested_bytes;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41 assert(#chunk:sub(consumed + 1, end_pos) == requested_bytes);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 return chunk:sub(consumed + 1, end_pos), requested_bytes;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 function dbuffer_methods:read(requested_bytes)
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 local chunks;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 if requested_bytes and requested_bytes > self._length then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 return nil;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 local chunk, read_bytes = self:read_chunk(requested_bytes);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
53 if not requested_bytes then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 return chunk;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 elseif chunk then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56 requested_bytes = requested_bytes - read_bytes;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
57 if requested_bytes == 0 then -- Already read everything we need
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
58 return chunk;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
60 chunks = {};
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61 else
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
62 return nil;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
63 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
64
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
65 -- Need to keep reading more chunks
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66 while chunk do
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
67 table.insert(chunks, chunk);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
68 if requested_bytes > 0 then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
69 chunk, read_bytes = self:read_chunk(requested_bytes);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
70 requested_bytes = requested_bytes - read_bytes;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
71 else
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 break;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76 return table.concat(chunks);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
79 -- Read to, and including, the specified character sequence (return nil if not found)
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 function dbuffer_methods:read_until(char)
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81 local buffer_pos = 0;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
82 for i, chunk in self.items:items() do
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83 local start = 1 + ((i == 1) and self.front_consumed or 0);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
84 local char_pos = chunk:find(char, start, true);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
85 if char_pos then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
86 return self:read(1 + buffer_pos + char_pos - start);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
87 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
88 buffer_pos = buffer_pos + #chunk - (start - 1);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
89 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
90 return nil;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
91 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
92
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
93 function dbuffer_methods:discard(requested_bytes)
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
94 if requested_bytes > self._length then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
95 return nil;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
96 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
97
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
98 local chunk, read_bytes = self:read_chunk(requested_bytes);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
99 if chunk then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
100 requested_bytes = requested_bytes - read_bytes;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
101 if requested_bytes == 0 then -- Already read everything we need
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
102 return true;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
103 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
104 else
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
105 return nil;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
106 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
107
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
108 while chunk do
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
109 if requested_bytes > 0 then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
110 chunk, read_bytes = self:read_chunk(requested_bytes);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
111 requested_bytes = requested_bytes - read_bytes;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
112 else
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
113 break;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
114 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
115 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
116 return true;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
117 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
118
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
119 -- Normalize i, j into absolute offsets within the
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
120 -- front chunk (accounting for front_consumed), and
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
121 -- ensure there is enough data in the first chunk
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
122 -- to cover any subsequent :sub() or :byte() operation
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
123 function dbuffer_methods:_prep_sub(i, j)
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
124 if j == nil then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
125 j = -1;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
126 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
127 if j < 0 then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
128 j = self._length + (j+1);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
129 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
130 if i < 0 then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
131 i = self._length + (i+1);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
132 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
133 if i < 1 then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
134 i = 1;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
135 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
136 if j > self._length then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
137 j = self._length;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
138 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
139 if i > j then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
140 return nil;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
141 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
142
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
143 self:collapse(j);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
144
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
145 if self.front_consumed > 0 then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
146 i = i + self.front_consumed;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
147 j = j + self.front_consumed;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
148 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
149
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
150 return i, j;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
151 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
152
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
153 function dbuffer_methods:sub(i, j)
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
154 i, j = self:_prep_sub(i, j);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
155 if not i then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
156 return "";
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
157 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
158 return s_sub(self.items:peek(), i, j);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
159 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
160
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
161 function dbuffer_methods:byte(i, j)
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
162 i = i or 1;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
163 j = j or i;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
164 i, j = self:_prep_sub(i, j);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
165 if not i then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
166 return;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
167 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
168 return s_byte(self.items:peek(), i, j);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
169 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
170
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
171 function dbuffer_methods:length()
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
172 return self._length;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
173 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
174 dbuffer_methods.len = dbuffer_methods.length; -- strings have :len()
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
175 dynamic_buffer_mt.__len = dbuffer_methods.length; -- support # operator
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
176
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
177 function dbuffer_methods:collapse(bytes)
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
178 bytes = bytes or self._length;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
179
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
180 local front_chunk = self.items:peek();
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
181
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
182 if not front_chunk or #front_chunk - self.front_consumed >= bytes then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
183 return;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
184 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
185
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
186 local front_chunks = { front_chunk:sub(self.front_consumed+1) };
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
187 local front_bytes = #front_chunks[1];
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
188
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
189 while front_bytes < bytes do
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
190 self.items:pop();
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
191 local chunk = self.items:peek();
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
192 front_bytes = front_bytes + #chunk;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
193 table.insert(front_chunks, chunk);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
194 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
195 self.items:replace(table.concat(front_chunks));
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
196 self.front_consumed = 0;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
197 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
198
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
199 local function new(max_size, max_chunks)
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
200 if max_size and max_size <= 0 then
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
201 return nil;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
202 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
203 return setmetatable({
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
204 front_consumed = 0;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
205 _length = 0;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
206 max_size = max_size;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
207 items = queue.new(max_chunks or 32);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
208 }, dynamic_buffer_mt);
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
209 end
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
210
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
211 return {
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
212 new = new;
89e39cd5a7cd Initial commit
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
213 };

mercurial