diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2015-05-04 17:30:19 -0400 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2015-05-04 17:30:19 -0400 |
commit | f5d0d2d35396e46c4e0431d28c6895396f971d20 (patch) | |
tree | 61c69ff3d1229adedbb842dd6724c8d2c8f6d8de /urldecode.c | |
parent | 18a80cee75a8bf0dc8fca71238b1e404e6651151 (diff) |
Rewrite urldecode in C
Diffstat (limited to 'urldecode.c')
-rw-r--r-- | urldecode.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/urldecode.c b/urldecode.c new file mode 100644 index 0000000..fbd39b3 --- /dev/null +++ b/urldecode.c @@ -0,0 +1,60 @@ +/* Copyright (C) 2015 Luke Shumaker <lukeshu@sbcglobal.net> */ +#include <stdio.h> + +/* ungetc is only guaranteed for 1 char; use our own buffer */ +int buf[2]; +int cnt = 0; +int ab = 0; +int _getchar() { + if (cnt > 0) + cnt--; + else + buf[ab] = getchar(); + int ret = buf[ab]; + ab = !ab; + return ret; +} +void _ungetchar() { + cnt++; + ab = !ab; +} + +int hex(int c) { + if ('0' <= c && c <= '9') + return c - '0'; + if ('A' <= c && c <= 'F') + return 10 + c - 'A'; + if ('a' <= c && c <= 'f') + return 10 + c - 'a'; + return -1; +} + +int +main () { + int c, v1, v2; + while ((c = _getchar()) != EOF) { + switch (c) { + case '%': + if ((v1 = hex(_getchar())) < 0) { + putchar('%'); + _ungetchar(); + continue; + } + if ((v2 = hex(_getchar())) < 0) { + putchar('%'); + _ungetchar(); + _ungetchar(); + continue; + } + putchar(((v1 << 4) & 0xF0) | (v2 & 0x0F)); + break; + case '+': + putchar(' '); + break; + default: + putchar(c); + break; + } + } + return 0; +} |