Buffers.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. //
  2. // libtgvoip is free and unencumbered public domain software.
  3. // For more information, see http://unlicense.org or the UNLICENSE file
  4. // you should have received with this source code distribution.
  5. //
  6. #include "Buffers.h"
  7. #include <assert.h>
  8. #include <string.h>
  9. #include <exception>
  10. #include <stdexcept>
  11. #include <stdlib.h>
  12. #include "logging.h"
  13. using namespace tgvoip;
  14. #pragma mark - BufferInputStream
  15. BufferInputStream::BufferInputStream(const unsigned char* data, size_t length){
  16. this->buffer=data;
  17. this->length=length;
  18. offset=0;
  19. }
  20. BufferInputStream::BufferInputStream(const Buffer &buffer){
  21. this->buffer=*buffer;
  22. this->length=buffer.Length();
  23. offset=0;
  24. }
  25. BufferInputStream::~BufferInputStream(){
  26. }
  27. void BufferInputStream::Seek(size_t offset){
  28. if(offset>length){
  29. throw std::out_of_range("Not enough bytes in buffer");
  30. }
  31. this->offset=offset;
  32. }
  33. size_t BufferInputStream::GetLength(){
  34. return length;
  35. }
  36. size_t BufferInputStream::GetOffset(){
  37. return offset;
  38. }
  39. size_t BufferInputStream::Remaining(){
  40. return length-offset;
  41. }
  42. unsigned char BufferInputStream::ReadByte(){
  43. EnsureEnoughRemaining(1);
  44. return (unsigned char)buffer[offset++];
  45. }
  46. int32_t BufferInputStream::ReadInt32(){
  47. EnsureEnoughRemaining(4);
  48. int32_t res=((int32_t)buffer[offset] & 0xFF) |
  49. (((int32_t)buffer[offset+1] & 0xFF) << 8) |
  50. (((int32_t)buffer[offset+2] & 0xFF) << 16) |
  51. (((int32_t)buffer[offset+3] & 0xFF) << 24);
  52. offset+=4;
  53. return res;
  54. }
  55. int64_t BufferInputStream::ReadInt64(){
  56. EnsureEnoughRemaining(8);
  57. int64_t res=((int64_t)buffer[offset] & 0xFF) |
  58. (((int64_t)buffer[offset+1] & 0xFF) << 8) |
  59. (((int64_t)buffer[offset+2] & 0xFF) << 16) |
  60. (((int64_t)buffer[offset+3] & 0xFF) << 24) |
  61. (((int64_t)buffer[offset+4] & 0xFF) << 32) |
  62. (((int64_t)buffer[offset+5] & 0xFF) << 40) |
  63. (((int64_t)buffer[offset+6] & 0xFF) << 48) |
  64. (((int64_t)buffer[offset+7] & 0xFF) << 56);
  65. offset+=8;
  66. return res;
  67. }
  68. int16_t BufferInputStream::ReadInt16(){
  69. EnsureEnoughRemaining(2);
  70. int16_t res=(uint16_t)buffer[offset] | ((uint16_t)buffer[offset+1] << 8);
  71. offset+=2;
  72. return res;
  73. }
  74. int32_t BufferInputStream::ReadTlLength(){
  75. unsigned char l=ReadByte();
  76. if(l<254)
  77. return l;
  78. assert(length-offset>=3);
  79. EnsureEnoughRemaining(3);
  80. int32_t res=((int32_t)buffer[offset] & 0xFF) |
  81. (((int32_t)buffer[offset+1] & 0xFF) << 8) |
  82. (((int32_t)buffer[offset+2] & 0xFF) << 16);
  83. offset+=3;
  84. return res;
  85. }
  86. void BufferInputStream::ReadBytes(unsigned char *to, size_t count){
  87. EnsureEnoughRemaining(count);
  88. memcpy(to, buffer+offset, count);
  89. offset+=count;
  90. }
  91. void BufferInputStream::ReadBytes(Buffer &to){
  92. ReadBytes(*to, to.Length());
  93. }
  94. BufferInputStream BufferInputStream::GetPartBuffer(size_t length, bool advance){
  95. EnsureEnoughRemaining(length);
  96. BufferInputStream s=BufferInputStream(buffer+offset, length);
  97. if(advance)
  98. offset+=length;
  99. return s;
  100. }
  101. void BufferInputStream::EnsureEnoughRemaining(size_t need){
  102. if(length-offset<need){
  103. throw std::out_of_range("Not enough bytes in buffer");
  104. }
  105. }
  106. #pragma mark - BufferOutputStream
  107. BufferOutputStream::BufferOutputStream(size_t size){
  108. buffer=(unsigned char*) malloc(size);
  109. if(!buffer)
  110. throw std::bad_alloc();
  111. offset=0;
  112. this->size=size;
  113. bufferProvided=false;
  114. }
  115. BufferOutputStream::BufferOutputStream(unsigned char *buffer, size_t size){
  116. this->buffer=buffer;
  117. this->size=size;
  118. offset=0;
  119. bufferProvided=true;
  120. }
  121. BufferOutputStream::~BufferOutputStream(){
  122. if(!bufferProvided && buffer)
  123. free(buffer);
  124. }
  125. void BufferOutputStream::WriteByte(unsigned char byte){
  126. this->ExpandBufferIfNeeded(1);
  127. buffer[offset++]=byte;
  128. }
  129. void BufferOutputStream::WriteInt32(int32_t i){
  130. this->ExpandBufferIfNeeded(4);
  131. buffer[offset+3]=(unsigned char)((i >> 24) & 0xFF);
  132. buffer[offset+2]=(unsigned char)((i >> 16) & 0xFF);
  133. buffer[offset+1]=(unsigned char)((i >> 8) & 0xFF);
  134. buffer[offset]=(unsigned char)(i & 0xFF);
  135. offset+=4;
  136. }
  137. void BufferOutputStream::WriteInt64(int64_t i){
  138. this->ExpandBufferIfNeeded(8);
  139. buffer[offset+7]=(unsigned char)((i >> 56) & 0xFF);
  140. buffer[offset+6]=(unsigned char)((i >> 48) & 0xFF);
  141. buffer[offset+5]=(unsigned char)((i >> 40) & 0xFF);
  142. buffer[offset+4]=(unsigned char)((i >> 32) & 0xFF);
  143. buffer[offset+3]=(unsigned char)((i >> 24) & 0xFF);
  144. buffer[offset+2]=(unsigned char)((i >> 16) & 0xFF);
  145. buffer[offset+1]=(unsigned char)((i >> 8) & 0xFF);
  146. buffer[offset]=(unsigned char)(i & 0xFF);
  147. offset+=8;
  148. }
  149. void BufferOutputStream::WriteInt16(int16_t i){
  150. this->ExpandBufferIfNeeded(2);
  151. buffer[offset+1]=(unsigned char)((i >> 8) & 0xFF);
  152. buffer[offset]=(unsigned char)(i & 0xFF);
  153. offset+=2;
  154. }
  155. void BufferOutputStream::WriteBytes(const unsigned char *bytes, size_t count){
  156. this->ExpandBufferIfNeeded(count);
  157. memcpy(buffer+offset, bytes, count);
  158. offset+=count;
  159. }
  160. void BufferOutputStream::WriteBytes(const Buffer &buffer){
  161. WriteBytes(*buffer, buffer.Length());
  162. }
  163. void BufferOutputStream::WriteBytes(const Buffer &buffer, size_t offset, size_t count){
  164. if(offset+count>buffer.Length())
  165. throw std::out_of_range("offset out of buffer bounds");
  166. WriteBytes(*buffer+offset, count);
  167. }
  168. unsigned char *BufferOutputStream::GetBuffer(){
  169. return buffer;
  170. }
  171. size_t BufferOutputStream::GetLength(){
  172. return offset;
  173. }
  174. void BufferOutputStream::ExpandBufferIfNeeded(size_t need){
  175. if(offset+need>size){
  176. if(bufferProvided){
  177. throw std::out_of_range("buffer overflow");
  178. }
  179. if(need<1024){
  180. buffer=(unsigned char *) realloc(buffer, size+1024);
  181. size+=1024;
  182. }else{
  183. buffer=(unsigned char *) realloc(buffer, size+need);
  184. size+=need;
  185. }
  186. if(!buffer)
  187. throw std::bad_alloc();
  188. }
  189. }
  190. void BufferOutputStream::Reset(){
  191. offset=0;
  192. }
  193. void BufferOutputStream::Rewind(size_t numBytes){
  194. if(numBytes>offset)
  195. throw std::out_of_range("buffer underflow");
  196. offset-=numBytes;
  197. }
  198. #pragma mark - BufferPool
  199. BufferPool::BufferPool(unsigned int size, unsigned int count){
  200. assert(count<=64);
  201. buffers[0]=(unsigned char*) malloc(size*count);
  202. bufferCount=count;
  203. unsigned int i;
  204. for(i=1;i<count;i++){
  205. buffers[i]=buffers[0]+i*size;
  206. }
  207. usedBuffers=0;
  208. this->size=size;
  209. }
  210. BufferPool::~BufferPool(){
  211. free(buffers[0]);
  212. }
  213. unsigned char* BufferPool::Get(){
  214. MutexGuard m(mutex);
  215. int i;
  216. for(i=0;i<bufferCount;i++){
  217. if(!((usedBuffers >> i) & 1)){
  218. usedBuffers|=(1LL << i);
  219. return buffers[i];
  220. }
  221. }
  222. return NULL;
  223. }
  224. void BufferPool::Reuse(unsigned char* buffer){
  225. MutexGuard m(mutex);
  226. int i;
  227. for(i=0;i<bufferCount;i++){
  228. if(buffers[i]==buffer){
  229. usedBuffers&= ~(1LL << i);
  230. return;
  231. }
  232. }
  233. LOGE("pointer passed isn't a valid buffer from this pool");
  234. abort();
  235. }
  236. size_t BufferPool::GetSingleBufferSize(){
  237. return size;
  238. }
  239. size_t BufferPool::GetBufferCount(){
  240. return (size_t) bufferCount;
  241. }
  242. #pragma mark - Buffer