summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/mangle.h7
-rw-r--r--lib/mangle.c57
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;
}