1 /*
2  * Collie - An asynchronous event-driven network framework using Dlang development
3  *
4  * Copyright (C) 2015-2017  Shanghai Putao Technology Co., Ltd 
5  *
6  * Developer: putao's Dlang team
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 module collie.codec.mqtt.bytebuf;
12 
13 import std.stdio;
14 import std.conv;
15 import core.memory;
16 import std.algorithm : swap;
17 import kiss.container.Vector;
18 
19 import core.stdc..string;
20 
21 //default big end
22 
23 final class ByteBuf 
24 {
25 	alias BufferVector = Vector!(ubyte); 
26 	
27     this()
28 	{
29 		_readIndex = _writeIndex = 0;
30 	}
31 
32     this(ubyte[] data )
33 	{
34 		_readIndex = _writeIndex = 0;
35 		writeBytes(data);
36 	}
37 
38 	~this()
39 	{
40 		clear();
41 	}
42 
43 	void reset()
44 	{
45 		if(_buffer.length > 0)
46 		{
47 			_readIndex = 0;
48 			_writeIndex = cast(int)_buffer.length;
49 		}
50 	}
51 
52 	ByteBuf readSlice(int len)
53 	{
54 		if(len > _buffer.length || len + _readIndex > _buffer.length)
55 		{
56 			throw new Exception("IndexOutOfBoundsException");
57 		}
58 		ubyte[] da;
59 		for(int i= 0 ; i < len;i++)
60 		{
61 			da ~= _buffer[_readIndex+i];
62 		}
63 		_readIndex += len;
64 		return new ByteBuf(da);
65 	}
66 
67 	int readerIndex()
68 	{
69 		return _readIndex;
70 	}
71 
72 	int writerIndex()
73 	{
74 		return _writeIndex;
75 	}
76 
77 	// to utf-8 string
78 	string toString(int index,int len)
79 	{
80 		if(len > _buffer.length || index + len > _buffer.length)
81 		{
82 			writeln("IndexOutOfBoundsException -->readindex:  ",index,"read len : ",len,"buf len :",_buffer.length);
83 			throw new Exception("IndexOutOfBoundsException");
84 		}
85 		ubyte[] da;
86 		for(int i= 0 ; i < len;i++)
87 		{
88 			da ~= _buffer[index+i];
89 		}
90 		//writeln("bytebuf tostring----> ",da," ",cast(string)(cast(byte[])da));
91 		return cast(string)(da);
92 	}
93 
94 	void skipBytes(int skipsize)
95 	{
96 		if(_readIndex + skipsize > _writeIndex)
97 		{
98 			writeln("_readInxde : ",_readIndex,"skipsize :",skipsize,"_writeIndex : ",_writeIndex);
99 			throw new Exception("IndexOutOfBoundsException");
100 		}
101 		_readIndex += skipsize;
102 	}
103 
104 	short readUnsignedByte()
105 	{
106 		if(_readIndex > _writeIndex || _readIndex < 0)
107 		{
108 			throw new Exception("buf cannot read");
109 		}
110 
111 		short va = cast(short)(_buffer[_readIndex] & 0xff);
112 		_readIndex++;
113 		return va;
114 	}
115 
116 	ubyte readByte()
117 	{
118 		if(_readIndex > _writeIndex || _readIndex < 0)
119 		{
120 			throw new Exception("buf cannot read");
121 		}
122 		
123 		ubyte va = cast(ubyte)_buffer[_readIndex];
124 		_readIndex++;
125 		return va;
126 	}
127 
128 	void writeByte(int value)
129 	{
130 		ubyte data = cast(ubyte)(value & 0xff);
131 		writeByte(data);
132 	
133 		if(_readIndex < 0)
134 			_readIndex = 0;
135 	}
136 
137 	void writeByte(ubyte value)
138 	{
139 		_buffer.insertBack(value);
140 		_writeIndex++;
141 		if(_readIndex < 0)
142 			_readIndex = 0;
143 	}
144 
145 	void writeShort(int value)
146 	{
147 		ubyte d1 = cast(ubyte)((value >> 8) & 0xff);
148 		writeByte(d1);
149 		ubyte d2 = cast(ubyte)(value & 0xff);
150 		writeByte(d2);
151 
152 		if(_readIndex < 0)
153 			_readIndex = 0;
154 	}
155 
156 	void writeBytes(ubyte[] value)
157 	{
158 		_buffer.insertBack(value);
159 		_writeIndex += value.length;
160 		if(_readIndex < 0)
161 			_readIndex = 0;
162 	}
163 
164 	void writeBytes(ubyte[] value, int srcIndex, int length )
165 	{
166 		ubyte[] data = value[srcIndex .. srcIndex+length];
167 		//writeln("writeBytes ---> : ",data);
168 		_buffer.insertBack(data);
169 		_writeIndex += length;
170 		if(_readIndex < 0)
171 			_readIndex = 0;
172 	}
173 
174 	ubyte[] data()
175 	{
176 		return _buffer.data().dup;
177 	}
178 
179 	pragma(inline, true) final const @property size_t length()
180 	{
181 		return _buffer.length;
182 	}
183 
184 //	pragma(inline) void opAssign( ByteBuf s)
185 //	{
186 //		this._readIndex = s._readIndex;
187 //		this._writeIndex = s._writeIndex;
188 //		this._buffer = s._buffer.dup;
189 //	}
190 
191 		
192 	@property void clear()
193 	{
194 		_buffer.clear();
195 		_readIndex = _writeIndex = 0;
196 		//logDebug("\n\tclear()!!! \n");
197 	}
198 private:
199 	BufferVector _buffer ;
200 	int _readIndex;
201 	int _writeIndex;
202 }
203