Created
March 29, 2017 22:40
-
-
Save nic-hartley/104feded8dc0a75d983bebdeadb7fce5 to your computer and use it in GitHub Desktop.
The escaping methods and its tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//to simulate my environment | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
typedef unsigned long long ERROR; | |
const ERROR TTO_WORDS_VALUELESS_FAIL = 9000; | |
const ERROR TTO_UNKNOWN_TYPE_FAIL = 9001; | |
const ERROR TTO_NOT_IMPLEMENTED_FAIL = 9002; | |
const ERROR TTO_CREATE_OBJ_FAIL = 9003; | |
const ERROR TTO_STRING_ESCAPE_FAIL = 9004; | |
const ERROR TTO_ESCAPE_END_FAIL = 9005; | |
const ERROR TTO_MALLOC_FAIL = 9006; | |
const ERROR TTO_ESCAPE_BAD_HEX_FAIL = 9007; | |
const ERROR NO_ERROR = 0; | |
//code | |
char tto_hexchar_to_val(const char c) { | |
switch (c) { | |
case '0': return 0; | |
case '1': return 1; | |
case '2': return 2; | |
case '3': return 3; | |
case '4': return 4; | |
case '5': return 5; | |
case '6': return 6; | |
case '7': return 7; | |
case '8': return 8; | |
case '9': return 9; | |
case 'a': case 'A': return 10; | |
case 'b': case 'B': return 11; | |
case 'c': case 'C': return 12; | |
case 'd': case 'D': return 13; | |
case 'e': case 'E': return 14; | |
case 'f': case 'F': return 15; | |
default: return 16; | |
} | |
} | |
ERROR tto_escape_hex(const char **pos, char **ret_pos, const char *const end) { | |
char x_val; | |
int t; | |
x_val = 0; | |
++(*pos); | |
if (*pos == end) { | |
return TTO_ESCAPE_END_FAIL; | |
} | |
t = tto_hexchar_to_val(**pos); | |
if (t > 15) { | |
return TTO_ESCAPE_BAD_HEX_FAIL; | |
} | |
x_val |= t << 4; | |
++(*pos); | |
if (*pos == end) { | |
return TTO_ESCAPE_END_FAIL; | |
} | |
t = tto_hexchar_to_val(**pos); | |
if (t > 15) { | |
return TTO_ESCAPE_BAD_HEX_FAIL; | |
} | |
x_val |= t; | |
**ret_pos = x_val; | |
return NO_ERROR; | |
} | |
ERROR tto_escape_string(const char *const str, size_t val_len, char **out) { | |
ERROR err; | |
char *ret = malloc(val_len); | |
if (!ret) return TTO_MALLOC_FAIL; | |
char *ret_pos = ret; | |
const char *const end_null = str + val_len - 1; | |
for (const char *pos = str; pos < end_null; ++pos, ++ret_pos) { | |
if (*pos == '\\') { | |
++pos; | |
if (pos == end_null) { | |
err = TTO_ESCAPE_END_FAIL; | |
goto error_handler; | |
} | |
switch (*pos) { | |
case '0': *ret_pos = '\0'; break; | |
case 'a': *ret_pos = '\a'; break; | |
case 'b': *ret_pos = '\b'; break; | |
case 'e': *ret_pos = '\x1B'; break; | |
case 'f': *ret_pos = '\f'; break; | |
case 'n': *ret_pos = '\n'; break; | |
case 'r': *ret_pos = '\r'; break; | |
case 't': *ret_pos = '\t'; break; | |
case 'v': *ret_pos = '\v'; break; | |
case 'x': | |
err = tto_escape_hex(&pos, &ret_pos, end_null); | |
if (err != NO_ERROR) goto error_handler; | |
break; | |
default: | |
*ret_pos = *pos; | |
} | |
} else { | |
*ret_pos = *pos; | |
} | |
} | |
*ret_pos = 0; | |
++ret_pos; | |
char *new_ret = realloc(ret, ret_pos - ret); | |
if (!new_ret) { | |
*out = ret; | |
} else { | |
*out = new_ret; | |
} | |
return NO_ERROR; | |
error_handler:; | |
free(ret); | |
return err; | |
} | |
//tests | |
int main() { | |
char *tests[] = { | |
"abc",// no effect | |
"ab\\c",// escape non-special characters | |
"ab\\x63",// hex escape | |
"ab\\tc",// standard escape | |
"ab\\t\\x21c",// multiple escapes | |
"ab\\\\c",// backslash escape | |
"\\\\abc",// escape at beginning | |
"ab\\\\",// escape at end | |
"\\x456",// hex followed by numbers | |
"abc\\",// incomplete | |
"abc\\x",// incomplete hex (differently) | |
"abc\\x0",// incomplete hex | |
"abc\\xO",// bad hex char | |
"abc\\0def",// null escape (printing stops at abc) | |
}; | |
const char *expects[] = { | |
"abc", | |
"abc", | |
"abc", | |
"ab\tc", | |
"ab\t!c", | |
"ab\\c", | |
"\\abc", | |
"ab\\", | |
"E6", | |
"error 9005", | |
"error 9005", | |
"error 9005", | |
"error 9007", | |
"abc" | |
}; | |
for (size_t i = 0; i < (sizeof(tests) / sizeof(char *)); ++i) { | |
printf("====test %zu:\n", i); | |
puts(tests[i]); | |
char *res; | |
ERROR err = tto_escape_string(tests[i], strlen(tests[i]) + 1, &res); | |
printf("-error:%llu\n", err); | |
if (err == NO_ERROR) puts(res); | |
else printf("error %llu\n", err); | |
puts(expects[i]); | |
if (err == NO_ERROR) free(res); | |
} | |
puts("==end"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment