1 module yu.tools.buffer.sectionbuffer;
2 
3 import yu.tools.buffer;
4 import yu.bytes;
5 import std.experimental.allocator.common;
6 import std.algorithm : swap;
7 import core.stdc.string;
8 
9 @trusted final class SectionBuffer(Alloc) : IBuffer
10 {
11     import yu.container.vector;
12     alias BufferVector = Vector!(ubyte[], Alloc, false);
13 
14     static if (stateSize!(Alloc) != 0)
15     {
16         alias ALLOC = Alloc;
17         this(uint sectionSize, Alloc alloc)
18         {
19             _alloc = clloc;
20             _sectionSize = sectionSize;
21             _buffer = BufferVector(4, alloc);
22             _buffer.destroyFun = &destroyBuffer;
23         }
24 
25         @property allocator()
26         {
27             return _store.allocator;
28         }
29 
30         private Alloc _alloc;
31     }
32     else
33     {
34         alias ALLOC = typeof(Alloc.instance);
35         this(uint sectionSize)
36         {
37             _sectionSize = sectionSize;
38             _buffer = BufferVector(4);
39             _buffer.destroyFun = &destroyBuffer;
40         }
41 
42         alias _alloc = Alloc.instance;
43     }
44 
45     static void destroyBuffer(ref ALLOC alloc, ref ubyte[] data) nothrow{
46         import std.exception;
47         if(data.length > 0)
48             collectException( _alloc.deallocate(data));
49     }
50 
51     void reserve(size_t size)
52     {
53         assert(size > 0);
54         size_t sec_size = size / _sectionSize;
55         if (sec_size < _buffer.length)
56         {
57             _buffer.removeBack(_buffer.length - sec_size);
58         }
59         else if (_buffer.length < sec_size)
60         {
61             size_t a_size = sec_size - _buffer.length;
62             for (size_t i = 0; i < a_size; ++i)
63             {
64                 _buffer.insertBack(cast(ubyte[]) _alloc.allocate(_sectionSize)); //new ubyte[_sectionSize]);//
65             }
66         }
67         size_t lsize = size - (_buffer.length * _sectionSize);
68         _buffer.insertBack(cast(ubyte[]) _alloc.allocate(lsize)); //new ubyte[lsize]);
69         _rSize = 0;
70         _wSize = 0;
71     }
72 
73     size_t maxSize()
74     {
75         if (_buffer.empty())
76             return size_t.max;
77         size_t leng = _buffer[_buffer.length - 1].length;
78         if (leng == _sectionSize)
79             return size_t.max;
80         else
81         {
82             return (_buffer.length - 1) * _sectionSize + leng;
83         }
84     }
85 
86     @property void clearWithMemory()
87     {
88         _buffer.clear();
89 
90         _rSize = 0;
91         _wSize = 0;
92     }
93 
94     pragma(inline) @property void clear()
95     {
96         if (maxSize() != size_t.max)
97         {
98             _buffer.removeBack();
99         }
100         _rSize = 0;
101         _wSize = 0;
102     }
103 
104     pragma(inline) size_t swap(ref BufferVector uarray)
105     {
106         auto size = _wSize;
107         .swap(uarray, _buffer);
108         _rSize = 0;
109         _wSize = 0;
110         return size;
111     }
112 
113     override @property bool eof() const
114     {
115         return isEof;
116     }
117 
118     override void rest(size_t size = 0)
119     {
120         _rSize = size;
121     }
122 
123     override @property size_t length() const
124     {
125         return _wSize;
126     }
127 
128     pragma(inline, true) @property size_t stectionSize()
129     {
130         return _sectionSize;
131     }
132 
133     pragma(inline) size_t read(ubyte[] data)
134     {
135         size_t rlen = 0;
136         return read(data.length, delegate(in ubyte[] dt) {
137             auto len = rlen;
138             rlen += dt.length;
139             data[len .. rlen] = dt[];
140 
141         });
142 
143     }
144 
145     override size_t read(size_t size, scope void delegate(in ubyte[]) cback) //回调模式,数据不copy
146     {
147         size_t len = _wSize - _rSize;
148         size_t maxlen = size < len ? size : len;
149         size_t rcount = readCount();
150         size_t rsite = readSite();
151         size_t rlen = 0, tlen;
152         while (rcount < _buffer.length)
153         {
154             ubyte[] by = cast(ubyte[])(_buffer[rcount]);
155             tlen = maxlen - rlen;
156             len = by.length - rsite;
157             if (len >= tlen)
158             {
159                 cback(by[rsite .. (tlen + rsite)]);
160                 rlen += tlen;
161                 _rSize += tlen;
162                 break;
163             }
164             else
165             {
166                 cback(by[rsite .. $]);
167                 _rSize += len;
168                 rlen += len;
169                 rsite = 0;
170                 ++rcount;
171             }
172         }
173         //_rSize += maxlen;
174         return maxlen;
175     }
176 
177     override size_t write(in ubyte[] data)
178     {
179         size_t len = maxSize() - _wSize;
180         size_t maxlen = data.length < len ? data.length : len;
181         size_t wcount = writeCount();
182         size_t wsite = writeSite();
183         size_t wlen = 0, tlen;
184         size_t maxSize = maxSize;
185         while (_wSize < maxSize)
186         {
187             if (wcount == _buffer.length)
188             {
189                 _buffer.insertBack(cast(ubyte[]) _alloc.allocate(_sectionSize)); //new ubyte[_sectionSize]);//
190             }
191             ubyte[] by = cast(ubyte[])_buffer[wcount];
192             tlen = maxlen - wlen;
193             len = by.length - wsite;
194             if (len >= tlen)
195             {
196                 by[wsite .. (wsite + tlen)] = data[wlen .. (wlen + tlen)];
197                 break;
198             }
199             else
200             {
201                 by[wsite .. (wsite + len)] = data[wlen .. (wlen + len)];
202                 wlen += len;
203                 wsite = 0;
204                 ++wcount;
205             }
206         }
207         _wSize += maxlen;
208         return maxlen;
209     }
210 
211     override size_t set(size_t pos, in ubyte[] data)
212 	{
213 		import core.stdc.string : memcpy;
214 		if(pos >= _wSize || data.length == 0) return 0;
215 		size_t len = _wSize - pos;
216 		len = len > data.length ? data.length : len;
217         auto sect =  pos / _sectionSize;
218         auto ssite = pos % _sectionSize;
219         ubyte[] by = cast(ubyte[])_buffer[sect];
220         if(ssite + len < by.length){
221             ubyte * ptr = by.ptr + ssite;
222             memcpy(ptr, data.ptr, len);
223         } else {
224             auto tlen = by.length - ssite;
225             ubyte * ptr = by.ptr + ssite;
226             memcpy(ptr, data.ptr, tlen);
227             by = cast(ubyte[])_buffer[sect + 1];
228             memcpy(by.ptr,(data.ptr + tlen),(len -tlen));
229         }
230         return len;
231 	}
232 
233     /*
234 	 * 会自动跳过找到的\r\n字段
235 	**/
236     override size_t readLine(scope void delegate(in ubyte[]) cback) //回调模式,数据不copy
237     {
238         if (isEof())
239             return 0;
240         size_t size = _rSize;
241         size_t wsite = writeSite();
242         size_t wcount = writeCount();
243         ubyte[] byptr, by;
244         while (!isEof())
245         {
246             size_t rcount = readCount();
247             size_t rsite = readSite();
248             by = _buffer[rcount];
249             if (rcount == wcount)
250             {
251                 byptr = by[rsite .. wsite];
252             }
253             else
254             {
255                 byptr = by[rsite .. $];
256             }
257             ptrdiff_t site = findCharByte(byptr, cast(ubyte) '\n');
258             if (site < 0)
259             {
260                 cback(byptr);
261                 rsite = 0;
262                 ++rcount;
263                 _rSize += byptr.length;
264             }
265             else
266             {
267                 auto tsize = (_rSize + site);
268                 if (site > 0)
269                 {
270                     size_t ts = site - 1;
271                     if (byptr[ts] == cast(ubyte) '\r')
272                     {
273                         site = ts;
274                     }
275                 }
276                 cback(byptr[0 .. site]);
277 
278                 _rSize = tsize + 1;
279                 size += 1;
280                 break;
281             }
282 
283         }
284         return _rSize - size;
285     }
286 
287     override size_t readAll(scope void delegate(in ubyte[]) cback) //回调模式,数据不copy
288     {
289         size_t maxlen = _wSize - _rSize;
290         size_t rcount = readCount();
291         size_t rsite = readSite();
292         size_t wcount = writeCount();
293         size_t wsize = writeSite();
294         ubyte[] rbyte;
295         while (rcount <= wcount && !isEof())
296         {
297             ubyte[] by = _buffer[rcount];
298             if (rcount == wcount)
299             {
300                 rbyte = by[rsite .. wsize];
301             }
302             else
303             {
304                 rbyte = by[rsite .. $];
305             }
306             cback(rbyte);
307             _rSize += rbyte.length;
308             rsite = 0;
309             ++rcount;
310         }
311         return _wSize - _rSize;
312     }
313 
314     /*
315 	 * 会自动跳过找到的data字段
316 	**/
317     override size_t readUtil(in ubyte[] data, scope void delegate(in ubyte[]) cback) //data.length 必须小于分段大小!
318     {
319         if (data.length == 0 || isEof() || data.length >= _sectionSize)
320             return 0;
321         auto ch = data[0];
322 
323         size_t size = _rSize;
324         size_t wsite = writeSite();
325         size_t wcount = writeCount();
326         ubyte[] byptr, by;
327         while (!isEof())
328         {
329             size_t rcount = readCount();
330             size_t rsite = readSite();
331             by = _buffer[rcount];
332             if (rcount == wcount)
333             {
334                 byptr = by[rsite .. wsite];
335             }
336             else
337             {
338                 byptr = by[rsite .. $];
339             }
340             ptrdiff_t site = findCharByte(byptr, ch);
341             if (site == -1)
342             {
343                 cback(byptr);
344                 rsite = 0;
345                 ++rcount;
346                 _rSize += byptr.length;
347             }
348             else
349             {
350                 auto tsize = (_rSize + site);
351                 size_t i = 1;
352                 size_t j = tsize + 1;
353                 for (; i < data.length && j < _wSize; ++i, ++j)
354                 {
355                     if (data[i] != this[j])
356                     {
357                         cback(byptr[0 .. site + 1]);
358                         _rSize = tsize + 1;
359                         goto next; //没找对,进行下次查找
360                     }
361                 } //循环正常执行完毕,表示
362                 cback(byptr[0 .. site]);
363                 _rSize = tsize + data.length;
364                 size += data.length;
365                 break;
366 
367             next:
368                 continue;
369             }
370         }
371         return (_rSize - size);
372     }
373 
374     pragma(inline) ref ubyte opIndex(size_t i)
375     {
376         assert(i < _wSize);
377         size_t count = i / _sectionSize;
378         size_t site = i % _sectionSize;
379         return _buffer[count][site];
380     }
381 
382     pragma(inline, true) @property readSize() const
383     {
384         return _rSize;
385     }
386 
387     override size_t readPos()
388     {
389         return _rSize;
390     }
391 
392     pragma(inline, true) @property readCount() const
393     {
394         return _rSize / _sectionSize;
395     }
396 
397     pragma(inline, true) @property readSite() const
398     {
399         return _rSize % _sectionSize;
400     }
401 
402     pragma(inline, true) @property writeCount() const
403     {
404         return _wSize / _sectionSize;
405     }
406 
407     pragma(inline, true) @property writeSite() const
408     {
409         return _wSize % _sectionSize;
410     }
411 
412 private:
413     pragma(inline, true) @property bool isEof() const
414     {
415         return (_rSize >= _wSize);
416     }
417 
418     size_t _rSize;
419     size_t _wSize;
420     size_t _sectionSize;
421     BufferVector _buffer;
422 }
423 
424 unittest
425 {
426     import std.stdio;
427     import std.experimental.allocator.mallocator;
428 
429     string data = "hello world. hello world. hello world. hello world. hello world. hello world. hello world. hello world. hello world. hello world. hello world. hello world. hello world.";
430     auto buf = new SectionBuffer!Mallocator(5);
431     buf.reserve(data.length);
432     writeln("buffer max size:", buf.maxSize());
433     writeln("buffer  size:", buf.length);
434     writeln("buffer write :", buf.write(cast(ubyte[]) data));
435     writeln("buffer  size:", buf.length);
436     ubyte[] dt;
437     dt.length = 13;
438     writeln("buffer read size =", buf.read(dt));
439     writeln("buffer read data =", cast(string) dt);
440 
441     writeln("\r\n");
442 
443     auto buf2 = new SectionBuffer!Mallocator(3);
444     writeln("buffer2 max size:", buf2.maxSize());
445     writeln("buffer2  size:", buf2.length);
446     writeln("buffer2 write :", buf2.write(cast(ubyte[]) data));
447     writeln("buffer2  size:", buf2.length);
448     ubyte[] dt2;
449     dt2.length = 13;
450     writeln("buffer2 read size =", buf2.read(dt2));
451     writeln("buffer2 read data =", cast(string) dt2);
452 
453     writeln("\r\nswitch \r\n");
454 
455     auto tary = SectionBuffer!Mallocator.BufferVector();
456     buf.swap(tary);
457     writeln("buffer  size:", buf.length);
458     writeln("buffer max size:", buf.maxSize());
459     writeln("Array!(ubyte[]) length : ", tary.length);
460     size_t len = tary.length < 5 ? tary.length : 5;
461     for (size_t i = 0; i < len; ++i)
462     {
463         write("i = ", i);
464         writeln("   ,ubyte[] = ", cast(string) tary[i]);
465     }
466 
467     buf.reserve(data.length);
468     writeln("buffer max size:", buf.maxSize());
469     writeln("buffer  size:", buf.length);
470     writeln("buffer write :", buf.write(cast(ubyte[]) data));
471     writeln("buffer  size:", buf.length);
472     writeln("\n 1.");
473 
474     /* dt.length = 1;
475     writeln("buffer read size =",buf.read(dt));
476     writeln("buffer read data =",cast(string)dt);*/
477 
478     data = "ewarwaerewtretr54654654kwjoerjopiwrjeo;jmq;lkwejoqwiurwnblknhkjhnjmq1111dewrewrjmqrtee";
479     buf = new SectionBuffer!Mallocator(5);
480     // buf.reserve(data.length);
481     writeln("buffer max size:", buf.maxSize());
482     writeln("buffer  size:", buf.length);
483     writeln("buffer write :", buf.write(cast(ubyte[]) data));
484     writeln("buffer  size:", buf.length);
485 
486     foreach (i; 0 .. 4)
487     {
488         ubyte[] tbyte;
489         writeln("\n\nbuffer readutil  size:", buf.readUtil(cast(ubyte[]) "jmq",
490                 delegate(in ubyte[] data) {
491                     //writeln("\t data :", cast(string)data);
492                     //writeln("\t read size: ", buf._rSize);
493                     tbyte ~= data;
494                 }));
495         if (tbyte.length > 0)
496         {
497             writeln("\n buffer readutil data:", cast(string) tbyte);
498             writeln("\t _Rread size: ", buf._rSize);
499             writeln("\t _Wread size: ", buf._wSize);
500         }
501         else
502         {
503             writeln("\n buffer readutil data eof");
504         }
505     }
506     //buf.clear();
507     //buf2.clear();
508     writeln("hahah");
509     destroy(buf);
510     destroy(buf2);
511 }