iobuffer.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. #include "precompile.h"
  2. #include "iobuffer.h"
  3. #include "refcnt.h"
  4. #include "list.h"
  5. #include <assert.h>
  6. #include <stdarg.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. void *sp_user_data;
  20. DECLARE_REF_COUNT_MEMBER(sp_ref_cnt);
  21. };
  22. #define DEFAULT_CAPACITY 256
  23. #define DEFAULT_HEADER_CAPACITY 128
  24. static void expand(iobuffer_t *iobuf, int head_capacity, int newcapacity)
  25. {
  26. if (head_capacity == -1) {
  27. int t = iobuf->sp_capacity;
  28. while (newcapacity > t)
  29. t = t*2;
  30. if (t > iobuf->sp_capacity) {
  31. iobuf->sp_data = (char*)realloc(iobuf->sp_data, t);
  32. iobuf->sp_capacity = t;
  33. }
  34. } else if (newcapacity == -1) {
  35. int t = iobuf->sp_hdr_capacity;
  36. while (head_capacity > t)
  37. t = t*2;
  38. if (t > iobuf->sp_rpos) {
  39. char *new_data;
  40. int new_rpos;
  41. int new_wpos;
  42. newcapacity = iobuf->sp_capacity + (t - iobuf->sp_hdr_capacity);
  43. new_data = malloc(newcapacity);
  44. new_rpos = t;
  45. new_wpos = new_rpos + (iobuf->sp_wpos - iobuf->sp_rpos);
  46. memcpy(new_data+new_rpos, iobuf->sp_data+iobuf->sp_rpos, iobuf->sp_wpos - iobuf->sp_rpos);
  47. free(iobuf->sp_data);
  48. iobuf->sp_data = new_data;
  49. iobuf->sp_rpos = new_rpos;
  50. iobuf->sp_wpos = new_wpos;
  51. iobuf->sp_hdr_capacity = t;
  52. iobuf->sp_capacity = newcapacity;
  53. }
  54. } else {
  55. int t = iobuf->sp_capacity;
  56. char *new_data = (char*)malloc(t);
  57. int new_rpos = head_capacity;
  58. int new_wpos = new_rpos + (iobuf->sp_wpos - iobuf->sp_rpos);
  59. while (newcapacity > t)
  60. t = t*2;
  61. memcpy(new_data+new_rpos, iobuf->sp_data+iobuf->sp_rpos, iobuf->sp_wpos - iobuf->sp_rpos);
  62. free(iobuf->sp_data);
  63. iobuf->sp_data = new_data;
  64. iobuf->sp_rpos = new_rpos;
  65. iobuf->sp_wpos = new_wpos;
  66. iobuf->sp_capacity = t;
  67. }
  68. }
  69. static __inline int empty_size(iobuffer_t *iobuf)
  70. {
  71. return iobuf->sp_capacity - iobuf->sp_wpos;
  72. }
  73. static __inline int content_size(iobuffer_t *iobuf)
  74. {
  75. return iobuf->sp_wpos - iobuf->sp_rpos;
  76. }
  77. static void destroy(iobuffer_t *iobuf)
  78. {
  79. WLog_DBG(TAG, "iobuffer destroy 0x%0X", iobuf);
  80. iobuffer_set_capacity(iobuf, 0);
  81. //memset(iobuf, 0, sizeof(*iobuf));
  82. //if (iobuf->sp_capacity > 0) {
  83. // assert(iobuf->sp_data);
  84. // free(iobuf->sp_data);
  85. //}
  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. assert(content_size(iobuf) >= n);
  127. assert(buf);
  128. memcpy(buf, iobuf->sp_data+iobuf->sp_rpos, n);
  129. iobuf->sp_rpos += n;
  130. }
  131. static void iobuffer_read_7bit_int(iobuffer_t *iobuf, int *v)
  132. {
  133. int count = 0;
  134. int shift = 0;
  135. unsigned char b;
  136. do {
  137. if (shift == 5*7) // corrupted stream
  138. assert(0);
  139. b = iobuf->sp_data[iobuf->sp_rpos ++];
  140. count |= (b & 0x7F) << shift;
  141. shift += 7;
  142. } while (b & 0x80); // most left bit is flag
  143. *v = count;
  144. }
  145. #ifdef DEBUD_MEM_TRACE
  146. static iobuffer_t* iobuffer_create_(int head_capacity, int capacity)
  147. #else
  148. TOOLKIT_API iobuffer_t* iobuffer_create(int head_capacity, int capacity)
  149. #endif
  150. {
  151. iobuffer_t *iobuf;
  152. if (head_capacity <= 0)
  153. head_capacity = DEFAULT_HEADER_CAPACITY;
  154. if (capacity <= 0) {
  155. capacity = head_capacity + DEFAULT_CAPACITY;
  156. } else {
  157. capacity += head_capacity;
  158. }
  159. iobuf = MALLOC_T(iobuffer_t);
  160. memset(iobuf, 0, sizeof(iobuffer_t));
  161. iobuf->sp_hdr_capacity = head_capacity;
  162. iobuf->sp_capacity = capacity;
  163. iobuf->sp_data = malloc(capacity);
  164. iobuf->sp_user_data = NULL;
  165. iobuf->sp_entry.next = iobuf->sp_entry.prev = NULL;
  166. iobuffer_reset(iobuf);
  167. REF_COUNT_INIT(&iobuf->sp_ref_cnt);
  168. WLog_DBG(TAG, "iobuffer create 0x%0X", iobuf);
  169. return iobuf;
  170. }
  171. TOOLKIT_API void iobuffer_destroy(iobuffer_t *iobuf)
  172. {
  173. iobuffer_dec_ref(iobuf);
  174. }
  175. #ifdef DEBUD_MEM_TRACE
  176. static iobuffer_t* iobuffer_clone_(iobuffer_t* iobuf)
  177. #else
  178. TOOLKIT_API iobuffer_t* iobuffer_clone(iobuffer_t* iobuf)
  179. #endif
  180. {
  181. iobuffer_t *newiobuf;
  182. newiobuf = iobuffer_create(iobuf->sp_hdr_capacity, iobuf->sp_capacity);
  183. memcpy(newiobuf->sp_data+iobuf->sp_rpos, iobuf->sp_data+iobuf->sp_rpos, iobuf->sp_wpos-iobuf->sp_rpos);
  184. newiobuf->sp_rpos = iobuf->sp_rpos;
  185. newiobuf->sp_wpos = iobuf->sp_wpos;
  186. newiobuf->sp_user_data = iobuf->sp_user_data;
  187. return newiobuf;
  188. }
  189. TOOLKIT_API void iobuffer_reset(iobuffer_t *iobuf)
  190. {
  191. iobuf->sp_rpos = iobuf->sp_hdr_capacity;
  192. iobuf->sp_wpos = iobuf->sp_hdr_capacity;
  193. }
  194. TOOLKIT_API int iobuffer_get_capacity(iobuffer_t *iobuf)
  195. {
  196. return iobuf->sp_capacity;
  197. }
  198. TOOLKIT_API void iobuffer_set_capacity(iobuffer_t *iobuf, int capacity)
  199. {
  200. iobuf->sp_data = (char*)realloc(iobuf->sp_data, capacity);
  201. if (iobuf->sp_wpos > capacity)
  202. iobuf->sp_wpos = capacity;
  203. if (iobuf->sp_rpos > capacity)
  204. iobuf->sp_rpos = capacity;
  205. iobuf->sp_capacity = capacity;
  206. }
  207. TOOLKIT_API char *iobuffer_data(iobuffer_t *iobuf, int offset)
  208. {
  209. if (offset != -1) {
  210. return iobuf->sp_data + iobuf->sp_rpos + offset;
  211. } else {
  212. return iobuf->sp_data + iobuf->sp_wpos;
  213. }
  214. }
  215. TOOLKIT_API int iobuffer_get_length(iobuffer_t *iobuf)
  216. {
  217. return iobuf->sp_wpos - iobuf->sp_rpos;
  218. }
  219. TOOLKIT_API void iobuffer_set_length(iobuffer_t *iobuf, int length)
  220. {
  221. iobuf->sp_wpos = iobuf->sp_rpos + length;
  222. if (iobuf->sp_wpos > iobuf->sp_capacity)
  223. iobuf->sp_wpos = iobuf->sp_capacity;
  224. }
  225. TOOLKIT_API void iobuffer_push_count(iobuffer_t *iobuf, int n)
  226. {
  227. assert(empty_size(iobuf) >= n);
  228. iobuf->sp_wpos += n;
  229. }
  230. TOOLKIT_API void iobuffer_pop_count(iobuffer_t *iobuf, int n)
  231. {
  232. assert(content_size(iobuf) >= n);
  233. iobuf->sp_rpos += n;
  234. }
  235. TOOLKIT_API void iobuffer_write(iobuffer_t *iobuf, int t, const void *v, int n)
  236. {
  237. int len = 0;
  238. switch (t) {
  239. case IOBUF_T_I8:
  240. len += 4;
  241. case IOBUF_T_I4:
  242. len += 2;
  243. case IOBUF_T_I2:
  244. len += 1;
  245. case IOBUF_T_I1:
  246. len += 1;
  247. iobuffer_write_buf(iobuf, v, len);
  248. break;
  249. case IOBUF_T_STR:
  250. if (!v) {
  251. n = 0;
  252. } else {
  253. if (n == -1)
  254. n = strlen(v);
  255. }
  256. iobuffer_write_7bit_int(iobuf, (unsigned int)n);
  257. if (n > 0)
  258. iobuffer_write_buf(iobuf, v, n);
  259. break;
  260. case IOBUF_T_WSTR:
  261. if (!v) {
  262. n = 0;
  263. } else {
  264. if (n == -1) {
  265. // be compatible with winpr [4/2/2020 16:02 Gifur]
  266. n = _wcslen(v) << 1;
  267. //n = wcslen(v)<<1;
  268. }
  269. }
  270. iobuffer_write_7bit_int(iobuf, n);
  271. if (n > 0)
  272. iobuffer_write_buf(iobuf, v, n);
  273. break;
  274. case IOBUF_T_BUF:
  275. if (n > 0)
  276. iobuffer_write_buf(iobuf, v, n);
  277. break;
  278. case IOBUF_T_7BIT:
  279. iobuffer_write_7bit_int(iobuf, *(unsigned int*)v);
  280. break;
  281. }
  282. }
  283. TOOLKIT_API void iobuffer_write_head(iobuffer_t *iobuf, int t, const void *v, int n)
  284. {
  285. int len = 0;
  286. switch (t) {
  287. case IOBUF_T_I8:
  288. len += 4;
  289. case IOBUF_T_I4:
  290. len += 2;
  291. case IOBUF_T_I2:
  292. len += 1;
  293. case IOBUF_T_I1:
  294. len += 1;
  295. iobuffer_write_head_buf(iobuf, v, len);
  296. break;
  297. case IOBUF_T_STR:
  298. if (!v) {
  299. n = 0;
  300. } else {
  301. if (n == -1) {
  302. n = strlen(v);
  303. }
  304. }
  305. if (n > 0)
  306. iobuffer_write_head_buf(iobuf, v, n);
  307. iobuffer_write_head_7bit_int(iobuf, n);
  308. break;
  309. case IOBUF_T_WSTR:
  310. if (!v) {
  311. n = 0;
  312. } else {
  313. if (n == -1) {
  314. n = _wcslen(v)<<1;
  315. }
  316. }
  317. if (n > 0)
  318. iobuffer_write_head_buf(iobuf, v, n);
  319. iobuffer_write_head_7bit_int(iobuf, n);
  320. break;
  321. case IOBUF_T_BUF:
  322. if (n > 0)
  323. iobuffer_write_head_buf(iobuf, v, n);
  324. break;
  325. case IOBUF_T_7BIT:
  326. iobuffer_write_head_7bit_int(iobuf, *(unsigned int*)v);
  327. break;
  328. default:
  329. assert(0);
  330. }
  331. }
  332. TOOLKIT_API void iobuffer_read(iobuffer_t *iobuf, int t, void *v, int *n)
  333. {
  334. int len = 0;
  335. switch (t) {
  336. case IOBUF_T_I8:
  337. len += 4;
  338. case IOBUF_T_I4:
  339. len += 2;
  340. case IOBUF_T_I2:
  341. len += 1;
  342. case IOBUF_T_I1:
  343. len += 1;
  344. iobuffer_read_buf(iobuf, v, len);
  345. break;
  346. case IOBUF_T_STR:
  347. if (v) {
  348. int old_rpos = iobuf->sp_rpos;
  349. iobuffer_read_7bit_int(iobuf, &len);
  350. if (!n || len < *n) {
  351. iobuffer_read_buf(iobuf, v, len);
  352. *((char*)v + len) = 0;
  353. if (n)
  354. *n = len;
  355. } else {
  356. iobuf->sp_rpos = old_rpos;
  357. *n = len;
  358. }
  359. } else {
  360. if (n) {
  361. int old_rpos = iobuf->sp_rpos;
  362. iobuffer_read_7bit_int(iobuf, &len);
  363. iobuf->sp_rpos = old_rpos;
  364. *n = len;
  365. } else {
  366. assert(0);
  367. }
  368. }
  369. break;
  370. case IOBUF_T_WSTR:
  371. if (v) {
  372. int old_rpos = iobuf->sp_rpos;
  373. iobuffer_read_7bit_int(iobuf, &len);
  374. if (!n || len < *n) {
  375. iobuffer_read_buf(iobuf, v, len); /* WCHAR */
  376. *((char*)v + len) = 0; // wchar termination char is 2 byte
  377. *((char*)v + len+1) = 0;
  378. if (n)
  379. *n = len;
  380. } else {
  381. iobuf->sp_rpos = old_rpos;
  382. *n = len;
  383. }
  384. } else {
  385. if (n) {
  386. int old_rpos = iobuf->sp_rpos;
  387. iobuffer_read_7bit_int(iobuf, &len);
  388. iobuf->sp_rpos = old_rpos;
  389. *n = len;
  390. } else {
  391. assert(0);
  392. }
  393. }
  394. break;
  395. case IOBUF_T_BUF:
  396. if (*n > 0)
  397. iobuffer_read_buf(iobuf, v, *n);
  398. break;
  399. case IOBUF_T_7BIT:
  400. iobuffer_read_7bit_int(iobuf, v);
  401. break;
  402. default:
  403. assert(0);
  404. }
  405. }
  406. TOOLKIT_API int iobuffer_get_read_state(iobuffer_t *iobuf)
  407. {
  408. return iobuf->sp_rpos;
  409. }
  410. TOOLKIT_API void iobuffer_restore_read_state(iobuffer_t *iobuf, int state)
  411. {
  412. iobuf->sp_rpos = state;
  413. }
  414. TOOLKIT_API int iobuffer_get_write_state(iobuffer_t *iobuf)
  415. {
  416. return iobuf->sp_wpos;
  417. }
  418. TOOLKIT_API void iobuffer_restore_write_state(iobuffer_t *iobuf, int state)
  419. {
  420. iobuf->sp_wpos = state;
  421. }
  422. TOOLKIT_API void iobuffer_set_user_data(iobuffer_t *iobuf, void *user_data)
  423. {
  424. iobuf->sp_user_data = user_data;
  425. }
  426. TOOLKIT_API void *iobuffer_get_user_data(iobuffer_t *iobuf)
  427. {
  428. return iobuf->sp_user_data;
  429. }
  430. IMPLEMENT_REF_COUNT_MT(iobuffer, iobuffer_t, sp_ref_cnt, destroy)
  431. TOOLKIT_API void iobuffer_format_readv(iobuffer_t *iobuf, const char *fmt, va_list arg)
  432. {
  433. if (fmt) {
  434. const char *p = fmt;
  435. while (*p) {
  436. switch (*p) {
  437. case '8':
  438. iobuffer_read(iobuf, IOBUF_T_I8, va_arg(arg, void*), NULL);
  439. break;
  440. case '7': // 7bit int code
  441. iobuffer_read(iobuf, IOBUF_T_7BIT, va_arg(arg, void*), NULL);
  442. break;
  443. case '4':
  444. iobuffer_read(iobuf, IOBUF_T_I4, va_arg(arg, void*), 0);
  445. break;
  446. case '2':
  447. iobuffer_read(iobuf, IOBUF_T_I2, va_arg(arg, void*), 0);
  448. break;
  449. case '1':
  450. iobuffer_read(iobuf, IOBUF_T_I1, va_arg(arg, void*), 0);
  451. break;
  452. case 's':case 'S':
  453. {
  454. char **pstr = va_arg(arg, char**);
  455. int slen;
  456. iobuffer_read(iobuf, IOBUF_T_STR, NULL, &slen);
  457. *pstr = (char*)malloc(slen+1);
  458. iobuffer_read(iobuf, IOBUF_T_STR, *pstr, 0);
  459. }
  460. break;
  461. case 'w': case 'W':
  462. {
  463. WCHAR **pstr = va_arg(arg, WCHAR**);
  464. int slen;
  465. iobuffer_read(iobuf, IOBUF_T_WSTR, NULL, &slen);
  466. *pstr = (WCHAR*)malloc(slen+2); // null terminated is two bytes
  467. iobuffer_read(iobuf, IOBUF_T_WSTR, *pstr, 0);
  468. }
  469. break;
  470. case 'b':case 'B':
  471. {
  472. void *buf = va_arg(arg, void*);
  473. int size = va_arg(arg, int);
  474. iobuffer_read(iobuf, IOBUF_T_BUF, buf, &size);
  475. }
  476. break;
  477. default:
  478. assert(0);
  479. break;
  480. }
  481. p++;
  482. }
  483. }
  484. }
  485. TOOLKIT_API void iobuffer_format_writev(iobuffer_t *iobuf, const char *fmt, va_list arg)
  486. {
  487. if (fmt) {
  488. const char *p = fmt;
  489. while (*p) {
  490. switch (*p) {
  491. case '8':
  492. iobuffer_write(iobuf, IOBUF_T_I8, va_arg(arg, void*), 0);
  493. break;
  494. case '7':
  495. iobuffer_write(iobuf, IOBUF_T_7BIT, va_arg(arg, void*), 0);
  496. break;
  497. case '4':
  498. iobuffer_write(iobuf, IOBUF_T_I4, va_arg(arg, void*), 0);
  499. break;
  500. case '2':
  501. iobuffer_write(iobuf, IOBUF_T_I2, va_arg(arg, void*), 0);
  502. break;
  503. case '1':
  504. iobuffer_write(iobuf, IOBUF_T_I1, va_arg(arg, void*), 0);
  505. break;
  506. case 's':case 'S':
  507. iobuffer_write(iobuf, IOBUF_T_STR, va_arg(arg, void*), -1);
  508. break;
  509. case 'w':case 'W':
  510. iobuffer_write(iobuf, IOBUF_T_WSTR, va_arg(arg, void*), -1);
  511. break;
  512. case 'b':case 'B':
  513. {
  514. void *buf = va_arg(arg, void*);
  515. int size = va_arg(arg, int);
  516. iobuffer_write(iobuf, IOBUF_T_BUF, buf, size);
  517. }
  518. break;
  519. default:
  520. assert(0);
  521. break;
  522. }
  523. p++;
  524. }
  525. }
  526. }
  527. TOOLKIT_API void iobuffer_format_read(iobuffer_t *iobuf, const char *fmt, ...)
  528. {
  529. va_list arg;
  530. va_start(arg, fmt);
  531. iobuffer_format_readv(iobuf, fmt, arg);
  532. va_end(arg);
  533. }
  534. TOOLKIT_API void iobuffer_format_write(iobuffer_t *iobuf, const char *fmt, ...)
  535. {
  536. va_list arg;
  537. va_start(arg, fmt);
  538. iobuffer_format_writev(iobuf, fmt, arg);
  539. va_end(arg);
  540. }
  541. TOOLKIT_API void iobuffer_format_writev_head(iobuffer_t *iobuf, const char *fmt, va_list arg)
  542. {
  543. if (fmt) {
  544. const char *p = fmt;
  545. while (*p) {
  546. switch (*p) {
  547. case '8':
  548. iobuffer_write_head(iobuf, IOBUF_T_I8, va_arg(arg, void*), 0);
  549. break;
  550. case '7':
  551. iobuffer_write_head(iobuf, IOBUF_T_7BIT, va_arg(arg, void*), 0);
  552. break;
  553. case '4':
  554. iobuffer_write_head(iobuf, IOBUF_T_I4, va_arg(arg, void*), 0);
  555. break;
  556. case '2':
  557. iobuffer_write_head(iobuf, IOBUF_T_I2, va_arg(arg, void*), 0);
  558. break;
  559. case '1':
  560. iobuffer_write_head(iobuf, IOBUF_T_I1, va_arg(arg, void*), 0);
  561. break;
  562. case 's':case 'S':
  563. iobuffer_write_head(iobuf, IOBUF_T_STR, va_arg(arg, void*), -1);
  564. break;
  565. case 'w':case 'W':
  566. iobuffer_write_head(iobuf, IOBUF_T_WSTR, va_arg(arg, void*), -1);
  567. break;
  568. case 'b':case 'B':
  569. {
  570. void *buf = va_arg(arg, void*);
  571. int size = va_arg(arg, int);
  572. iobuffer_write_head(iobuf, IOBUF_T_BUF, buf, size);
  573. }
  574. break;
  575. default:
  576. assert(0);
  577. break;
  578. }
  579. p++;
  580. }
  581. }
  582. }
  583. TOOLKIT_API void iobuffer_format_write_head(iobuffer_t *iobuf, const char *fmt, ...)
  584. {
  585. va_list arg;
  586. va_start(arg, fmt);
  587. iobuffer_format_writev_head(iobuf, fmt, arg);
  588. va_end(arg);
  589. }
  590. struct iobuffer_queue_t
  591. {
  592. struct list_head iobuf_list;
  593. int cnt;
  594. };
  595. TOOLKIT_API iobuffer_queue_t *iobuffer_queue_create()
  596. {
  597. iobuffer_queue_t *queue = MALLOC_T(iobuffer_queue_t);
  598. queue->cnt = 0;
  599. INIT_LIST_HEAD(&queue->iobuf_list);
  600. return queue;
  601. }
  602. TOOLKIT_API void iobuffer_queue_destroy(iobuffer_queue_t *queue)
  603. {
  604. while (!list_empty(&queue->iobuf_list)) {
  605. iobuffer_t *iobuf = iobuffer_queue_deque(queue);
  606. iobuffer_destroy(iobuf);
  607. }
  608. free(queue);
  609. }
  610. TOOLKIT_API void iobuffer_queue_enqueue(iobuffer_queue_t *queue, iobuffer_t *iobuf)
  611. {
  612. list_add_tail(&iobuf->sp_entry, &queue->iobuf_list);
  613. queue->cnt++;
  614. }
  615. TOOLKIT_API iobuffer_t *iobuffer_queue_deque(iobuffer_queue_t *queue)
  616. {
  617. iobuffer_t *iob = list_first_entry(&queue->iobuf_list, iobuffer_t, sp_entry);
  618. list_del(&iob->sp_entry);
  619. queue->cnt--;
  620. return iob;
  621. }
  622. TOOLKIT_API int iobuffer_queue_count(iobuffer_queue_t *queue)
  623. {
  624. return queue->cnt;
  625. }
  626. TOOLKIT_API iobuffer_t *iobuffer_queue_head(iobuffer_queue_t *queue)
  627. {
  628. return list_first_entry(&queue->iobuf_list, iobuffer_t, sp_entry);
  629. }
  630. TOOLKIT_API iobuffer_t *iobuffer_queue_tail(iobuffer_queue_t *queue)
  631. {
  632. return list_last_entry(&queue->iobuf_list, iobuffer_t, sp_entry);
  633. }
  634. #ifdef DEBUD_MEM_TRACE
  635. TOOLKIT_API iobuffer_t* iobuffer_create_trace(int head_capacity, int capacity, const char* file, const char* function, int line)
  636. {
  637. WLog_DBG(TAG, "iobuffer_create_trace: <%s>[%d]{%s}", function, line, file);
  638. return iobuffer_create_(head_capacity, capacity);
  639. }
  640. TOOLKIT_API iobuffer_t* iobuffer_clone_trace(iobuffer_t* iobuf, const char* file, const char* function, int line)
  641. {
  642. WLog_DBG(TAG, "%s: <%s>[%d]{%s}", __FUNCTION__, function, line, file);
  643. return iobuffer_clone_(iobuf);
  644. }
  645. #endif // DEBUD_MEM_TRACE