buf.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. /*
  2. * This file is part of the zlog Library.
  3. *
  4. * Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
  5. *
  6. * Licensed under the LGPL v2.1, see the file COPYING in base directory.
  7. */
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <pthread.h>
  11. #include <errno.h>
  12. #include <stdint.h>
  13. #include "zc_defs.h"
  14. #include "buf.h"
  15. /*******************************************************************************/
  16. /* Author's Note
  17. * This buf.c is base on C99, that is, if buffer size is not enough,
  18. * the return value of vsnprintf(3) is a number tell how many character should
  19. * be output. vsnprintf in glibc 2.1 conforms to C99 , but glibc 2.0 doesn't.
  20. * see manpage of vsnprintf(3) on you platform for more detail.
  21. * So, what should you do if you want to using zlog on the platform that doesn't
  22. * conform C99? My Answer is, crack zlog with a portable C99-vsnprintf, like this
  23. * http://sourceforge.net/projects/ctrio/
  24. * http://www.jhweiss.de/software/snprintf.html
  25. * If you can see this note, you can fix it yourself? Aren't you? ^_^
  26. * Oh, I put the snprintf in C99 standard here,
  27. * vsnprintf is the same on return value.
  28. 7.19.6.5 The snprintf function
  29. Synopsis
  30. [#1]
  31. #include <stdio.h>
  32. int snprintf(char * restrict s, size_t n,
  33. const char * restrict format, ...);
  34. Description
  35. [#2] The snprintf function is equivalent to fprintf, except
  36. that the output is written into an array (specified by
  37. argument s) rather than to a stream. If n is zero, nothing
  38. is written, and s may be a null pointer. Otherwise, output
  39. characters beyond the n-1st are discarded rather than being
  40. written to the array, and a null character is written at the
  41. end of the characters actually written into the array. If
  42. copying takes place between objects that overlap, the
  43. behavior is undefined.
  44. Returns
  45. [#3] The snprintf function returns the number of characters
  46. that would have been written had n been sufficiently large,
  47. not counting the terminating null character, or a negative
  48. value if an encoding error occurred. Thus, the null-
  49. terminated output has been completely written if and only if
  50. the returned value is nonnegative and less than n.
  51. */
  52. /*******************************************************************************/
  53. void zlog_buf_profile(zlog_buf_t * a_buf, int flag)
  54. {
  55. //zc_assert(a_buf,);
  56. zc_profile(flag, "---buf[%p][%ld-%ld][%ld][%s][%p:%ld]---",
  57. a_buf,
  58. a_buf->size_min, a_buf->size_max,
  59. a_buf->size_real,
  60. a_buf->truncate_str,
  61. a_buf->start, a_buf->tail - a_buf->start);
  62. return;
  63. }
  64. /*******************************************************************************/
  65. void zlog_buf_del(zlog_buf_t * a_buf)
  66. {
  67. //zc_assert(a_buf,);
  68. if (a_buf->start) free(a_buf->start);
  69. zc_debug("zlog_buf_del[%p]", a_buf);
  70. free(a_buf);
  71. return;
  72. }
  73. zlog_buf_t *zlog_buf_new(size_t buf_size_min, size_t buf_size_max, const char *truncate_str)
  74. {
  75. zlog_buf_t *a_buf;
  76. if (buf_size_min == 0) {
  77. zc_error("buf_size_min == 0, not allowed");
  78. return NULL;
  79. }
  80. if (buf_size_max != 0 && buf_size_max < buf_size_min) {
  81. zc_error("buf_size_max[%lu] < buf_size_min[%lu] && buf_size_max != 0",
  82. (unsigned long)buf_size_max, (unsigned long)buf_size_min);
  83. return NULL;
  84. }
  85. a_buf = calloc(1, sizeof(*a_buf));
  86. if (!a_buf) {
  87. zc_error("calloc fail, errno[%d]", errno);
  88. return NULL;
  89. }
  90. if (truncate_str) {
  91. if (strlen(truncate_str) > sizeof(a_buf->truncate_str) - 1) {
  92. zc_error("truncate_str[%s] overflow", truncate_str);
  93. goto err;
  94. } else {
  95. strcpy(a_buf->truncate_str, truncate_str);
  96. }
  97. a_buf->truncate_str_len = strlen(truncate_str);
  98. }
  99. a_buf->size_min = buf_size_min;
  100. a_buf->size_max = buf_size_max;
  101. a_buf->size_real = a_buf->size_min;
  102. a_buf->start = calloc(1, a_buf->size_real);
  103. if (!a_buf->start) {
  104. zc_error("calloc fail, errno[%d]", errno);
  105. goto err;
  106. }
  107. a_buf->tail = a_buf->start;
  108. a_buf->end_plus_1 = a_buf->start + a_buf->size_real;
  109. a_buf->end = a_buf->end_plus_1 - 1;
  110. //zlog_buf_profile(a_buf, ZC_DEBUG);
  111. return a_buf;
  112. err:
  113. zlog_buf_del(a_buf);
  114. return NULL;
  115. }
  116. /*******************************************************************************/
  117. static void zlog_buf_truncate(zlog_buf_t * a_buf)
  118. {
  119. char *p;
  120. size_t len;
  121. if ((a_buf->truncate_str)[0] == '\0') return;
  122. p = (a_buf->tail - a_buf->truncate_str_len);
  123. if (p < a_buf->start) p = a_buf->start;
  124. len = a_buf->tail - p;
  125. memcpy(p, a_buf->truncate_str, len);
  126. return;
  127. }
  128. /*******************************************************************************/
  129. /* return 0: success
  130. * return <0: fail, set size_real to -1;
  131. * return >0: by conf limit, can't extend size
  132. * increment must > 0
  133. */
  134. static int zlog_buf_resize(zlog_buf_t * a_buf, size_t increment)
  135. {
  136. int rc = 0;
  137. size_t new_size = 0;
  138. size_t len = 0;
  139. char *p = NULL;
  140. if (a_buf->size_max != 0 && a_buf->size_real >= a_buf->size_max) {
  141. zc_error("a_buf->size_real[%ld] >= a_buf->size_max[%ld]",
  142. a_buf->size_real, a_buf->size_max);
  143. return 1;
  144. }
  145. if (a_buf->size_max == 0) {
  146. /* unlimit */
  147. new_size = a_buf->size_real + 1.5 * increment;
  148. } else {
  149. /* limited */
  150. if (a_buf->size_real + increment <= a_buf->size_max) {
  151. new_size = a_buf->size_real + increment;
  152. } else {
  153. new_size = a_buf->size_max;
  154. rc = 1;
  155. }
  156. }
  157. len = a_buf->tail - a_buf->start;
  158. p = realloc(a_buf->start, new_size);
  159. if (!p) {
  160. zc_error("realloc fail, errno[%d]", errno);
  161. free(a_buf->start);
  162. a_buf->start = NULL;
  163. a_buf->tail = NULL;
  164. a_buf->end = NULL;
  165. a_buf->end_plus_1 = NULL;
  166. return -1;
  167. } else {
  168. a_buf->start = p;
  169. a_buf->tail = p + len;
  170. a_buf->size_real = new_size;
  171. a_buf->end_plus_1 = a_buf->start + new_size;
  172. a_buf->end = a_buf->end_plus_1 - 1;
  173. }
  174. return rc;
  175. }
  176. int zlog_buf_vprintf(zlog_buf_t * a_buf, const char *format, va_list args)
  177. {
  178. va_list ap;
  179. size_t size_left;
  180. int nwrite;
  181. if (!a_buf->start) {
  182. zc_error("pre-use of zlog_buf_resize fail, so can't convert");
  183. return -1;
  184. }
  185. va_copy(ap, args);
  186. size_left = a_buf->end_plus_1 - a_buf->tail;
  187. nwrite = vsnprintf(a_buf->tail, size_left, format, ap);
  188. if (nwrite >= 0 && nwrite < size_left) {
  189. a_buf->tail += nwrite;
  190. //*(a_buf->tail) = '\0';
  191. return 0;
  192. } else if (nwrite < 0) {
  193. zc_error("vsnprintf fail, errno[%d]", errno);
  194. zc_error("nwrite[%d], size_left[%ld], format[%s]", nwrite, size_left, format);
  195. return -1;
  196. } else if (nwrite >= size_left) {
  197. int rc;
  198. //zc_debug("nwrite[%d]>=size_left[%ld],format[%s],resize", nwrite, size_left, format);
  199. rc = zlog_buf_resize(a_buf, nwrite - size_left + 1);
  200. if (rc > 0) {
  201. zc_error("conf limit to %ld, can't extend, so truncate", a_buf->size_max);
  202. va_copy(ap, args);
  203. size_left = a_buf->end_plus_1 - a_buf->tail;
  204. vsnprintf(a_buf->tail, size_left, format, ap);
  205. a_buf->tail += size_left - 1;
  206. //*(a_buf->tail) = '\0';
  207. zlog_buf_truncate(a_buf);
  208. return 1;
  209. } else if (rc < 0) {
  210. zc_error("zlog_buf_resize fail");
  211. return -1;
  212. } else {
  213. //zc_debug("zlog_buf_resize succ, to[%ld]", a_buf->size_real);
  214. va_copy(ap, args);
  215. size_left = a_buf->end_plus_1 - a_buf->tail;
  216. nwrite = vsnprintf(a_buf->tail, size_left, format, ap);
  217. if (nwrite < 0) {
  218. zc_error("vsnprintf fail, errno[%d]", errno);
  219. zc_error("nwrite[%d], size_left[%ld], format[%s]", nwrite, size_left, format);
  220. return -1;
  221. } else {
  222. a_buf->tail += nwrite;
  223. //*(a_buf->tail) = '\0';
  224. return 0;
  225. }
  226. }
  227. }
  228. return 0;
  229. }
  230. /*******************************************************************************/
  231. /* if width > num_len, 0 padding, else output num */
  232. int zlog_buf_printf_dec32(zlog_buf_t * a_buf, uint32_t ui32, int width)
  233. {
  234. unsigned char *p;
  235. char *q;
  236. unsigned char tmp[ZLOG_INT32_LEN + 1];
  237. size_t num_len, zero_len, out_len;
  238. if (!a_buf->start) {
  239. zc_error("pre-use of zlog_buf_resize fail, so can't convert");
  240. return -1;
  241. }
  242. p = tmp + ZLOG_INT32_LEN;
  243. do {
  244. *--p = (unsigned char) (ui32 % 10 + '0');
  245. } while (ui32 /= 10);
  246. /* zero or space padding */
  247. num_len = (tmp + ZLOG_INT32_LEN) - p;
  248. if (width > num_len) {
  249. zero_len = width - num_len;
  250. out_len = width;
  251. } else {
  252. zero_len = 0;
  253. out_len = num_len;
  254. }
  255. if ((q = a_buf->tail + out_len) > a_buf->end) {
  256. int rc;
  257. //zc_debug("size_left not enough, resize");
  258. rc = zlog_buf_resize(a_buf, out_len - (a_buf->end - a_buf->tail));
  259. if (rc > 0) {
  260. size_t len_left;
  261. zc_error("conf limit to %ld, can't extend, so output", a_buf->size_max);
  262. len_left = a_buf->end - a_buf->tail;
  263. if (len_left <= zero_len) {
  264. zero_len = len_left;
  265. num_len = 0;
  266. } else if (len_left > zero_len) {
  267. /* zero_len not changed */
  268. num_len = len_left - zero_len;
  269. }
  270. if (zero_len) memset(a_buf->tail, '0', zero_len);
  271. memcpy(a_buf->tail + zero_len, p, num_len);
  272. a_buf->tail += len_left;
  273. //*(a_buf->tail) = '\0';
  274. zlog_buf_truncate(a_buf);
  275. return 1;
  276. } else if (rc < 0) {
  277. zc_error("zlog_buf_resize fail");
  278. return -1;
  279. } else {
  280. //zc_debug("zlog_buf_resize succ, to[%ld]", a_buf->size_real);
  281. q = a_buf->tail + out_len; /* re-calculate p*/
  282. }
  283. }
  284. if (zero_len) memset(a_buf->tail, '0', zero_len);
  285. memcpy(a_buf->tail + zero_len, p, num_len);
  286. a_buf->tail = q;
  287. //*(a_buf->tail) = '\0';
  288. return 0;
  289. }
  290. /*******************************************************************************/
  291. int zlog_buf_printf_dec64(zlog_buf_t * a_buf, uint64_t ui64, int width)
  292. {
  293. unsigned char *p;
  294. char *q;
  295. unsigned char tmp[ZLOG_INT64_LEN + 1];
  296. size_t num_len, zero_len, out_len;
  297. uint32_t ui32;
  298. if (!a_buf->start) {
  299. zc_error("pre-use of zlog_buf_resize fail, so can't convert");
  300. return -1;
  301. }
  302. p = tmp + ZLOG_INT64_LEN;
  303. if (ui64 <= ZLOG_MAX_UINT32_VALUE) {
  304. /*
  305. * To divide 64-bit numbers and to find remainders
  306. * on the x86 platform gcc and icc call the libc functions
  307. * [u]divdi3() and [u]moddi3(), they call another function
  308. * in its turn. On FreeBSD it is the qdivrem() function,
  309. * its source code is about 170 lines of the code.
  310. * The glibc counterpart is about 150 lines of the code.
  311. *
  312. * For 32-bit numbers and some divisors gcc and icc use
  313. * a inlined multiplication and shifts. For example,
  314. * unsigned "i32 / 10" is compiled to
  315. *
  316. * (i32 * 0xCCCCCCCD) >> 35
  317. */
  318. ui32 = (uint32_t) ui64;
  319. do {
  320. *--p = (unsigned char) (ui32 % 10 + '0');
  321. } while (ui32 /= 10);
  322. } else {
  323. do {
  324. *--p = (unsigned char) (ui64 % 10 + '0');
  325. } while (ui64 /= 10);
  326. }
  327. /* zero or space padding */
  328. num_len = (tmp + ZLOG_INT64_LEN) - p;
  329. if (width > num_len) {
  330. zero_len = width - num_len;
  331. out_len = width;
  332. } else {
  333. zero_len = 0;
  334. out_len = num_len;
  335. }
  336. if ((q = a_buf->tail + out_len) > a_buf->end) {
  337. int rc;
  338. //zc_debug("size_left not enough, resize");
  339. rc = zlog_buf_resize(a_buf, out_len - (a_buf->end - a_buf->tail));
  340. if (rc > 0) {
  341. size_t len_left;
  342. zc_error("conf limit to %ld, can't extend, so output", a_buf->size_max);
  343. len_left = a_buf->end - a_buf->tail;
  344. if (len_left <= zero_len) {
  345. zero_len = len_left;
  346. num_len = 0;
  347. } else if (len_left > zero_len) {
  348. /* zero_len not changed */
  349. num_len = len_left - zero_len;
  350. }
  351. if (zero_len) memset(a_buf->tail, '0', zero_len);
  352. memcpy(a_buf->tail + zero_len, p, num_len);
  353. a_buf->tail += len_left;
  354. //*(a_buf->tail) = '\0';
  355. zlog_buf_truncate(a_buf);
  356. return 1;
  357. } else if (rc < 0) {
  358. zc_error("zlog_buf_resize fail");
  359. return -1;
  360. } else {
  361. //zc_debug("zlog_buf_resize succ, to[%ld]", a_buf->size_real);
  362. q = a_buf->tail + out_len; /* re-calculate p*/
  363. }
  364. }
  365. if (zero_len) memset(a_buf->tail, '0', zero_len);
  366. memcpy(a_buf->tail + zero_len, p, num_len);
  367. a_buf->tail = q;
  368. //*(a_buf->tail) = '\0';
  369. return 0;
  370. }
  371. /*******************************************************************************/
  372. int zlog_buf_printf_hex(zlog_buf_t * a_buf, uint32_t ui32, int width)
  373. {
  374. unsigned char *p;
  375. char *q;
  376. unsigned char tmp[ZLOG_INT32_LEN + 1];
  377. size_t num_len, zero_len, out_len;
  378. static unsigned char hex[] = "0123456789abcdef";
  379. //static unsigned char HEX[] = "0123456789ABCDEF";
  380. if (!a_buf->start) {
  381. zc_error("pre-use of zlog_buf_resize fail, so can't convert");
  382. return -1;
  383. }
  384. p = tmp + ZLOG_INT32_LEN;
  385. do {
  386. /* the "(uint32_t)" cast disables the BCC's warning */
  387. *--p = hex[(uint32_t) (ui32 & 0xf)];
  388. } while (ui32 >>= 4);
  389. #if 0
  390. } else { /* is_hex == 2 */
  391. do {
  392. /* the "(uint32_t)" cast disables the BCC's warning */
  393. *--p = HEX[(uint32_t) (ui64 & 0xf)];
  394. } while (ui64 >>= 4);
  395. }
  396. #endif
  397. /* zero or space padding */
  398. num_len = (tmp + ZLOG_INT32_LEN) - p;
  399. if (width > num_len) {
  400. zero_len = width - num_len;
  401. out_len = width;
  402. } else {
  403. zero_len = 0;
  404. out_len = num_len;
  405. }
  406. if ((q = a_buf->tail + out_len) > a_buf->end) {
  407. int rc;
  408. //zc_debug("size_left not enough, resize");
  409. rc = zlog_buf_resize(a_buf, out_len - (a_buf->end - a_buf->tail));
  410. if (rc > 0) {
  411. size_t len_left;
  412. zc_error("conf limit to %ld, can't extend, so output", a_buf->size_max);
  413. len_left = a_buf->end - a_buf->tail;
  414. if (len_left <= zero_len) {
  415. zero_len = len_left;
  416. num_len = 0;
  417. } else if (len_left > zero_len) {
  418. /* zero_len not changed */
  419. num_len = len_left - zero_len;
  420. }
  421. if (zero_len) memset(a_buf->tail, '0', zero_len);
  422. memcpy(a_buf->tail + zero_len, p, num_len);
  423. a_buf->tail += len_left;
  424. //*(a_buf->tail) = '\0';
  425. zlog_buf_truncate(a_buf);
  426. return 1;
  427. } else if (rc < 0) {
  428. zc_error("zlog_buf_resize fail");
  429. return -1;
  430. } else {
  431. //zc_debug("zlog_buf_resize succ, to[%ld]", a_buf->size_real);
  432. q = a_buf->tail + out_len; /* re-calculate p*/
  433. }
  434. }
  435. if (zero_len) memset(a_buf->tail, '0', zero_len);
  436. memcpy(a_buf->tail + zero_len, p, num_len);
  437. a_buf->tail = q;
  438. //*(a_buf->tail) = '\0';
  439. return 0;
  440. }
  441. /*******************************************************************************/
  442. int zlog_buf_append(zlog_buf_t * a_buf, const char *str, size_t str_len)
  443. {
  444. char *p;
  445. #if 0
  446. if (str_len <= 0 || str == NULL) {
  447. return 0;
  448. }
  449. if (!a_buf->start) {
  450. zc_error("pre-use of zlog_buf_resize fail, so can't convert");
  451. return -1;
  452. }
  453. #endif
  454. if ((p = a_buf->tail + str_len) > a_buf->end) {
  455. int rc;
  456. //zc_debug("size_left not enough, resize");
  457. rc = zlog_buf_resize(a_buf, str_len - (a_buf->end - a_buf->tail));
  458. if (rc > 0) {
  459. size_t len_left;
  460. zc_error("conf limit to %ld, can't extend, so output",
  461. a_buf->size_max);
  462. len_left = a_buf->end - a_buf->tail;
  463. memcpy(a_buf->tail, str, len_left);
  464. a_buf->tail += len_left;
  465. //*(a_buf->tail) = '\0';
  466. zlog_buf_truncate(a_buf);
  467. return 1;
  468. } else if (rc < 0) {
  469. zc_error("zlog_buf_resize fail");
  470. return -1;
  471. } else {
  472. //zc_debug("zlog_buf_resize succ, to[%ld]", a_buf->size_real);
  473. p = a_buf->tail + str_len; /* re-calculate p*/
  474. }
  475. }
  476. memcpy(a_buf->tail, str, str_len);
  477. a_buf->tail = p;
  478. // *(a_buf->tail) = '\0';
  479. return 0;
  480. }
  481. /*******************************************************************************/
  482. int zlog_buf_adjust_append(zlog_buf_t * a_buf, const char *str, size_t str_len,
  483. int left_adjust, int zero_pad, size_t in_width, size_t out_width)
  484. {
  485. size_t append_len = 0;
  486. size_t source_len = 0;
  487. size_t space_len = 0;
  488. #if 0
  489. if (str_len <= 0 || str == NULL) {
  490. return 0;
  491. }
  492. #endif
  493. if (!a_buf->start) {
  494. zc_error("pre-use of zlog_buf_resize fail, so can't convert");
  495. return -1;
  496. }
  497. /* calculate how many character will be got from str */
  498. if (out_width == 0 || str_len < out_width) {
  499. source_len = str_len;
  500. } else {
  501. source_len = out_width;
  502. }
  503. /* calculate how many character will be output */
  504. if (in_width == 0 || source_len >= in_width ) {
  505. append_len = source_len;
  506. space_len = 0;
  507. } else {
  508. append_len = in_width;
  509. space_len = in_width - source_len;
  510. }
  511. /* |-----append_len-----------| */
  512. /* |-source_len---|-space_len-| left_adjust */
  513. /* |-space_len---|-source_len-| right_adjust */
  514. /* |-(size_real-1)---| size not enough */
  515. if (append_len > a_buf->end - a_buf->tail) {
  516. int rc = 0;
  517. //zc_debug("size_left not enough, resize");
  518. rc = zlog_buf_resize(a_buf, append_len - (a_buf->end -a_buf->tail));
  519. if (rc > 0) {
  520. zc_error("conf limit to %ld, can't extend, so output", a_buf->size_max);
  521. append_len = (a_buf->end - a_buf->tail);
  522. if (left_adjust) {
  523. if (source_len < append_len) {
  524. space_len = append_len - source_len;
  525. } else {
  526. source_len = append_len;
  527. space_len = 0;
  528. }
  529. if (space_len) memset(a_buf->tail + source_len, ' ', space_len);
  530. memcpy(a_buf->tail, str, source_len);
  531. } else {
  532. if (space_len < append_len) {
  533. source_len = append_len - space_len;
  534. } else {
  535. space_len = append_len;
  536. source_len = 0;
  537. }
  538. if (space_len) {
  539. if (zero_pad) {
  540. memset(a_buf->tail, '0', space_len);
  541. } else {
  542. memset(a_buf->tail, ' ', space_len);
  543. }
  544. }
  545. memcpy(a_buf->tail + space_len, str, source_len);
  546. }
  547. a_buf->tail += append_len;
  548. //*(a_buf->tail) = '\0';
  549. zlog_buf_truncate(a_buf);
  550. return 1;
  551. } else if (rc < 0) {
  552. zc_error("zlog_buf_resize fail");
  553. return -1;
  554. } else {
  555. //zc_debug("zlog_buf_resize succ, to[%ld]", a_buf->size_real);
  556. }
  557. }
  558. if (left_adjust) {
  559. if (space_len) memset(a_buf->tail + source_len, ' ', space_len);
  560. memcpy(a_buf->tail, str, source_len);
  561. } else {
  562. if (space_len) {
  563. if (zero_pad) {
  564. memset(a_buf->tail, '0', space_len);
  565. } else {
  566. memset(a_buf->tail, ' ', space_len);
  567. }
  568. }
  569. memcpy(a_buf->tail + space_len, str, source_len);
  570. }
  571. a_buf->tail += append_len;
  572. //*(a_buf->tail) = '\0';
  573. return 0;
  574. }
  575. /*******************************************************************************/