#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 #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); #if (defined _WIN32 || defined _WIN64) * ((char*)v + len) = 0; // wchar termination char is 2 byte *((char*)v + len + 1) = 0; #else memset((void*)((char*)v + len), 0, sizeof(wchar_t)); #endif 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); #if (defined _WIN32 || defined _WIN64) * pstr = new wchar_t[slen + 2]; #else * pstr = new wchar_t[slen + 1]; #endif 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 < nArrayNum; i++) { ReadT(iobuf, t[i], rpos); } } } static inline void ReadT(const char* iobuf, CSimpleStringA& t, int* rpos) { #if (defined _WIN32 || defined _WIN64) wchar_t* wt = NULL; #else SPCHAR* wt = NULL; #endif BufferFormatRead::buffer_format_read(iobuf, rpos, "w", &wt); // string is unicode so we can compatible with silverlight CSimpleStringW wStr = wt; free(wt); t = CSimpleStringW2A(wStr); } static inline void ReadT(const char* iobuf, CSimpleStringW& t, int* rpos) { #if (defined _WIN32 || defined _WIN64) wchar_t* wt = NULL; #else SPCHAR* wt = NULL; #endif BufferFormatRead::buffer_format_read(iobuf, rpos, "w", &wt); // string is unicode so we can compatible with silverlight t = wt; free(wt); } /////////////////// Read Buf End/////////////////////// ////////////////// Write Buffer Start ///////////////////// static void expand(char* iobuf, int head_capacity, int newcapacity, int* capacity, int* hcapacity, int* rpos, int* wpos) { if (head_capacity == -1) { int t = *capacity; while (newcapacity > 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) #if (defined _WIN32 || defined _WIN64) n = wcslen((const wchar_t*)v) << 1; #else n = wcslen((const wchar_t*)v) << 2; #endif } 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 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 < nArrayNum; i++) { WriteT(iobuf, t[i], wpos, capacity); } } template 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 < nArrayNum; i++) { WriteT(iobuf, t[i], wpos, capacity); } } static inline void WriteT(char* iobuf, CSimpleStringA& t, int* wpos, int* capacity) { CSimpleStringW wt = CSimpleStringA2W(t); // string is unicode so we can compatible with silverlight buffer_write(iobuf, IOBUF_T_WSTR, wt.GetData(), -1, wpos, capacity); } static inline void WriteT(char* iobuf, CSimpleStringW& t, int* wpos, int* capacity) { buffer_write(iobuf, IOBUF_T_WSTR, t.GetData(), -1, wpos, capacity); } static inline void WriteT(char* iobuf, const CSimpleStringA& t, int* wpos, int* capacity) { CSimpleStringW wt = CSimpleStringA2W(t); // string is unicode so we can compatible with silverlight buffer_write(iobuf, IOBUF_T_WSTR, wt.GetData(), -1, wpos, capacity); } static inline void WriteT(char* iobuf, const CSimpleStringW& t, int* wpos, int* capacity) { buffer_write(iobuf, IOBUF_T_WSTR, t.GetData(), -1, wpos, capacity); } static inline void WriteT(char* iobuf, const char* t, int* wpos, int* capacity, int len) { buffer_write(iobuf, IOBUF_T_BUF, t, len, wpos, capacity); } // static inline void WriteT(char *iobuf, CBlob &t) // { // // iobuffer_write(iobuf, IOBUF_T_I4, &t.m_iLength, 0); // // iobuffer_write(iobuf, IOBUF_T_BUF, t.m_pData, t.m_iLength); // } // // // static inline void WriteT(char *iobuf, const CBlob &t) // { // // iobuffer_write(iobuf, IOBUF_T_I4, &t.m_iLength, 0); // // iobuffer_write(iobuf, IOBUF_T_BUF, t.m_pData, t.m_iLength); // } ///////////////// Write Buffer End ////////////////////// } #endif