diff options
Diffstat (limited to 'src/helper')
-rw-r--r-- | src/helper/binarybuffer.c | 170 | ||||
-rw-r--r-- | src/helper/binarybuffer.h | 4 | ||||
-rw-r--r-- | src/helper/interpreter.c | 2 |
3 files changed, 138 insertions, 38 deletions
diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index ce33f138..6afd6e59 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -208,56 +208,156 @@ u32 flip_u32(u32 value, unsigned int num) return c; } -char* buf_to_char(u8 *buf, int size) +int ceil_f_to_u32(float x) { - int char_len = CEIL(size, 8) * 2; - char *char_buf = malloc(char_len + 1); - int i; - int bits_left = size; + u32 y; + + if (x < 0) /* return zero for negative numbers */ + return 0; - char_buf[char_len] = 0; + y = x; /* cut off fraction */ - for (i = 0; i < CEIL(size, 8); i++) + if ((x - y) > 0.0) /* if there was a fractional part, increase by one */ + y++; + + return y; +} + +char* buf_to_str(u8 *buf, int buf_len, int radix) +{ + const char *DIGITS = "0123456789abcdef"; + float factor; + char *str; + int str_len; + int b256_len = CEIL(buf_len, 8); + u32 tmp; + + int j; /* base-256 digits */ + int i; /* output digits (radix) */ + + if (radix == 16) { - if (bits_left < 8) - { - buf[i] &= ((1 << bits_left) - 1); - } - - if (((buf[i] & 0x0f) >= 0) && ((buf[i] & 0x0f) <= 9)) - char_buf[char_len - 2*i - 1] = '0' + (buf[i] & 0xf); - else - char_buf[char_len - 2*i - 1] = 'a' + (buf[i] & 0xf) - 10; - - if (((buf[i] & 0xf0) >> 4 >= 0) && ((buf[i] & 0xf0) >> 4 <= 9)) - char_buf[char_len - 2*i - 2] = '0' + ((buf[i] & 0xf0) >> 4); - else - char_buf[char_len - 2*i - 2] = 'a' + ((buf[i] & 0xf0) >> 4) - 10; - + factor = 2.0; /* log(256) / log(16) = 2.0 */ } + else if (radix == 10) + { + factor = 2.40824; /* log(256) / log(10) = 2.40824 */ + } + else if (radix == 8) + { + factor = 2.66667; /* log(256) / log(8) = 2.66667 */ + } + else + return NULL; + + str_len = ceil_f_to_u32(CEIL(buf_len, 8) * factor); + str = calloc(str_len + 1, 1); + + for (i = b256_len - 1; i >= 0; i--) + { + tmp = buf[i]; + if ((i == (buf_len / 8)) && (buf_len % 8)) + tmp &= (0xff >> (8 - (buf_len % 8))); - return char_buf; + for (j = str_len; j > 0; j--) + { + tmp += (u32)str[j-1] * 256; + str[j-1] = (u8)(tmp % radix); + tmp /= radix; + } + } + + for (j = 0; j < str_len; j++) + str[j] = DIGITS[(int)str[j]]; + + return str; } -int char_to_buf(char *buf, int len, u8 *bin_buf, int buf_size) +int str_to_buf(char* str, int str_len, u8 *buf, int buf_len, int radix) { - int bin_len = CEIL(len, 2); - int i; + char *charbuf; + u32 tmp; + float factor; + u8 *b256_buf; + int b256_len; - if (buf_size < CEIL(bin_len, 8)) - return 0; + int j; /* base-256 digits */ + int i; /* input digits (ASCII) */ + + if (radix == 0) + { + /* identify radix, and skip radix-prefix (0, 0x or 0X) */ + if ((str[0] == '0') && (str[1] && ((str[1] == 'x') || (str[1] == 'X')))) + { + radix = 16; + str += 2; + str_len -= 2; + } + else if ((str[0] == '0') && (str_len != 1)) + { + radix = 8; + str += 1; + str_len -= 1; + } + else + { + radix = 10; + } + } - if (len % 2) + if (radix == 16) + factor = 0.5; /* log(16) / log(256) = 0.5 */ + else if (radix == 10) + factor = 0.41524; /* log(10) / log(256) = 0.41524 */ + else if (radix == 8) + factor = 0.375; /* log(8) / log(256) = 0.375 */ + else return 0; + + /* copy to zero-terminated buffer */ + charbuf = malloc(str_len + 1); + memcpy(charbuf, str, str_len); + charbuf[str_len] = '\0'; - for (i = 0; i < strlen(buf); i++) - { - u32 tmp; - sscanf(buf + 2*i, "%2x", &tmp); - bin_buf[i] = tmp & 0xff; + /* number of digits in base-256 notation */ + b256_len = ceil_f_to_u32(str_len * factor); + b256_buf = calloc(b256_len, 1); + + /* go through zero terminated buffer */ + for (i = 0; charbuf[i]; i++) + { + tmp = charbuf[i]; + if ((tmp >= '0') && (tmp <= '9')) + tmp = (tmp - '0'); + else if ((tmp >= 'a') && (tmp <= 'f')) + tmp = (tmp - 'a' + 10); + else if ((tmp >= 'A') && (tmp <= 'F')) + tmp = (tmp - 'A' + 10); + else continue; /* skip characters other than [0-9,a-f,A-F] */ + + if (tmp >= radix) + continue; /* skip digits invalid for the current radix */ + + for (j = 0; j < b256_len; j++) + { + tmp += (u32)b256_buf[j] * radix; + b256_buf[j] = (u8)(tmp & 0xFF); + tmp >>= 8; + } + } - return bin_len * 8; + for (j = 0; j < CEIL(buf_len, 8); j++) + buf[j] = b256_buf[j]; + + /* mask out bits that don't belong to the buffer */ + if (buf_len % 8) + buf[(buf_len / 8)] &= 0xff >> (8 - (buf_len % 8)); + + free(b256_buf); + free(charbuf); + + return i; } int buf_to_u32_handler(u8 *in_buf, void *priv) diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index 0a688945..6f39e7cf 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -38,8 +38,8 @@ extern u8* buf_cpy(u8 *from, u8 *to, int size); extern u8* buf_set_ones(u8 *buf, int count); extern u8* buf_set_buf(u8 *src, int src_start, u8 *dst, int dst_start, int len); -extern char* buf_to_char(u8 *buf, int size); -extern int char_to_buf(char *buf, int len, u8 *bin_buf, int buf_size); +extern int str_to_buf(char* str, int len, u8 *bin_buf, int buf_size, int radix); +extern char* buf_to_str(u8 *buf, int size, int radix); extern int buf_to_u32_handler(u8 *in_buf, void *priv); diff --git a/src/helper/interpreter.c b/src/helper/interpreter.c index 17d24b1f..7b0432ab 100644 --- a/src/helper/interpreter.c +++ b/src/helper/interpreter.c @@ -126,7 +126,7 @@ int handle_var_command(struct command_context_s *cmd_ctx, char *cmd, char **args last_var_p = &((*last_var_p)->next); } - if ((args[0][0] >= 0) && (args[0][0] <= 9)) + if ((args[0][0] >= '0') && (args[0][0] <= '9')) { command_print(cmd_ctx, "invalid name specified (first character may not be a number)"); return ERROR_OK; |