summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorruki <[email protected]>2025-12-06 20:12:56 +0800
committerruki <[email protected]>2025-12-06 20:12:56 +0800
commit9f72cca908c2e2a531adb3276287a2ac28b3e8af (patch)
treebda669b260167b6f33de95f53764f21e31b36fbf /core/src
parentcd1323f4590b51b092da2c69d44853e1185e3c40 (diff)
improve bin2c
Diffstat (limited to 'core/src')
-rw-r--r--core/src/xmake/utils/bin2c.c162
1 files changed, 120 insertions, 42 deletions
diff --git a/core/src/xmake/utils/bin2c.c b/core/src/xmake/utils/bin2c.c
index b39217e0c..a0e0cf7dd 100644
--- a/core/src/xmake/utils/bin2c.c
+++ b/core/src/xmake/utils/bin2c.c
@@ -31,65 +31,141 @@
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+
+#define XM_BIN2C_DATA_SIZE (8 * 1024)
+#define XM_BIN2C_LINE_SIZE (4 * 1024)
+#define XM_BIN2C_LINEWIDTH_MAX ((XM_BIN2C_LINE_SIZE - 2) / 6)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
-static __tb_inline__ tb_size_t xm_utils_bin2c_hex2str(tb_char_t str[5], tb_byte_t value) {
- static tb_char_t const *digits_table = "0123456789ABCDEF";
- str[0] = ' ';
- str[1] = '0';
- str[2] = 'x';
- str[3] = digits_table[(value >> 4) & 15];
- str[4] = digits_table[value & 15];
- return 5;
+
+// optimized hex conversion table
+static tb_char_t const *xm_utils_bin2c_digits = "0123456789ABCDEF";
+
+// inline hex conversion for better performance
+static __tb_inline__ tb_void_t xm_utils_bin2c_write_hex(tb_char_t *str, tb_byte_t value) {
+ str[0] = ' ';
+ str[1] = '0';
+ str[2] = 'x';
+ str[3] = xm_utils_bin2c_digits[(value >> 4) & 15];
+ str[4] = xm_utils_bin2c_digits[value & 15];
}
static tb_bool_t xm_utils_bin2c_dump(tb_stream_ref_t istream,
tb_stream_ref_t ostream,
tb_int_t linewidth,
tb_bool_t nozeroend) {
+
tb_bool_t first = tb_true;
- tb_hong_t i = 0;
- tb_hong_t left = 0;
- tb_char_t line[4096];
- tb_byte_t data[512];
+ tb_byte_t data[XM_BIN2C_DATA_SIZE];
+ tb_char_t line[XM_BIN2C_LINE_SIZE];
tb_size_t linesize = 0;
- tb_size_t need = 0;
- tb_assert_and_check_return_val(linewidth < sizeof(data), tb_false);
- while (!tb_stream_beof(istream)) {
- linesize = 0;
- left = tb_stream_left(istream);
- need = (tb_size_t)tb_min(left, linewidth);
- if (need) {
- if (!tb_stream_bread(istream, data, need))
+ tb_size_t bytes_in_line = 0;
+ tb_size_t data_pos = 0;
+ tb_size_t data_size = 0;
+ tb_assert_and_check_return_val(linewidth > 0 && linewidth <= XM_BIN2C_LINEWIDTH_MAX, tb_false);
+
+ while (!tb_stream_beof(istream) || data_pos < data_size) {
+ // read a large chunk of data if buffer is empty
+ if (data_pos >= data_size) {
+ tb_hong_t left = tb_stream_left(istream);
+ tb_size_t to_read = (tb_size_t)tb_min(left, (tb_hong_t)XM_BIN2C_DATA_SIZE);
+ tb_check_break(to_read);
+
+ if (!tb_stream_bread(istream, data, to_read)) {
break;
-
+ }
+ data_size = to_read;
+ data_pos = 0;
+
+ // add zero terminator at the end if needed
if (!nozeroend && tb_stream_beof(istream)) {
- tb_assert_and_check_break(need + 1 < sizeof(data));
- data[need++] = '\0';
+ if (data_size < XM_BIN2C_DATA_SIZE) {
+ data[data_size++] = '\0';
+ }
}
-
- tb_assert_and_check_break(linesize + 6 * need < sizeof(line));
-
- i = 0;
- if (first) {
- first = tb_false;
- line[linesize++] = ' ';
+ }
+
+ // process bytes from buffer
+ while (data_pos < data_size) {
+ // check if we need a new line
+ if (bytes_in_line >= (tb_size_t)linewidth) {
+ // ensure we have space for newline
+ if (linesize + 2 > sizeof(line)) {
+ // flush line if buffer is full
+ if (!tb_stream_bwrit(ostream, (tb_byte_t *)line, linesize)) {
+ return tb_false;
+ }
+ linesize = 0;
+ }
+ // add newline
+ #ifdef TB_CONFIG_OS_WINDOWS
+ line[linesize++] = '\r';
+ #endif
+ line[linesize++] = '\n';
+
+ // write line
+ if (!tb_stream_bwrit(ostream, (tb_byte_t *)line, linesize)) {
+ return tb_false;
+ }
+
+ linesize = 0;
+ bytes_in_line = 0;
+ first = tb_false;
+ }
+
+ // ensure we have enough space in line buffer (6 chars per byte: ", 0xXX")
+ if (linesize + 6 > sizeof(line)) {
+ // flush partial line if buffer is full
+ if (linesize > 0) {
+ if (!tb_stream_bwrit(ostream, (tb_byte_t *)line, linesize)) {
+ return tb_false;
+ }
+ linesize = 0;
+ }
+ }
+
+ // add separator
+ if (bytes_in_line == 0) {
+ if (first) {
+ line[linesize++] = ' ';
+ first = tb_false;
+ } else {
+ line[linesize++] = ',';
+ }
} else {
line[linesize++] = ',';
}
- linesize += xm_utils_bin2c_hex2str(line + linesize, data[i]);
-
- for (i = 1; i < need; i++) {
- line[linesize++] = ',';
- linesize += xm_utils_bin2c_hex2str(line + linesize, data[i]);
+
+ // write hex value (inline for performance)
+ xm_utils_bin2c_write_hex(line + linesize, data[data_pos]);
+ linesize += 5;
+ bytes_in_line++;
+ data_pos++;
+ }
+ }
+
+ // flush remaining line
+ if (linesize > 0) {
+ // ensure we have space for newline
+ if (linesize + 2 > sizeof(line)) {
+ if (!tb_stream_bwrit(ostream, (tb_byte_t *)line, linesize)) {
+ return tb_false;
}
- tb_assert_and_check_break(i == need && linesize && linesize < sizeof(line));
-
- if (tb_stream_bwrit_line(ostream, line, linesize) < 0)
- break;
+ linesize = 0;
+ }
+ #ifdef TB_CONFIG_OS_WINDOWS
+ line[linesize++] = '\r';
+ #endif
+ line[linesize++] = '\n';
+ if (!tb_stream_bwrit(ostream, (tb_byte_t *)line, linesize)) {
+ return tb_false;
}
}
-
+
return tb_stream_beof(istream);
}
@@ -147,12 +223,14 @@ tb_int_t xm_utils_bin2c(lua_State *lua) {
} while (0);
- if (istream)
+ if (istream) {
tb_stream_clos(istream);
+ }
istream = tb_null;
- if (ostream)
+ if (ostream) {
tb_stream_clos(ostream);
+ }
ostream = tb_null;
return ok ? 1 : 2;