1 module yu.tools.buffer; 2 3 interface IWriteBuffer 4 { 5 size_t write(in ubyte[] data); 6 7 size_t set(size_t pos, in ubyte[] data); 8 9 @property size_t length() const; 10 } 11 12 interface IReadBuffer 13 { 14 @property bool eof() const; 15 16 size_t read(size_t size, scope void delegate(in ubyte[]) cback); 17 18 void rest(size_t size = 0); 19 20 size_t readPos(); 21 22 @property size_t length() const; 23 } 24 25 interface IBuffer : IWriteBuffer, IReadBuffer 26 { 27 size_t readLine(scope void delegate(in ubyte[]) cback); //回调模式,数据不copy 28 29 size_t readAll(scope void delegate(in ubyte[]) cback); 30 31 size_t readUtil(in ubyte[] data, scope void delegate(in ubyte[]) cback); 32 } 33 34 final class Buffer(Alloc) : IBuffer 35 { 36 import yu.bytes; 37 import yu.container.vector; 38 import std.experimental.allocator.common; 39 40 alias BufferStore = Vector!(ubyte,Alloc); 41 42 static if (stateSize!(Alloc) != 0) 43 { 44 this(Alloc alloc) 45 { 46 _store = BufferStore(1024,alloc); 47 } 48 49 @property allocator(){return _store.allocator;} 50 51 } else { 52 this() 53 { 54 _store = BufferStore(1024); 55 } 56 } 57 58 ~this(){ 59 destroy(_store); 60 } 61 62 pragma(inline,true) void reserve(size_t elements) 63 { 64 _store.reserve(elements); 65 } 66 67 pragma(inline,true) void clear() 68 { 69 _rsize = 0; 70 _store.clear(); 71 } 72 73 override @property bool eof() const 74 { 75 return (_rsize >= _store.length); 76 } 77 78 override size_t read(size_t size,scope void delegate(in ubyte[]) cback) 79 { 80 size_t len = _store.length - _rsize; 81 len = size < len ? size : len; 82 auto _data = _store.data(); 83 size = _rsize; 84 _rsize += len; 85 if (len > 0) 86 cback(_data[size .. _rsize]); 87 88 return len; 89 } 90 91 override size_t write(in ubyte[] dt) 92 { 93 size_t len = _store.length; 94 _store.insertBack(cast(ubyte[])dt); 95 return _store.length - len; 96 } 97 98 override size_t set(size_t pos, in ubyte[] data) 99 { 100 import core.stdc.string : memcpy; 101 if(pos >= _store.length || data.length == 0) return 0; 102 size_t len = _store.length - pos; 103 len = len > data.length ? data.length : len; 104 ubyte * ptr = cast(ubyte *)(_store.ptr + pos); 105 memcpy(ptr, data.ptr, len); 106 return len; 107 } 108 109 override void rest(size_t size = 0){ 110 _rsize = size; 111 } 112 113 override size_t readPos() { 114 return _rsize; 115 } 116 117 BufferStore allData(){ 118 return _store; 119 } 120 121 override @property size_t length() const { return _store.length; } 122 123 override size_t readLine(scope void delegate(in ubyte[]) cback) //回调模式,数据不copy 124 { 125 if(eof()) return 0; 126 auto _data = _store.data(); 127 auto tdata = _data[_rsize..$]; 128 size_t size = _rsize; 129 ptrdiff_t index = findCharByte(tdata,cast(ubyte)'\n'); 130 if(index < 0){ 131 _rsize += tdata.length; 132 cback(tdata); 133 } else { 134 _rsize += (index + 1); 135 size += 1; 136 if(index > 0){ 137 size_t ts = index -1; 138 if(tdata[ts] == cast(ubyte)'\r') { 139 index = ts; 140 } 141 } 142 cback(tdata[0..index]); 143 } 144 145 return _rsize - size; 146 } 147 148 override size_t readAll(scope void delegate(in ubyte[]) cback) 149 { 150 if(eof()) return 0; 151 auto _data = _store.data(); 152 auto tdata = _data[_rsize..$]; 153 _rsize = _store.length; 154 cback(tdata); 155 return tdata.length; 156 } 157 158 override size_t readUtil(in ubyte[] chs, scope void delegate(in ubyte[]) cback) 159 { 160 if(eof()) return 0; 161 auto _data = _store.data(); 162 auto tdata = _data[_rsize..$]; 163 size_t size = _rsize; 164 ptrdiff_t index = findCharBytes(tdata,chs); 165 if(index < 0){ 166 _rsize += tdata.length; 167 cback(tdata); 168 } else { 169 _rsize += (index + chs.length); 170 size += chs.length; 171 cback(tdata[0..index]); 172 } 173 return _rsize - size; 174 } 175 176 private: 177 BufferStore _store; 178 size_t _rsize = 0; 179 } 180 181 unittest 182 { 183 import std.stdio; 184 import std.experimental.allocator.mallocator; 185 string data = "hello world. hello world.\n hello world. hello world. hello \nworld. hello\r\n world. hello world. hello world. hello world. hello world. hello world. hello world. hello world."; 186 auto buf = new Buffer!Mallocator(); 187 writeln("buffer write :", buf.write(cast(ubyte[]) data)); 188 writeln("buffer size:", buf.length); 189 assert(buf.length == data.length); 190 ubyte[] dt; 191 dt.length = 13; 192 writeln("buffer read size =", buf.read(13,(in ubyte[] data2){dt[] = data2[];})); 193 writeln("buffer read data =", cast(string) dt); 194 195 buf.rest(); 196 string datat; 197 buf.readLine((in ubyte[] data2){datat ~= (cast(string)data2);}); 198 writeln("line is : ", datat); 199 assert(datat == "hello world. hello world."); 200 }