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 }