|
30 | 30 | */ |
31 | 31 | #include "prefix.h" |
32 | 32 |
|
| 33 | +/* ////////////////////////////////////////////////////////////////////////////////////// |
| 34 | + * macros |
| 35 | + */ |
| 36 | + |
| 37 | +#define XM_BIN2C_DATA_SIZE (8 * 1024) |
| 38 | +#define XM_BIN2C_LINE_SIZE (4 * 1024) |
| 39 | +#define XM_BIN2C_LINEWIDTH_MAX ((XM_BIN2C_LINE_SIZE - 2) / 6) |
| 40 | + |
33 | 41 | /* ////////////////////////////////////////////////////////////////////////////////////// |
34 | 42 | * private implementation |
35 | 43 | */ |
36 | | -static __tb_inline__ tb_size_t xm_utils_bin2c_hex2str(tb_char_t str[5], tb_byte_t value) { |
37 | | - static tb_char_t const *digits_table = "0123456789ABCDEF"; |
38 | | - str[0] = ' '; |
39 | | - str[1] = '0'; |
40 | | - str[2] = 'x'; |
41 | | - str[3] = digits_table[(value >> 4) & 15]; |
42 | | - str[4] = digits_table[value & 15]; |
43 | | - return 5; |
| 44 | + |
| 45 | +// optimized hex conversion table |
| 46 | +static tb_char_t const *xm_utils_bin2c_digits = "0123456789ABCDEF"; |
| 47 | + |
| 48 | +// inline hex conversion for better performance |
| 49 | +static __tb_inline__ tb_void_t xm_utils_bin2c_write_hex(tb_char_t *str, tb_byte_t value) { |
| 50 | + str[0] = ' '; |
| 51 | + str[1] = '0'; |
| 52 | + str[2] = 'x'; |
| 53 | + str[3] = xm_utils_bin2c_digits[(value >> 4) & 15]; |
| 54 | + str[4] = xm_utils_bin2c_digits[value & 15]; |
44 | 55 | } |
45 | 56 |
|
46 | 57 | static tb_bool_t xm_utils_bin2c_dump(tb_stream_ref_t istream, |
47 | 58 | tb_stream_ref_t ostream, |
48 | 59 | tb_int_t linewidth, |
49 | 60 | tb_bool_t nozeroend) { |
| 61 | + |
50 | 62 | tb_bool_t first = tb_true; |
51 | | - tb_hong_t i = 0; |
52 | | - tb_hong_t left = 0; |
53 | | - tb_char_t line[4096]; |
54 | | - tb_byte_t data[512]; |
| 63 | + tb_bool_t zero_pending = tb_false; |
| 64 | + tb_byte_t data[XM_BIN2C_DATA_SIZE]; |
| 65 | + tb_char_t line[XM_BIN2C_LINE_SIZE]; |
55 | 66 | tb_size_t linesize = 0; |
56 | | - tb_size_t need = 0; |
57 | | - tb_assert_and_check_return_val(linewidth < sizeof(data), tb_false); |
58 | | - while (!tb_stream_beof(istream)) { |
59 | | - linesize = 0; |
60 | | - left = tb_stream_left(istream); |
61 | | - need = (tb_size_t)tb_min(left, linewidth); |
62 | | - if (need) { |
63 | | - if (!tb_stream_bread(istream, data, need)) |
64 | | - break; |
65 | | - |
66 | | - if (!nozeroend && tb_stream_beof(istream)) { |
67 | | - tb_assert_and_check_break(need + 1 < sizeof(data)); |
68 | | - data[need++] = '\0'; |
| 67 | + tb_size_t bytes_in_line = 0; |
| 68 | + tb_size_t data_pos = 0; |
| 69 | + tb_size_t data_size = 0; |
| 70 | + tb_assert_and_check_return_val(linewidth > 0 && linewidth <= XM_BIN2C_LINEWIDTH_MAX, tb_false); |
| 71 | + |
| 72 | + while (!tb_stream_beof(istream) || data_pos < data_size || zero_pending) { |
| 73 | + // read a large chunk of data if buffer is empty |
| 74 | + if (data_pos >= data_size) { |
| 75 | + // handle pending zero terminator |
| 76 | + if (zero_pending) { |
| 77 | + data[0] = '\0'; |
| 78 | + data_size = 1; |
| 79 | + data_pos = 0; |
| 80 | + zero_pending = tb_false; |
| 81 | + } else { |
| 82 | + tb_hong_t left = tb_stream_left(istream); |
| 83 | + tb_size_t to_read = (tb_size_t)tb_min(left, (tb_hong_t)XM_BIN2C_DATA_SIZE); |
| 84 | + if (!to_read) { |
| 85 | + break; |
| 86 | + } |
| 87 | + |
| 88 | + if (!tb_stream_bread(istream, data, to_read)) { |
| 89 | + break; |
| 90 | + } |
| 91 | + data_size = to_read; |
| 92 | + data_pos = 0; |
| 93 | + |
| 94 | + // check if we need to add zero terminator at the end |
| 95 | + if (!nozeroend && tb_stream_beof(istream)) { |
| 96 | + if (data_size < XM_BIN2C_DATA_SIZE) { |
| 97 | + // can add directly to current buffer |
| 98 | + data[data_size++] = '\0'; |
| 99 | + } else { |
| 100 | + // buffer is full, need to add zero in next iteration |
| 101 | + zero_pending = tb_true; |
| 102 | + } |
| 103 | + } |
| 104 | + } |
| 105 | + } |
| 106 | + |
| 107 | + // process bytes from buffer |
| 108 | + while (data_pos < data_size) { |
| 109 | + // check if we need a new line |
| 110 | + if (bytes_in_line >= (tb_size_t)linewidth) { |
| 111 | + // write line (tb_stream_bwrit_line will add newline automatically) |
| 112 | + if (tb_stream_bwrit_line(ostream, line, linesize) < 0) { |
| 113 | + return tb_false; |
| 114 | + } |
| 115 | + |
| 116 | + linesize = 0; |
| 117 | + bytes_in_line = 0; |
| 118 | + first = tb_false; |
69 | 119 | } |
70 | 120 |
|
71 | | - tb_assert_and_check_break(linesize + 6 * need < sizeof(line)); |
| 121 | + // ensure we have enough space in line buffer (6 chars per byte: ", 0xXX") |
| 122 | + if (linesize + 6 > sizeof(line)) { |
| 123 | + // flush partial line if buffer is full |
| 124 | + if (linesize > 0) { |
| 125 | + if (!tb_stream_bwrit(ostream, (tb_byte_t *)line, linesize)) { |
| 126 | + return tb_false; |
| 127 | + } |
| 128 | + linesize = 0; |
| 129 | + } |
| 130 | + } |
72 | 131 |
|
73 | | - i = 0; |
74 | | - if (first) { |
75 | | - first = tb_false; |
| 132 | + // add separator |
| 133 | + if (bytes_in_line == 0 && first) { |
76 | 134 | line[linesize++] = ' '; |
| 135 | + first = tb_false; |
77 | 136 | } else { |
78 | 137 | line[linesize++] = ','; |
79 | 138 | } |
80 | | - linesize += xm_utils_bin2c_hex2str(line + linesize, data[i]); |
81 | 139 |
|
82 | | - for (i = 1; i < need; i++) { |
83 | | - line[linesize++] = ','; |
84 | | - linesize += xm_utils_bin2c_hex2str(line + linesize, data[i]); |
85 | | - } |
86 | | - tb_assert_and_check_break(i == need && linesize && linesize < sizeof(line)); |
| 140 | + // write hex value (inline for performance) |
| 141 | + xm_utils_bin2c_write_hex(line + linesize, data[data_pos]); |
| 142 | + linesize += 5; |
| 143 | + bytes_in_line++; |
| 144 | + data_pos++; |
| 145 | + } |
| 146 | + } |
87 | 147 |
|
88 | | - if (tb_stream_bwrit_line(ostream, line, linesize) < 0) |
89 | | - break; |
| 148 | + // flush remaining line |
| 149 | + if (linesize > 0) { |
| 150 | + // write line (tb_stream_bwrit_line will add newline automatically) |
| 151 | + if (tb_stream_bwrit_line(ostream, line, linesize) < 0) { |
| 152 | + return tb_false; |
90 | 153 | } |
91 | 154 | } |
92 | 155 |
|
@@ -147,12 +210,14 @@ tb_int_t xm_utils_bin2c(lua_State *lua) { |
147 | 210 |
|
148 | 211 | } while (0); |
149 | 212 |
|
150 | | - if (istream) |
| 213 | + if (istream) { |
151 | 214 | tb_stream_clos(istream); |
| 215 | + } |
152 | 216 | istream = tb_null; |
153 | 217 |
|
154 | | - if (ostream) |
| 218 | + if (ostream) { |
155 | 219 | tb_stream_clos(ostream); |
| 220 | + } |
156 | 221 | ostream = tb_null; |
157 | 222 |
|
158 | 223 | return ok ? 1 : 2; |
|
0 commit comments