#ifndef CBufferOperation_h #define CBufferOperation_h #include "SimpleString.h" #include "AutoArray.h" #include "Blob.h" namespace Chromium{ #define IOBUF_T_I8 0 #define IOBUF_T_I4 1 #define IOBUF_T_I2 2 #define IOBUF_T_I1 3 #define IOBUF_T_STR 4 #define IOBUF_T_BUF 5 #define IOBUF_T_WSTR 6 /* wchar_t */ #define IOBUF_T_7BIT 7 /////////////////// Read Buf Start /////////////////////// static void buffer_read_buf(const char *iobuf, char *buf, int n, int* rpos) { // assert(content_size(iobuf) >= n); memcpy(buf, iobuf + *rpos, n); *rpos += n; } static void buffer_read_7bit_int(const char *iobuf, int *v, int* rpos) { int count = 0; int shift = 0; unsigned char b; do { if (shift == 5*7) // corrupted stream assert(0); b = iobuf[*rpos]; *rpos += 1; count |= (b & 0x7F) << shift; shift += 7; } while (b & 0x80); // most left bit is flag *v = count; } static void buffer_read(const char *iobuf, int t, void *v, int *n, int* rpos){ int len = 0; switch (t) { case IOBUF_T_I8: len += 8; buffer_read_buf(iobuf, (char*)v, len, rpos); break; case IOBUF_T_I4: len += 4; buffer_read_buf(iobuf, (char*)v, len, rpos); break; case IOBUF_T_I2: len += 2; buffer_read_buf(iobuf, (char*)v, len, rpos); break; case IOBUF_T_I1: len += 1; buffer_read_buf(iobuf, (char*)v, len, rpos); break; case IOBUF_T_STR: if (v) { int old_rpos = *rpos; buffer_read_7bit_int(iobuf, &len, rpos); if (!n || len < *n) { buffer_read_buf(iobuf, (char *)v, len, rpos); *((char*)v + len) = 0; if (n) *n = len; } else { *rpos = old_rpos; *n = len; } } else { if (n) { int old_rpos = *rpos; buffer_read_7bit_int(iobuf, &len, rpos); *rpos = old_rpos; *n = len; } else { assert(0); } } break; case IOBUF_T_WSTR: if (v) { int old_rpos = *rpos; buffer_read_7bit_int(iobuf, &len, rpos); if (!n || len < *n) { buffer_read_buf(iobuf, (char*)v, len, rpos); /* wchar_t */ *((char*)v + len) = 0; // wchar termination char is 2 byte *((char*)v + len+1) = 0; if (n) *n = len; } else { *rpos = old_rpos; *n = len; } } else { if (n) { int old_rpos = *rpos; buffer_read_7bit_int(iobuf, &len, rpos); *rpos = old_rpos; *n = len; } else { assert(0); } } break; case IOBUF_T_BUF: if (*n > 0) buffer_read_buf(iobuf, (char*)v, *n, rpos); break; case IOBUF_T_7BIT: buffer_read_7bit_int(iobuf, (int*)v, rpos); break; default: assert(0); } } void buffer_format_readv(const char *iobuf, int* rpos, const char *fmt, va_list arg) { if (fmt) { const char *p = fmt; while (*p) { switch (*p) { case '8': buffer_read(iobuf, IOBUF_T_I8, va_arg(arg, void*), NULL, rpos); break; case '7': // 7bit int code buffer_read(iobuf, IOBUF_T_7BIT, va_arg(arg, void*), NULL, rpos); break; case '4': buffer_read(iobuf, IOBUF_T_I4, va_arg(arg, void*), 0, rpos); break; case '2': buffer_read(iobuf, IOBUF_T_I2, va_arg(arg, void*), 0, rpos); break; case '1': buffer_read(iobuf, IOBUF_T_I1, va_arg(arg, void*), 0, rpos); break; case 's':case 'S': { char **pstr = va_arg(arg, char**); int slen; buffer_read(iobuf, IOBUF_T_STR, NULL, &slen, rpos); //*pstr = (char*)malloc(slen+1); *pstr = new char[slen+1]; buffer_read(iobuf, IOBUF_T_STR, *pstr, 0, rpos); } break; case 'w': case 'W': { wchar_t **pstr = va_arg(arg, wchar_t**); int slen; buffer_read(iobuf, IOBUF_T_WSTR, NULL, &slen, rpos); // *pstr = (wchar_t*)malloc(slen+2); // null terminated is two bytes *pstr = new wchar_t[slen+2]; buffer_read(iobuf, IOBUF_T_WSTR, *pstr, 0, rpos); } break; case 'b':case 'B': { void *buf = va_arg(arg, void*); int size = va_arg(arg, int); buffer_read(iobuf, IOBUF_T_BUF, buf, &size, rpos); } break; default: assert(0); break; } p++; } } } class BufferFormatRead{ public: static void buffer_format_read(const char *iobuf, int* rpos, const char *fmt, ...) { va_list arg; va_start(arg, fmt); buffer_format_readv(iobuf, rpos, fmt, arg); va_end(arg); } }; template static inline void ReadT(const char *iobuf, T &t, int* rpos){ int size = sizeof(t); buffer_read(iobuf, IOBUF_T_BUF, &t, &size, rpos); } static inline void ReadT(const char *iobuf, void* data, int &len, int* rpos){ buffer_read(iobuf, IOBUF_T_BUF, data, &len, rpos); } template static inline void ReadArrayT(const char *iobuf, CAutoArray &t, int* rpos){ int nArrayNum(0); buffer_read(iobuf, IOBUF_T_I4, &nArrayNum, NULL, rpos); if (nArrayNum >0) { t.Init(nArrayNum); for(int i=0; i t) t = t*2; if (t > *capacity) { iobuf = (char*)realloc(iobuf, t); *capacity = t; } } else if (newcapacity == -1) { int t = *hcapacity; while (head_capacity > t) t = t*2; if (t > *rpos) { char *new_data; int new_rpos; int new_wpos; newcapacity = *capacity + (t - *hcapacity); // new_data = (char*)malloc(newcapacity); new_data = new char[newcapacity]; new_rpos = t; new_wpos = new_rpos + (*wpos - *rpos); memcpy(new_data+new_rpos, iobuf+*rpos, *wpos - *rpos); free(iobuf); iobuf = new_data; *rpos = new_rpos; *wpos = new_wpos; *hcapacity = t; *capacity = newcapacity; } } else { int t = *capacity; // char *new_data = (char*)malloc(t); char *new_data = new char[t]; int new_rpos = head_capacity; int new_wpos = new_rpos + (*wpos - *rpos); while (newcapacity > t) t = t*2; memcpy(new_data+new_rpos, iobuf+*rpos, *wpos - *rpos); free(iobuf); iobuf = new_data; *rpos = new_rpos; *wpos = new_wpos; *capacity = t; } } static void buffer_write_buf(char *iobuf, const char *buf, int n, int* wpos, int* capacity) { int rpos = 0; int hcapacity = 0; if ( n+(*wpos) > *capacity ) expand(iobuf, -1, n + *wpos, capacity, &hcapacity, &rpos, wpos); memcpy(iobuf+*wpos, buf, n); *wpos += n; } static int write_7bit_int(unsigned char buf[8], unsigned int v) { int i = 0; while (v >= 0x80) { buf[i++] = (unsigned char)(v | 0x80); // set most left bit == 1 v >>= 7; } buf[i++] = (unsigned char)v; return i; } static void buffer_write_7bit_int(char *iobuf, unsigned int v, int* wpos, int* capacity) { char buf[8]; int n = write_7bit_int((unsigned char*)buf, v); buffer_write_buf(iobuf, buf, n, wpos, capacity); } void buffer_write(char *iobuf, int t, const void *v, int n, int* wpos, int* capacity) { int len = 0; switch (t) { case IOBUF_T_I8: len += 8; buffer_write_buf(iobuf, (const char*)v, len, wpos, capacity); break; case IOBUF_T_I4: len += 4; buffer_write_buf(iobuf, (const char*)v, len, wpos, capacity); break; case IOBUF_T_I2: len += 2; buffer_write_buf(iobuf, (const char*)v, len, wpos, capacity); break; case IOBUF_T_I1: len += 1; buffer_write_buf(iobuf, (const char*)v, len, wpos, capacity); break; case IOBUF_T_STR: if (!v) { n = 0; } else { if (n == -1) n = strlen((const char*)v); } buffer_write_7bit_int(iobuf, (unsigned int)n, wpos, capacity); if (n > 0) buffer_write_buf(iobuf, (const char*)v, n, wpos, capacity); break; case IOBUF_T_WSTR: if (!v) { n = 0; } else { if (n == -1) n = wcslen((const wchar_t*)v)<<1; } buffer_write_7bit_int(iobuf, n, wpos, capacity); if (n > 0) buffer_write_buf(iobuf, (const char*)v, n, wpos, capacity); break; case IOBUF_T_BUF: if (n > 0) buffer_write_buf(iobuf, (const char*)v, n, wpos, capacity); break; case IOBUF_T_7BIT: buffer_write_7bit_int(iobuf, *(unsigned int*)v, wpos, capacity); break; default: assert(0); break; } } template static inline void WriteT(char *iobuf, T &t, int* wpos, int* capacity) { buffer_write(iobuf, IOBUF_T_BUF, &t, sizeof(t), wpos, capacity); } template static inline void WriteT(char *iobuf, const T &t) { buffer_write(iobuf, IOBUF_T_BUF, &t, sizeof(t), wpos, capacity); } template static inline void WriteArrayT(char *iobuf, CAutoArray &t, int* wpos, int* capacity) { int nArrayNum = t.GetCount(); buffer_write(iobuf, IOBUF_T_I4, &nArrayNum, 0, wpos, capacity); for(int i=0; i static inline void WriteArrayT(char *iobuf, const CAutoArray &t, int* wpos, int* capacity) { int nArrayNum = t.GetCount(); buffer_write(iobuf, IOBUF_T_I4, &nArrayNum, 0, wpos, capacity); for(int i=0; i