BufferOperation.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. #ifndef CBufferOperation_h
  2. #define CBufferOperation_h
  3. #include "SimpleString.h"
  4. #include "AutoArray.h"
  5. #include "Blob.h"
  6. namespace Chromium{
  7. #define IOBUF_T_I8 0
  8. #define IOBUF_T_I4 1
  9. #define IOBUF_T_I2 2
  10. #define IOBUF_T_I1 3
  11. #define IOBUF_T_STR 4
  12. #define IOBUF_T_BUF 5
  13. #define IOBUF_T_WSTR 6 /* wchar_t */
  14. #define IOBUF_T_7BIT 7
  15. /////////////////// Read Buf Start ///////////////////////
  16. static void buffer_read_buf(const char *iobuf, char *buf, int n, int* rpos)
  17. {
  18. // assert(content_size(iobuf) >= n);
  19. memcpy(buf, iobuf + *rpos, n);
  20. *rpos += n;
  21. }
  22. static void buffer_read_7bit_int(const char *iobuf, int *v, int* rpos)
  23. {
  24. int count = 0;
  25. int shift = 0;
  26. unsigned char b;
  27. do {
  28. if (shift == 5*7) // corrupted stream
  29. assert(0);
  30. b = iobuf[*rpos];
  31. *rpos += 1;
  32. count |= (b & 0x7F) << shift;
  33. shift += 7;
  34. } while (b & 0x80); // most left bit is flag
  35. *v = count;
  36. }
  37. static void buffer_read(const char *iobuf, int t, void *v, int *n, int* rpos){
  38. int len = 0;
  39. switch (t)
  40. {
  41. case IOBUF_T_I8:
  42. len += 8;
  43. buffer_read_buf(iobuf, (char*)v, len, rpos);
  44. break;
  45. case IOBUF_T_I4:
  46. len += 4;
  47. buffer_read_buf(iobuf, (char*)v, len, rpos);
  48. break;
  49. case IOBUF_T_I2:
  50. len += 2;
  51. buffer_read_buf(iobuf, (char*)v, len, rpos);
  52. break;
  53. case IOBUF_T_I1:
  54. len += 1;
  55. buffer_read_buf(iobuf, (char*)v, len, rpos);
  56. break;
  57. case IOBUF_T_STR:
  58. if (v) {
  59. int old_rpos = *rpos;
  60. buffer_read_7bit_int(iobuf, &len, rpos);
  61. if (!n || len < *n) {
  62. buffer_read_buf(iobuf, (char *)v, len, rpos);
  63. *((char*)v + len) = 0;
  64. if (n)
  65. *n = len;
  66. } else {
  67. *rpos = old_rpos;
  68. *n = len;
  69. }
  70. } else {
  71. if (n) {
  72. int old_rpos = *rpos;
  73. buffer_read_7bit_int(iobuf, &len, rpos);
  74. *rpos = old_rpos;
  75. *n = len;
  76. } else {
  77. assert(0);
  78. }
  79. }
  80. break;
  81. case IOBUF_T_WSTR:
  82. if (v) {
  83. int old_rpos = *rpos;
  84. buffer_read_7bit_int(iobuf, &len, rpos);
  85. if (!n || len < *n) {
  86. buffer_read_buf(iobuf, (char*)v, len, rpos); /* wchar_t */
  87. *((char*)v + len) = 0; // wchar termination char is 2 byte
  88. *((char*)v + len+1) = 0;
  89. if (n)
  90. *n = len;
  91. } else {
  92. *rpos = old_rpos;
  93. *n = len;
  94. }
  95. } else {
  96. if (n) {
  97. int old_rpos = *rpos;
  98. buffer_read_7bit_int(iobuf, &len, rpos);
  99. *rpos = old_rpos;
  100. *n = len;
  101. } else {
  102. assert(0);
  103. }
  104. }
  105. break;
  106. case IOBUF_T_BUF:
  107. if (*n > 0)
  108. buffer_read_buf(iobuf, (char*)v, *n, rpos);
  109. break;
  110. case IOBUF_T_7BIT:
  111. buffer_read_7bit_int(iobuf, (int*)v, rpos);
  112. break;
  113. default:
  114. assert(0);
  115. }
  116. }
  117. void buffer_format_readv(const char *iobuf, int* rpos, const char *fmt, va_list arg)
  118. {
  119. if (fmt) {
  120. const char *p = fmt;
  121. while (*p) {
  122. switch (*p) {
  123. case '8':
  124. buffer_read(iobuf, IOBUF_T_I8, va_arg(arg, void*), NULL, rpos);
  125. break;
  126. case '7': // 7bit int code
  127. buffer_read(iobuf, IOBUF_T_7BIT, va_arg(arg, void*), NULL, rpos);
  128. break;
  129. case '4':
  130. buffer_read(iobuf, IOBUF_T_I4, va_arg(arg, void*), 0, rpos);
  131. break;
  132. case '2':
  133. buffer_read(iobuf, IOBUF_T_I2, va_arg(arg, void*), 0, rpos);
  134. break;
  135. case '1':
  136. buffer_read(iobuf, IOBUF_T_I1, va_arg(arg, void*), 0, rpos);
  137. break;
  138. case 's':case 'S':
  139. {
  140. char **pstr = va_arg(arg, char**);
  141. int slen;
  142. buffer_read(iobuf, IOBUF_T_STR, NULL, &slen, rpos);
  143. //*pstr = (char*)malloc(slen+1);
  144. *pstr = new char[slen+1];
  145. buffer_read(iobuf, IOBUF_T_STR, *pstr, 0, rpos);
  146. }
  147. break;
  148. case 'w': case 'W':
  149. {
  150. wchar_t **pstr = va_arg(arg, wchar_t**);
  151. int slen;
  152. buffer_read(iobuf, IOBUF_T_WSTR, NULL, &slen, rpos);
  153. // *pstr = (wchar_t*)malloc(slen+2); // null terminated is two bytes
  154. *pstr = new wchar_t[slen+2];
  155. buffer_read(iobuf, IOBUF_T_WSTR, *pstr, 0, rpos);
  156. }
  157. break;
  158. case 'b':case 'B':
  159. {
  160. void *buf = va_arg(arg, void*);
  161. int size = va_arg(arg, int);
  162. buffer_read(iobuf, IOBUF_T_BUF, buf, &size, rpos);
  163. }
  164. break;
  165. default:
  166. assert(0);
  167. break;
  168. }
  169. p++;
  170. }
  171. }
  172. }
  173. class BufferFormatRead{
  174. public:
  175. static void buffer_format_read(const char *iobuf, int* rpos, const char *fmt, ...)
  176. {
  177. va_list arg;
  178. va_start(arg, fmt);
  179. buffer_format_readv(iobuf, rpos, fmt, arg);
  180. va_end(arg);
  181. }
  182. };
  183. template<class T>
  184. static inline void ReadT(const char *iobuf, T &t, int* rpos){
  185. int size = sizeof(t);
  186. buffer_read(iobuf, IOBUF_T_BUF, &t, &size, rpos);
  187. }
  188. static inline void ReadT(const char *iobuf, void* data, int &len, int* rpos){
  189. buffer_read(iobuf, IOBUF_T_BUF, data, &len, rpos);
  190. }
  191. template<class T>
  192. static inline void ReadArrayT(const char *iobuf, CAutoArray<T> &t, int* rpos){
  193. int nArrayNum(0);
  194. buffer_read(iobuf, IOBUF_T_I4, &nArrayNum, NULL, rpos);
  195. if (nArrayNum >0)
  196. {
  197. t.Init(nArrayNum);
  198. for(int i=0; i<nArrayNum; i++)
  199. {
  200. ReadT(iobuf, t[i], rpos);
  201. }
  202. }
  203. }
  204. static inline void ReadT(const char *iobuf, CSimpleStringA &t, int* rpos){
  205. wchar_t *wt = NULL;
  206. BufferFormatRead::buffer_format_read(iobuf, rpos, "w", &wt); // string is unicode so we can compatible with silverlight
  207. CSimpleStringW wStr = wt;
  208. free(wt);
  209. t = CSimpleStringW2A(wStr);
  210. }
  211. static inline void ReadT(const char *iobuf, CSimpleStringW &t, int* rpos){
  212. wchar_t *wt = NULL;
  213. BufferFormatRead::buffer_format_read(iobuf, rpos, "w", &wt); // string is unicode so we can compatible with silverlight
  214. t = wt;
  215. free(wt);
  216. }
  217. /////////////////// Read Buf End///////////////////////
  218. ////////////////// Write Buffer Start /////////////////////
  219. static void expand(char *iobuf, int head_capacity, int newcapacity,
  220. int *capacity, int *hcapacity, int* rpos, int* wpos)
  221. {
  222. if (head_capacity == -1) {
  223. int t = *capacity;
  224. while (newcapacity > t)
  225. t = t*2;
  226. if (t > *capacity) {
  227. iobuf = (char*)realloc(iobuf, t);
  228. *capacity = t;
  229. }
  230. } else if (newcapacity == -1) {
  231. int t = *hcapacity;
  232. while (head_capacity > t)
  233. t = t*2;
  234. if (t > *rpos) {
  235. char *new_data;
  236. int new_rpos;
  237. int new_wpos;
  238. newcapacity = *capacity + (t - *hcapacity);
  239. // new_data = (char*)malloc(newcapacity);
  240. new_data = new char[newcapacity];
  241. new_rpos = t;
  242. new_wpos = new_rpos + (*wpos - *rpos);
  243. memcpy(new_data+new_rpos, iobuf+*rpos, *wpos - *rpos);
  244. free(iobuf);
  245. iobuf = new_data;
  246. *rpos = new_rpos;
  247. *wpos = new_wpos;
  248. *hcapacity = t;
  249. *capacity = newcapacity;
  250. }
  251. } else {
  252. int t = *capacity;
  253. // char *new_data = (char*)malloc(t);
  254. char *new_data = new char[t];
  255. int new_rpos = head_capacity;
  256. int new_wpos = new_rpos + (*wpos - *rpos);
  257. while (newcapacity > t)
  258. t = t*2;
  259. memcpy(new_data+new_rpos, iobuf+*rpos, *wpos - *rpos);
  260. free(iobuf);
  261. iobuf = new_data;
  262. *rpos = new_rpos;
  263. *wpos = new_wpos;
  264. *capacity = t;
  265. }
  266. }
  267. static void buffer_write_buf(char *iobuf, const char *buf, int n, int* wpos, int* capacity)
  268. {
  269. int rpos = 0;
  270. int hcapacity = 0;
  271. if ( n+(*wpos) > *capacity )
  272. expand(iobuf, -1, n + *wpos, capacity, &hcapacity, &rpos, wpos);
  273. memcpy(iobuf+*wpos, buf, n);
  274. *wpos += n;
  275. }
  276. static int write_7bit_int(unsigned char buf[8], unsigned int v)
  277. {
  278. int i = 0;
  279. while (v >= 0x80) {
  280. buf[i++] = (unsigned char)(v | 0x80); // set most left bit == 1
  281. v >>= 7;
  282. }
  283. buf[i++] = (unsigned char)v;
  284. return i;
  285. }
  286. static void buffer_write_7bit_int(char *iobuf, unsigned int v, int* wpos, int* capacity)
  287. {
  288. char buf[8];
  289. int n = write_7bit_int((unsigned char*)buf, v);
  290. buffer_write_buf(iobuf, buf, n, wpos, capacity);
  291. }
  292. void buffer_write(char *iobuf, int t, const void *v, int n, int* wpos, int* capacity)
  293. {
  294. int len = 0;
  295. switch (t) {
  296. case IOBUF_T_I8:
  297. len += 8;
  298. buffer_write_buf(iobuf, (const char*)v, len, wpos, capacity);
  299. break;
  300. case IOBUF_T_I4:
  301. len += 4;
  302. buffer_write_buf(iobuf, (const char*)v, len, wpos, capacity);
  303. break;
  304. case IOBUF_T_I2:
  305. len += 2;
  306. buffer_write_buf(iobuf, (const char*)v, len, wpos, capacity);
  307. break;
  308. case IOBUF_T_I1:
  309. len += 1;
  310. buffer_write_buf(iobuf, (const char*)v, len, wpos, capacity);
  311. break;
  312. case IOBUF_T_STR:
  313. if (!v) {
  314. n = 0;
  315. } else {
  316. if (n == -1)
  317. n = strlen((const char*)v);
  318. }
  319. buffer_write_7bit_int(iobuf, (unsigned int)n, wpos, capacity);
  320. if (n > 0)
  321. buffer_write_buf(iobuf, (const char*)v, n, wpos, capacity);
  322. break;
  323. case IOBUF_T_WSTR:
  324. if (!v) {
  325. n = 0;
  326. } else {
  327. if (n == -1)
  328. n = wcslen((const wchar_t*)v)<<1;
  329. }
  330. buffer_write_7bit_int(iobuf, n, wpos, capacity);
  331. if (n > 0)
  332. buffer_write_buf(iobuf, (const char*)v, n, wpos, capacity);
  333. break;
  334. case IOBUF_T_BUF:
  335. if (n > 0)
  336. buffer_write_buf(iobuf, (const char*)v, n, wpos, capacity);
  337. break;
  338. case IOBUF_T_7BIT:
  339. buffer_write_7bit_int(iobuf, *(unsigned int*)v, wpos, capacity);
  340. break;
  341. default:
  342. assert(0);
  343. break;
  344. }
  345. }
  346. template<class T>
  347. static inline void WriteT(char *iobuf, T &t, int* wpos, int* capacity)
  348. {
  349. buffer_write(iobuf, IOBUF_T_BUF, &t, sizeof(t), wpos, capacity);
  350. }
  351. template<class T>
  352. static inline void WriteT(char *iobuf, const T &t)
  353. {
  354. buffer_write(iobuf, IOBUF_T_BUF, &t, sizeof(t), wpos, capacity);
  355. }
  356. template<class T>
  357. static inline void WriteArrayT(char *iobuf, CAutoArray<T> &t, int* wpos, int* capacity)
  358. {
  359. int nArrayNum = t.GetCount();
  360. buffer_write(iobuf, IOBUF_T_I4, &nArrayNum, 0, wpos, capacity);
  361. for(int i=0; i<nArrayNum; i++)
  362. {
  363. WriteT(iobuf, t[i], wpos, capacity);
  364. }
  365. }
  366. template<class T>
  367. static inline void WriteArrayT(char *iobuf, const CAutoArray<T> &t, int* wpos, int* capacity)
  368. {
  369. int nArrayNum = t.GetCount();
  370. buffer_write(iobuf, IOBUF_T_I4, &nArrayNum, 0, wpos, capacity);
  371. for(int i=0; i<nArrayNum; i++)
  372. {
  373. WriteT(iobuf, t[i], wpos, capacity);
  374. }
  375. }
  376. static inline void WriteT(char *iobuf, CSimpleStringA &t, int* wpos, int* capacity)
  377. {
  378. CSimpleStringW wt = CSimpleStringA2W(t); // string is unicode so we can compatible with silverlight
  379. buffer_write(iobuf, IOBUF_T_WSTR, wt.GetData(), -1, wpos, capacity);
  380. }
  381. static inline void WriteT(char *iobuf, CSimpleStringW &t, int* wpos, int* capacity)
  382. {
  383. buffer_write(iobuf, IOBUF_T_WSTR, t.GetData(), -1, wpos, capacity);
  384. }
  385. static inline void WriteT(char *iobuf, const CSimpleStringA &t, int* wpos, int* capacity)
  386. {
  387. CSimpleStringW wt = CSimpleStringA2W(t); // string is unicode so we can compatible with silverlight
  388. buffer_write(iobuf, IOBUF_T_WSTR, wt.GetData(), -1, wpos, capacity);
  389. }
  390. static inline void WriteT(char *iobuf, const CSimpleStringW &t, int* wpos, int* capacity)
  391. {
  392. buffer_write(iobuf, IOBUF_T_WSTR, t.GetData(), -1, wpos, capacity);
  393. }
  394. static inline void WriteT(char *iobuf, char* t, int* wpos, int* capacity, int len)
  395. {
  396. buffer_write(iobuf, IOBUF_T_BUF, t, len, wpos, capacity);
  397. }
  398. // static inline void WriteT(char *iobuf, CBlob &t)
  399. // {
  400. // // iobuffer_write(iobuf, IOBUF_T_I4, &t.m_iLength, 0);
  401. // // iobuffer_write(iobuf, IOBUF_T_BUF, t.m_pData, t.m_iLength);
  402. // }
  403. //
  404. //
  405. // static inline void WriteT(char *iobuf, const CBlob &t)
  406. // {
  407. // // iobuffer_write(iobuf, IOBUF_T_I4, &t.m_iLength, 0);
  408. // // iobuffer_write(iobuf, IOBUF_T_BUF, t.m_pData, t.m_iLength);
  409. // }
  410. ///////////////// Write Buffer End //////////////////////
  411. }
  412. #endif