diff options
-rw-r--r-- | include/mangle.h | 7 | ||||
-rw-r--r-- | lib/mangle.c | 57 |
2 files changed, 46 insertions, 18 deletions
diff --git a/include/mangle.h b/include/mangle.h index 158d07820..ec492b556 100644 --- a/include/mangle.h +++ b/include/mangle.h @@ -8,6 +8,8 @@ extern char *mangle(const char *s); extern void unmangle_to_buffer(const char *s, char *buf, size_t len); +void unhexmangle_to_buffer(const char *s, char *buf, size_t len); + extern char *unmangle(const char *s, char **end); static inline void unmangle_string(char *s) @@ -15,5 +17,10 @@ static inline void unmangle_string(char *s) unmangle_to_buffer(s, s, strlen(s) + 1); } +static inline void unhexmangle_string(char *s) +{ + unhexmangle_to_buffer(s, s, strlen(s) + 1); +} + #endif /* UTIL_LINUX_MANGLE_H */ diff --git a/lib/mangle.c b/lib/mangle.c index fd0ee993e..e1b48149f 100644 --- a/lib/mangle.c +++ b/lib/mangle.c @@ -13,41 +13,40 @@ #include "mangle.h" #include "c.h" -#define isoctal(a) (((a) & ~7) == '0') +#define isoctal(a) (((a) & ~7) == '0') + +#define from_hex(c) (isdigit(c) ? c - '0' : tolower(c) - 'a' + 10) + +#define is_unwanted_char(x) (strchr(" \t\n\\", (unsigned int) x) != NULL) -static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' }; char *mangle(const char *s) { char *ss, *sp; - size_t n; if (!s) return NULL; - n = strlen(s); - ss = sp = malloc(4*n+1); + ss = sp = malloc(4 * strlen(s) + 1); if (!sp) return NULL; while(1) { - for (n = 0; n < sizeof(need_escaping); n++) { - if (*s == need_escaping[n]) { - *sp++ = '\\'; - *sp++ = '0' + ((*s & 0300) >> 6); - *sp++ = '0' + ((*s & 070) >> 3); - *sp++ = '0' + (*s & 07); - goto next; - } + if (is_unwanted_char(*s)) { + *sp++ = '\\'; + *sp++ = '0' + ((*s & 0300) >> 6); + *sp++ = '0' + ((*s & 070) >> 3); + *sp++ = '0' + (*s & 07); + } else { + *sp++ = *s; + if (!*s) + break; } - *sp++ = *s; - if (*s == 0) - break; - next: s++; } return ss; } + void unmangle_to_buffer(const char *s, char *buf, size_t len) { size_t sz = 0; @@ -70,6 +69,28 @@ void unmangle_to_buffer(const char *s, char *buf, size_t len) *buf = '\0'; } +void unhexmangle_to_buffer(const char *s, char *buf, size_t len) +{ + size_t sz = 0; + + if (!s) + return; + + while(*s && sz < len - 1) { + if (*s == '\\' && sz + 4 < len - 1 && s[1] == 'x' && + isxdigit(s[2]) && isxdigit(s[3])) { + + *buf++ = from_hex(s[2]) << 4 | from_hex(s[3]); + s += 4; + sz += 4; + } else { + *buf++ = *s++; + sz++; + } + } + *buf = '\0'; +} + static inline char *skip_nonspaces(const char *s) { while (*s && !(*s == ' ' || *s == '\t')) @@ -110,7 +131,7 @@ char *unmangle(const char *s, char **end) int main(int argc, char *argv[]) { if (argc < 3) { - fprintf(stderr, "usage: %s --mangle | --unmangle <string>\n", + fprintf(stderr, "usage: %s --mangle|unmangle <string>\n", program_invocation_short_name); return EXIT_FAILURE; } |