iobuffer.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. #include "precompile.h"
  2. #include "iobuffer.h"
  3. #include "refcnt.h"
  4. #include "list.h"
  5. #include <stdarg.h>
  6. #include "dbgutil.h"
  7. #include <winpr/string.h>
  8. #include <winpr/wlog.h>
  9. #include "memutil.h"
  10. #define TAG TOOLKIT_TAG("iobuffer")
  11. struct iobuffer_t
  12. {
  13. struct list_head sp_entry;
  14. char *sp_data;
  15. int sp_capacity;
  16. int sp_hdr_capacity;
  17. int sp_wpos;
  18. int sp_rpos;
  19. int sp_linkId;
  20. char bussinessId[LINKINFO_BUSSID_LEN];
  21. char traceId[LINKINFO_TRACEID_LEN];
  22. char spanId[LINKINFO_SPANID_LEN];
  23. char parentSpanId[LINKINFO_PARENTSPANID_LEN];
  24. void *sp_user_data;
  25. DECLARE_REF_COUNT_MEMBER(sp_ref_cnt);
  26. };
  27. #define DEFAULT_CAPACITY 256
  28. #define DEFAULT_HEADER_CAPACITY 228
  29. static void expand(iobuffer_t *iobuf, int head_capacity, int newcapacity)
  30. {
  31. if (head_capacity == -1) {
  32. int t = iobuf->sp_capacity;
  33. while (newcapacity > t)
  34. t = t*2;
  35. if (t > iobuf->sp_capacity) {
  36. iobuf->sp_data = (char*)realloc(iobuf->sp_data, t);
  37. iobuf->sp_capacity = t;
  38. }
  39. } else if (newcapacity == -1) {
  40. int t = iobuf->sp_hdr_capacity;
  41. while (head_capacity > t)
  42. t = t*2;
  43. if (t > iobuf->sp_rpos) {
  44. char *new_data;
  45. int new_rpos;
  46. int new_wpos;
  47. newcapacity = iobuf->sp_capacity + (t - iobuf->sp_hdr_capacity);
  48. new_data = malloc(newcapacity);
  49. new_rpos = t;
  50. new_wpos = new_rpos + (iobuf->sp_wpos - iobuf->sp_rpos);
  51. memcpy(new_data+new_rpos, iobuf->sp_data+iobuf->sp_rpos, iobuf->sp_wpos - iobuf->sp_rpos);
  52. free(iobuf->sp_data);
  53. iobuf->sp_data = new_data;
  54. iobuf->sp_rpos = new_rpos;
  55. iobuf->sp_wpos = new_wpos;
  56. iobuf->sp_hdr_capacity = t;
  57. iobuf->sp_capacity = newcapacity;
  58. }
  59. } else {
  60. int t = iobuf->sp_capacity;
  61. char *new_data = (char*)malloc(t);
  62. int new_rpos = head_capacity;
  63. int new_wpos = new_rpos + (iobuf->sp_wpos - iobuf->sp_rpos);
  64. while (newcapacity > t)
  65. t = t*2;
  66. memcpy(new_data+new_rpos, iobuf->sp_data+iobuf->sp_rpos, iobuf->sp_wpos - iobuf->sp_rpos);
  67. free(iobuf->sp_data);
  68. iobuf->sp_data = new_data;
  69. iobuf->sp_rpos = new_rpos;
  70. iobuf->sp_wpos = new_wpos;
  71. iobuf->sp_capacity = t;
  72. }
  73. }
  74. static __inline int empty_size(iobuffer_t *iobuf)
  75. {
  76. return iobuf->sp_capacity - iobuf->sp_wpos;
  77. }
  78. static __inline int content_size(iobuffer_t *iobuf)
  79. {
  80. return iobuf->sp_wpos - iobuf->sp_rpos;
  81. }
  82. static void destroy(iobuffer_t *iobuf)
  83. {
  84. WLog_DBG(TAG, "iobuffer destroy 0x%0X", iobuf);
  85. iobuffer_set_capacity(iobuf, 0);
  86. free(iobuf);
  87. }
  88. static void iobuffer_write_buf(iobuffer_t *iobuf, const char *buf, int n)
  89. {
  90. if (n+iobuf->sp_wpos > iobuf->sp_capacity)
  91. expand(iobuf, -1, n + iobuf->sp_wpos);
  92. memcpy(iobuf->sp_data+iobuf->sp_wpos, buf, n);
  93. iobuf->sp_wpos += n;
  94. }
  95. static void iobuffer_write_head_buf(iobuffer_t *iobuf, const char *buf, int n)
  96. {
  97. if (iobuf->sp_rpos < n)
  98. expand(iobuf, iobuf->sp_hdr_capacity-iobuf->sp_rpos+n, -1);
  99. iobuf->sp_rpos -= n;
  100. memcpy(iobuf->sp_data+iobuf->sp_rpos, buf, n);
  101. }
  102. static int write_7bit_int(unsigned char buf[8], unsigned int v)
  103. {
  104. int i = 0;
  105. while (v >= 0x80) {
  106. buf[i++] = (unsigned char)(v | 0x80); // set most left bit == 1
  107. v >>= 7;
  108. }
  109. buf[i++] = (unsigned char)v;
  110. return i;
  111. }
  112. static void iobuffer_write_7bit_int(iobuffer_t *iobuf, unsigned int v)
  113. {
  114. char buf[8];
  115. int n = write_7bit_int(buf, v);
  116. iobuffer_write_buf(iobuf, buf, n);
  117. }
  118. static void iobuffer_write_head_7bit_int(iobuffer_t *iobuf, unsigned int v)
  119. {
  120. char buf[8];
  121. int n = write_7bit_int(buf, v);
  122. iobuffer_write_head_buf(iobuf, buf, n);
  123. }
  124. static void iobuffer_read_buf(iobuffer_t *iobuf, char *buf, int n)
  125. {
  126. //WLog_DBG(TAG, "iobuffer_read_buf %d, retrive %d byte(s)", content_size(iobuf), n);
  127. TOOLKIT_ASSERT(content_size(iobuf) >= n);
  128. TOOLKIT_ASSERT(buf);
  129. memcpy(buf, iobuf->sp_data+iobuf->sp_rpos, n);
  130. iobuf->sp_rpos += n;
  131. }
  132. static void iobuffer_read_7bit_int(iobuffer_t *iobuf, int *v)
  133. {
  134. int count = 0;
  135. int shift = 0;
  136. unsigned char b;
  137. do {
  138. if (shift == 5*7) // corrupted stream
  139. TOOLKIT_ASSERT(0);
  140. b = iobuf->sp_data[iobuf->sp_rpos ++];
  141. count |= (b & 0x7F) << shift;
  142. shift += 7;
  143. } while (b & 0x80); // most left bit is flag
  144. *v = count;
  145. }
  146. #ifdef DEBUD_MEM_TRACE
  147. static iobuffer_t* iobuffer_create_(int head_capacity, int capacity)
  148. #else
  149. TOOLKIT_API iobuffer_t* iobuffer_create(int head_capacity, int capacity)
  150. #endif
  151. {
  152. iobuffer_t *iobuf;
  153. if (head_capacity <= 0)
  154. head_capacity = DEFAULT_HEADER_CAPACITY;
  155. if (capacity <= 0) {
  156. capacity = head_capacity + DEFAULT_CAPACITY;
  157. } else {
  158. capacity += head_capacity;
  159. }
  160. iobuf = MALLOC_T(iobuffer_t);
  161. memset(iobuf, 0, sizeof(iobuffer_t));
  162. iobuf->sp_hdr_capacity = head_capacity;
  163. iobuf->sp_capacity = capacity;
  164. iobuf->sp_data = malloc(capacity);
  165. iobuf->sp_user_data = NULL;
  166. iobuf->sp_entry.next = iobuf->sp_entry.prev = NULL;
  167. iobuf->sp_linkId = 0;
  168. memset(iobuf->bussinessId, 0, sizeof(iobuf->bussinessId));
  169. memset(iobuf->traceId, 0, sizeof(iobuf->traceId));
  170. memset(iobuf->spanId, 0, sizeof(iobuf->spanId));
  171. memset(iobuf->parentSpanId, 0, sizeof(iobuf->parentSpanId));
  172. iobuffer_reset(iobuf);
  173. REF_COUNT_INIT(&iobuf->sp_ref_cnt);
  174. WLog_DBG(TAG, "iobuffer create 0x%0X", iobuf);
  175. return iobuf;
  176. }
  177. TOOLKIT_API void iobuffer_destroy(iobuffer_t *iobuf)
  178. {
  179. iobuffer_dec_ref(iobuf);
  180. }
  181. #ifdef DEBUD_MEM_TRACE
  182. static iobuffer_t* iobuffer_clone_(iobuffer_t* iobuf)
  183. #else
  184. TOOLKIT_API iobuffer_t* iobuffer_clone(iobuffer_t* iobuf)
  185. #endif
  186. {
  187. iobuffer_t *newiobuf;
  188. newiobuf = iobuffer_create(iobuf->sp_hdr_capacity, iobuf->sp_capacity);
  189. memcpy(newiobuf->sp_data+iobuf->sp_rpos, iobuf->sp_data+iobuf->sp_rpos, iobuf->sp_wpos-iobuf->sp_rpos);
  190. newiobuf->sp_rpos = iobuf->sp_rpos;
  191. newiobuf->sp_wpos = iobuf->sp_wpos;
  192. newiobuf->sp_user_data = iobuf->sp_user_data;
  193. return newiobuf;
  194. }
  195. TOOLKIT_API void iobuffer_reset(iobuffer_t *iobuf)
  196. {
  197. iobuf->sp_rpos = iobuf->sp_hdr_capacity;
  198. iobuf->sp_wpos = iobuf->sp_hdr_capacity;
  199. }
  200. TOOLKIT_API int iobuffer_get_capacity(iobuffer_t *iobuf)
  201. {
  202. return iobuf->sp_capacity;
  203. }
  204. TOOLKIT_API void iobuffer_set_capacity(iobuffer_t *iobuf, int capacity)
  205. {
  206. iobuf->sp_data = (char*)realloc(iobuf->sp_data, capacity);
  207. if (iobuf->sp_wpos > capacity)
  208. iobuf->sp_wpos = capacity;
  209. if (iobuf->sp_rpos > capacity)
  210. iobuf->sp_rpos = capacity;
  211. iobuf->sp_capacity = capacity;
  212. }
  213. TOOLKIT_API char *iobuffer_data(iobuffer_t *iobuf, int offset)
  214. {
  215. if (offset != -1) {
  216. return iobuf->sp_data + iobuf->sp_rpos + offset;
  217. } else {
  218. return iobuf->sp_data + iobuf->sp_wpos;
  219. }
  220. }
  221. TOOLKIT_API int iobuffer_get_length(iobuffer_t *iobuf)
  222. {
  223. return iobuf->sp_wpos - iobuf->sp_rpos;
  224. }
  225. TOOLKIT_API void iobuffer_set_length(iobuffer_t *iobuf, int length)
  226. {
  227. iobuf->sp_wpos = iobuf->sp_rpos + length;
  228. if (iobuf->sp_wpos > iobuf->sp_capacity)
  229. iobuf->sp_wpos = iobuf->sp_capacity;
  230. }
  231. TOOLKIT_API void iobuffer_push_count(iobuffer_t *iobuf, int n)
  232. {
  233. TOOLKIT_ASSERT(empty_size(iobuf) >= n);
  234. iobuf->sp_wpos += n;
  235. }
  236. TOOLKIT_API void iobuffer_pop_count(iobuffer_t *iobuf, int n)
  237. {
  238. TOOLKIT_ASSERT(content_size(iobuf) >= n);
  239. iobuf->sp_rpos += n;
  240. }
  241. TOOLKIT_API void iobuffer_write(iobuffer_t *iobuf, int t, const void *v, int n)
  242. {
  243. int len = 0;
  244. switch (t) {
  245. case IOBUF_T_I8:
  246. len += 4;
  247. case IOBUF_T_I4:
  248. len += 2;
  249. case IOBUF_T_I2:
  250. len += 1;
  251. case IOBUF_T_I1:
  252. len += 1;
  253. iobuffer_write_buf(iobuf, v, len);
  254. break;
  255. case IOBUF_T_STR:
  256. if (!v) {
  257. n = 0;
  258. } else {
  259. if (n == -1)
  260. n = strlen(v);
  261. }
  262. iobuffer_write_7bit_int(iobuf, (unsigned int)n);
  263. if (n > 0)
  264. iobuffer_write_buf(iobuf, v, n);
  265. break;
  266. case IOBUF_T_WSTR:
  267. if (!v) {
  268. n = 0;
  269. } else {
  270. if (n == -1) {
  271. #if defined(_MSC_VER)
  272. n = wcslen(v) << 1;
  273. #else
  274. // be compatible with winpr [4/2/2020 16:02 Gifur]
  275. n = _wcslen(v) << 1;
  276. #endif //_MSC_VER
  277. }
  278. }
  279. iobuffer_write_7bit_int(iobuf, n);
  280. if (n > 0)
  281. iobuffer_write_buf(iobuf, v, n);
  282. break;
  283. case IOBUF_T_WCSTR:
  284. if (!v) {
  285. n = 0;
  286. } else {
  287. if (n == -1) {
  288. n = wcslen(v) << 2;
  289. }
  290. }
  291. iobuffer_write_7bit_int(iobuf, (unsigned int)n);
  292. if (n > 0)
  293. iobuffer_write_buf(iobuf, v, n);
  294. break;
  295. case IOBUF_T_BUF:
  296. if (n > 0)
  297. iobuffer_write_buf(iobuf, v, n);
  298. break;
  299. case IOBUF_T_7BIT:
  300. iobuffer_write_7bit_int(iobuf, *(unsigned int*)v);
  301. break;
  302. }
  303. }
  304. TOOLKIT_API void iobuffer_write_head(iobuffer_t *iobuf, int t, const void *v, int n)
  305. {
  306. int len = 0;
  307. switch (t) {
  308. case IOBUF_T_I8:
  309. len += 4;
  310. case IOBUF_T_I4:
  311. len += 2;
  312. case IOBUF_T_I2:
  313. len += 1;
  314. case IOBUF_T_I1:
  315. len += 1;
  316. iobuffer_write_head_buf(iobuf, v, len);
  317. break;
  318. case IOBUF_T_STR:
  319. if (!v) {
  320. n = 0;
  321. } else {
  322. if (n == -1) {
  323. n = strlen(v);
  324. }
  325. }
  326. if (n > 0)
  327. iobuffer_write_head_buf(iobuf, v, n);
  328. iobuffer_write_head_7bit_int(iobuf, n);
  329. break;
  330. case IOBUF_T_WSTR:
  331. if (!v) {
  332. n = 0;
  333. } else {
  334. if (n == -1) {
  335. #if defined(_MSC_VER)
  336. n = wcslen(v) << 1;
  337. #else
  338. n = _wcslen(v) << 1;
  339. #endif //_MSC_VER
  340. }
  341. }
  342. if (n > 0)
  343. iobuffer_write_head_buf(iobuf, v, n);
  344. iobuffer_write_head_7bit_int(iobuf, n);
  345. break;
  346. case IOBUF_T_WCSTR:
  347. if (!v) {
  348. n = 0;
  349. } else {
  350. if (n == -1) {
  351. n = wcslen(v) << 2;
  352. }
  353. }
  354. if (n > 0)
  355. iobuffer_write_head_buf(iobuf, v, n);
  356. iobuffer_write_head_7bit_int(iobuf, n);
  357. break;
  358. case IOBUF_T_BUF:
  359. if (n > 0)
  360. iobuffer_write_head_buf(iobuf, v, n);
  361. break;
  362. case IOBUF_T_7BIT:
  363. iobuffer_write_head_7bit_int(iobuf, *(unsigned int*)v);
  364. break;
  365. default:
  366. TOOLKIT_ASSERT(0);
  367. }
  368. }
  369. TOOLKIT_API void iobuffer_read(iobuffer_t *iobuf, int t, void *v, int *n)
  370. {
  371. int len = 0;
  372. switch (t) {
  373. case IOBUF_T_I8:
  374. len += 4;
  375. case IOBUF_T_I4:
  376. len += 2;
  377. case IOBUF_T_I2:
  378. len += 1;
  379. case IOBUF_T_I1:
  380. len += 1;
  381. iobuffer_read_buf(iobuf, v, len);
  382. break;
  383. case IOBUF_T_STR:
  384. if (v) {
  385. int old_rpos = iobuf->sp_rpos;
  386. iobuffer_read_7bit_int(iobuf, &len);
  387. if (!n || len < *n) {
  388. iobuffer_read_buf(iobuf, v, len);
  389. *((char*)v + len) = 0;
  390. if (n)
  391. *n = len;
  392. } else {
  393. iobuf->sp_rpos = old_rpos;
  394. *n = len;
  395. }
  396. } else {
  397. if (n) {
  398. int old_rpos = iobuf->sp_rpos;
  399. iobuffer_read_7bit_int(iobuf, &len);
  400. iobuf->sp_rpos = old_rpos;
  401. *n = len;
  402. } else {
  403. TOOLKIT_ASSERT(0);
  404. }
  405. }
  406. break;
  407. case IOBUF_T_WSTR:
  408. if (v) {
  409. int old_rpos = iobuf->sp_rpos;
  410. iobuffer_read_7bit_int(iobuf, &len);
  411. if (!n || len < *n) {
  412. #if defined(_MSC_VER)
  413. iobuffer_read_buf(iobuf, v, len); /* wchar_t */
  414. *((char*)v + len) = 0; // wchar termination char is 2 byte
  415. *((char*)v + len + 1) = 0;
  416. #else
  417. iobuffer_read_buf(iobuf, v, len); /* WCHAR */
  418. memset((void*)((char*)v + len), 0, sizeof(WCHAR));
  419. #endif //_MSC_VER
  420. if (n)
  421. *n = len;
  422. } else {
  423. iobuf->sp_rpos = old_rpos;
  424. *n = len;
  425. }
  426. } else {
  427. if (n) {
  428. int old_rpos = iobuf->sp_rpos;
  429. iobuffer_read_7bit_int(iobuf, &len);
  430. iobuf->sp_rpos = old_rpos;
  431. *n = len;
  432. } else {
  433. TOOLKIT_ASSERT(0);
  434. }
  435. }
  436. break;
  437. case IOBUF_T_WCSTR:
  438. if (v) {
  439. int old_rpos = iobuf->sp_rpos;
  440. iobuffer_read_7bit_int(iobuf, &len);
  441. if (!n || len < *n) {
  442. iobuffer_read_buf(iobuf, v, len);
  443. memset((void*)((char*)v + len), 0, sizeof(wchar_t));
  444. if (n)
  445. *n = len;
  446. } else {
  447. iobuf->sp_rpos = old_rpos;
  448. *n = len;
  449. }
  450. } else {
  451. if (n) {
  452. int old_rpos = iobuf->sp_rpos;
  453. iobuffer_read_7bit_int(iobuf, &len);
  454. iobuf->sp_rpos = old_rpos;
  455. *n = len;
  456. } else {
  457. TOOLKIT_ASSERT(0);
  458. }
  459. }
  460. break;
  461. case IOBUF_T_BUF:
  462. if (*n > 0)
  463. iobuffer_read_buf(iobuf, v, *n);
  464. break;
  465. case IOBUF_T_7BIT:
  466. iobuffer_read_7bit_int(iobuf, v);
  467. break;
  468. default:
  469. TOOLKIT_ASSERT(0);
  470. }
  471. }
  472. TOOLKIT_API int iobuffer_get_read_state(iobuffer_t *iobuf)
  473. {
  474. return iobuf->sp_rpos;
  475. }
  476. TOOLKIT_API void iobuffer_restore_read_state(iobuffer_t *iobuf, int state)
  477. {
  478. iobuf->sp_rpos = state;
  479. }
  480. TOOLKIT_API int iobuffer_get_write_state(iobuffer_t *iobuf)
  481. {
  482. return iobuf->sp_wpos;
  483. }
  484. TOOLKIT_API void iobuffer_restore_write_state(iobuffer_t *iobuf, int state)
  485. {
  486. iobuf->sp_wpos = state;
  487. }
  488. TOOLKIT_API void iobuffer_set_user_data(iobuffer_t *iobuf, void *user_data)
  489. {
  490. iobuf->sp_user_data = user_data;
  491. }
  492. TOOLKIT_API void *iobuffer_get_user_data(iobuffer_t *iobuf)
  493. {
  494. return iobuf->sp_user_data;
  495. }
  496. TOOLKIT_API int iobuffer_get_linkId(iobuffer_t* iobuf)
  497. {
  498. return iobuf->sp_linkId;
  499. }
  500. TOOLKIT_API void iobuffer_set_linkId(iobuffer_t* iobuf, int linkId)
  501. {
  502. iobuf->sp_linkId = linkId;
  503. }
  504. TOOLKIT_API void iobuffer_get_linkInfo(iobuffer_t* iobuf, char* t_bussId, char* t_tranceId, char* t_spanId, char* t_parentSpanId)
  505. {
  506. memcpy(t_bussId, iobuf->bussinessId, sizeof(iobuf->bussinessId));
  507. memcpy(t_tranceId, iobuf->traceId, sizeof(iobuf->traceId));
  508. memcpy(t_spanId, iobuf->spanId, sizeof(iobuf->spanId));
  509. memcpy(t_parentSpanId, iobuf->parentSpanId, sizeof(iobuf->parentSpanId));
  510. }
  511. TOOLKIT_API void iobuffer_set_linkInfo(iobuffer_t* iobuf, const char* t_bussId, const char* t_tranceId, const char* t_spanId, const char* t_parentSpanId)
  512. {
  513. memcpy(iobuf->bussinessId, t_bussId, strlen(t_bussId) + 1);
  514. memcpy(iobuf->traceId, t_tranceId, sizeof(iobuf->traceId));
  515. memcpy(iobuf->spanId, t_spanId, sizeof(iobuf->spanId));
  516. memcpy(iobuf->parentSpanId, t_parentSpanId, sizeof(iobuf->parentSpanId));
  517. }
  518. void iobuffer_copy_linkInfo(iobuffer_t* dst, iobuffer_t* src)
  519. {
  520. if (src && dst)
  521. {
  522. char bussinessId[LINKINFO_BUSSID_LEN];
  523. char traceId[LINKINFO_TRACEID_LEN];
  524. char spanId[LINKINFO_SPANID_LEN];
  525. char parentSpanId[LINKINFO_PARENTSPANID_LEN];
  526. iobuffer_get_linkInfo(src, bussinessId, traceId, spanId, parentSpanId);
  527. iobuffer_set_linkInfo(dst, bussinessId, traceId, spanId, parentSpanId);
  528. }
  529. }
  530. IMPLEMENT_REF_COUNT_MT(iobuffer, iobuffer_t, sp_ref_cnt, destroy)
  531. TOOLKIT_API void iobuffer_format_readv(iobuffer_t *iobuf, const char *fmt, va_list arg)
  532. {
  533. if (fmt) {
  534. const char *p = fmt;
  535. while (*p) {
  536. switch (*p) {
  537. case '8':
  538. iobuffer_read(iobuf, IOBUF_T_I8, va_arg(arg, void*), NULL);
  539. break;
  540. case '7': // 7bit int code
  541. iobuffer_read(iobuf, IOBUF_T_7BIT, va_arg(arg, void*), NULL);
  542. break;
  543. case '4':
  544. iobuffer_read(iobuf, IOBUF_T_I4, va_arg(arg, void*), 0);
  545. break;
  546. case '2':
  547. iobuffer_read(iobuf, IOBUF_T_I2, va_arg(arg, void*), 0);
  548. break;
  549. case '1':
  550. iobuffer_read(iobuf, IOBUF_T_I1, va_arg(arg, void*), 0);
  551. break;
  552. case 's':case 'S':
  553. {
  554. char **pstr = va_arg(arg, char**);
  555. int slen;
  556. iobuffer_read(iobuf, IOBUF_T_STR, NULL, &slen);
  557. *pstr = (char*)malloc(slen+1);
  558. iobuffer_read(iobuf, IOBUF_T_STR, *pstr, 0);
  559. }
  560. break;
  561. case 'w': case 'W':
  562. {
  563. #if defined(_MSC_VER)
  564. wchar_t** pstr = va_arg(arg, wchar_t**);
  565. int slen;
  566. iobuffer_read(iobuf, IOBUF_T_WSTR, NULL, &slen);
  567. *pstr = (wchar_t*)malloc(slen + 2); // null terminated is two bytes
  568. #else
  569. WCHAR** pstr = va_arg(arg, WCHAR**);
  570. int slen;
  571. iobuffer_read(iobuf, IOBUF_T_WSTR, NULL, &slen);
  572. *pstr = (WCHAR*)malloc(slen + sizeof(WCHAR));
  573. #endif //_MSC_VER
  574. iobuffer_read(iobuf, IOBUF_T_WSTR, *pstr, 0);
  575. }
  576. break;
  577. case 'm': case 'M':
  578. {
  579. wchar_t** pstr = va_arg(arg, wchar_t**);
  580. int slen = 0;
  581. iobuffer_read(iobuf, IOBUF_T_WCSTR, NULL, &slen);
  582. *pstr = (wchar_t*)malloc(slen + sizeof(wchar_t));
  583. iobuffer_read(iobuf, IOBUF_T_WCSTR, *pstr, 0);
  584. }
  585. break;
  586. case 'b':case 'B':
  587. {
  588. void *buf = va_arg(arg, void*);
  589. int size = va_arg(arg, int);
  590. iobuffer_read(iobuf, IOBUF_T_BUF, buf, &size);
  591. }
  592. break;
  593. default:
  594. TOOLKIT_ASSERT(0);
  595. break;
  596. }
  597. p++;
  598. }
  599. }
  600. }
  601. TOOLKIT_API void iobuffer_format_writev(iobuffer_t *iobuf, const char *fmt, va_list arg)
  602. {
  603. if (fmt) {
  604. const char *p = fmt;
  605. while (*p) {
  606. switch (*p) {
  607. case '8':
  608. iobuffer_write(iobuf, IOBUF_T_I8, va_arg(arg, void*), 0);
  609. break;
  610. case '7':
  611. iobuffer_write(iobuf, IOBUF_T_7BIT, va_arg(arg, void*), 0);
  612. break;
  613. case '4':
  614. iobuffer_write(iobuf, IOBUF_T_I4, va_arg(arg, void*), 0);
  615. break;
  616. case '2':
  617. iobuffer_write(iobuf, IOBUF_T_I2, va_arg(arg, void*), 0);
  618. break;
  619. case '1':
  620. iobuffer_write(iobuf, IOBUF_T_I1, va_arg(arg, void*), 0);
  621. break;
  622. case 's':case 'S':
  623. iobuffer_write(iobuf, IOBUF_T_STR, va_arg(arg, void*), -1);
  624. break;
  625. case 'w':case 'W':
  626. iobuffer_write(iobuf, IOBUF_T_WSTR, va_arg(arg, void*), -1);
  627. break;
  628. case 'm':case 'M':
  629. iobuffer_write(iobuf, IOBUF_T_WCSTR, va_arg(arg, void*), -1);
  630. break;
  631. case 'b':case 'B':
  632. {
  633. void *buf = va_arg(arg, void*);
  634. int size = va_arg(arg, int);
  635. iobuffer_write(iobuf, IOBUF_T_BUF, buf, size);
  636. }
  637. break;
  638. default:
  639. TOOLKIT_ASSERT(0);
  640. break;
  641. }
  642. p++;
  643. }
  644. }
  645. }
  646. TOOLKIT_API void iobuffer_format_read(iobuffer_t *iobuf, const char *fmt, ...)
  647. {
  648. va_list arg;
  649. va_start(arg, fmt);
  650. iobuffer_format_readv(iobuf, fmt, arg);
  651. va_end(arg);
  652. }
  653. TOOLKIT_API void iobuffer_format_write(iobuffer_t *iobuf, const char *fmt, ...)
  654. {
  655. va_list arg;
  656. va_start(arg, fmt);
  657. iobuffer_format_writev(iobuf, fmt, arg);
  658. va_end(arg);
  659. }
  660. TOOLKIT_API void iobuffer_format_writev_head(iobuffer_t *iobuf, const char *fmt, va_list arg)
  661. {
  662. if (fmt) {
  663. const char *p = fmt;
  664. while (*p) {
  665. switch (*p) {
  666. case '8':
  667. iobuffer_write_head(iobuf, IOBUF_T_I8, va_arg(arg, void*), 0);
  668. break;
  669. case '7':
  670. iobuffer_write_head(iobuf, IOBUF_T_7BIT, va_arg(arg, void*), 0);
  671. break;
  672. case '4':
  673. iobuffer_write_head(iobuf, IOBUF_T_I4, va_arg(arg, void*), 0);
  674. break;
  675. case '2':
  676. iobuffer_write_head(iobuf, IOBUF_T_I2, va_arg(arg, void*), 0);
  677. break;
  678. case '1':
  679. iobuffer_write_head(iobuf, IOBUF_T_I1, va_arg(arg, void*), 0);
  680. break;
  681. case 's':case 'S':
  682. iobuffer_write_head(iobuf, IOBUF_T_STR, va_arg(arg, void*), -1);
  683. break;
  684. case 'w':case 'W':
  685. iobuffer_write_head(iobuf, IOBUF_T_WSTR, va_arg(arg, void*), -1);
  686. break;
  687. case 'm':case 'M':
  688. iobuffer_write_head(iobuf, IOBUF_T_WCSTR, va_arg(arg, void*), -1);
  689. break;
  690. case 'b':case 'B':
  691. {
  692. void *buf = va_arg(arg, void*);
  693. int size = va_arg(arg, int);
  694. iobuffer_write_head(iobuf, IOBUF_T_BUF, buf, size);
  695. }
  696. break;
  697. default:
  698. TOOLKIT_ASSERT(0);
  699. break;
  700. }
  701. p++;
  702. }
  703. }
  704. }
  705. TOOLKIT_API void iobuffer_format_write_head(iobuffer_t *iobuf, const char *fmt, ...)
  706. {
  707. va_list arg;
  708. va_start(arg, fmt);
  709. iobuffer_format_writev_head(iobuf, fmt, arg);
  710. va_end(arg);
  711. }
  712. struct iobuffer_queue_t
  713. {
  714. struct list_head iobuf_list;
  715. int cnt;
  716. };
  717. TOOLKIT_API iobuffer_queue_t *iobuffer_queue_create()
  718. {
  719. iobuffer_queue_t *queue = MALLOC_T(iobuffer_queue_t);
  720. queue->cnt = 0;
  721. INIT_LIST_HEAD(&queue->iobuf_list);
  722. return queue;
  723. }
  724. TOOLKIT_API void iobuffer_queue_destroy(iobuffer_queue_t *queue)
  725. {
  726. while (!list_empty(&queue->iobuf_list)) {
  727. iobuffer_t *iobuf = iobuffer_queue_deque(queue);
  728. iobuffer_destroy(iobuf);
  729. }
  730. free(queue);
  731. }
  732. TOOLKIT_API void iobuffer_queue_enqueue(iobuffer_queue_t *queue, iobuffer_t *iobuf)
  733. {
  734. list_add_tail(&iobuf->sp_entry, &queue->iobuf_list);
  735. queue->cnt++;
  736. }
  737. TOOLKIT_API iobuffer_t *iobuffer_queue_deque(iobuffer_queue_t *queue)
  738. {
  739. iobuffer_t *iob = list_first_entry(&queue->iobuf_list, iobuffer_t, sp_entry);
  740. list_del(&iob->sp_entry);
  741. queue->cnt--;
  742. return iob;
  743. }
  744. TOOLKIT_API int iobuffer_queue_count(iobuffer_queue_t *queue)
  745. {
  746. return queue->cnt;
  747. }
  748. TOOLKIT_API iobuffer_t *iobuffer_queue_head(iobuffer_queue_t *queue)
  749. {
  750. return list_first_entry(&queue->iobuf_list, iobuffer_t, sp_entry);
  751. }
  752. TOOLKIT_API iobuffer_t *iobuffer_queue_tail(iobuffer_queue_t *queue)
  753. {
  754. return list_last_entry(&queue->iobuf_list, iobuffer_t, sp_entry);
  755. }
  756. #ifdef DEBUD_MEM_TRACE
  757. TOOLKIT_API iobuffer_t* iobuffer_create_trace(int head_capacity, int capacity, const char* file, const char* function, int line)
  758. {
  759. WLog_DBG(TAG, "iobuffer_create_trace: <%s>[%d]{%s}", function, line, file);
  760. return iobuffer_create_(head_capacity, capacity);
  761. }
  762. TOOLKIT_API iobuffer_t* iobuffer_clone_trace(iobuffer_t* iobuf, const char* file, const char* function, int line)
  763. {
  764. WLog_DBG(TAG, "%s: <%s>[%d]{%s}", __FUNCTION__, function, line, file);
  765. return iobuffer_clone_(iobuf);
  766. }
  767. #endif // DEBUD_MEM_TRACE