diff options
| author | Andre Weissflog <floooh@gmail.com> | 2018-10-17 14:52:10 +0200 |
|---|---|---|
| committer | Andre Weissflog <floooh@gmail.com> | 2018-10-17 14:52:10 +0200 |
| commit | e98796b7731ddfd5d921b0f89126ed8d1d6a05b1 (patch) | |
| tree | 190d71993022348a32d19fdf5f20dc40cd99d997 | |
| parent | 656f085c11bccc602db6514470adcc23b3845d71 (diff) | |
sokol-args: escape sequences
| -rw-r--r-- | sokol_args.h | 55 |
1 files changed, 43 insertions, 12 deletions
diff --git a/sokol_args.h b/sokol_args.h index ab601fed..87247d67 100644 --- a/sokol_args.h +++ b/sokol_args.h @@ -36,13 +36,7 @@ The value string can contain the following escape sequences: \\ - escape '\' - \= - escape '=' - \: - escape ':' - \" - escape '"' - \' - escape ''' \n, \r, \t - newline, carriage return and tab - \[space] - escape a space character - \[number] - a decimal number (must fit in a byte) Any spaces between the end of key and the start of value are stripped. @@ -215,6 +209,7 @@ typedef struct { bool valid; uint32_t parse_state; char quote; /* current quote char, 0 if not in a quote */ + bool in_escape; /* currently in an escape sequence */ } _sargs_state; static _sargs_state _sargs; @@ -312,6 +307,32 @@ _SOKOL_PRIVATE void _sargs_end_val(void) { _sargs.parse_state = 0; } +_SOKOL_PRIVATE bool _sargs_is_escape(char c) { + return '\\' == c; +} + +_SOKOL_PRIVATE void _sargs_start_escape(void) { + _sargs.in_escape = true; +} + +_SOKOL_PRIVATE bool _sargs_in_escape(void) { + return _sargs.in_escape; +} + +_SOKOL_PRIVATE char _sargs_escape(char c) { + switch (c) { + case 'n': return '\n'; + case 't': return '\t'; + case 'r': return '\r'; + case '\\': return '\\'; + default: return c; + } +} + +_SOKOL_PRIVATE void _sargs_end_escape(void) { + _sargs.in_escape = false; +} + _SOKOL_PRIVATE bool _sargs_parsing_val(void) { return 0 != (_sargs.parse_state & _SARGS_PARSING_VAL); } @@ -319,9 +340,17 @@ _SOKOL_PRIVATE bool _sargs_parsing_val(void) { _SOKOL_PRIVATE bool _sargs_parse_carg(const char* src) { char c; while (0 != (c = *src++)) { + if (_sargs_in_escape()) { + c = _sargs_escape(c); + _sargs_end_escape(); + } + else if (_sargs_is_escape(c)) { + _sargs_start_escape(); + continue; + } if (_sargs_any_expected()) { - /* find start of key or value */ if (!_sargs_is_whitespace(c)) { + /* start of key, value or separator */ if (_sargs_key_expected()) { /* start of new key */ _sargs_start_key(); @@ -349,6 +378,7 @@ _SOKOL_PRIVATE bool _sargs_parse_carg(const char* src) { } else if (_sargs_parsing_key()) { if (_sargs_is_whitespace(c) || _sargs_is_separator(c)) { + /* end of key string */ _sargs_end_key(); if (_sargs_is_separator(c)) { _sargs_expect_val(); @@ -361,6 +391,9 @@ _SOKOL_PRIVATE bool _sargs_parse_carg(const char* src) { } else if (_sargs_parsing_val()) { if (_sargs_in_quotes()) { + /* when in quotes, whitespace is a normal character + and a matching quote ends the value string + */ if (_sargs_is_quote(c)) { _sargs_end_quote(); _sargs_end_val(); @@ -369,20 +402,19 @@ _SOKOL_PRIVATE bool _sargs_parse_carg(const char* src) { } } else if (_sargs_is_whitespace(c)) { + /* end of value string (no quotes) */ _sargs_end_val(); _sargs_expect_key(); continue; } } - if (c >= 32) { - _sargs_putc(c); - } + _sargs_putc(c); } if (_sargs_parsing_key()) { _sargs_end_key(); _sargs_expect_sep(); } - else if (_sargs_parsing_val()) { + else if (_sargs_parsing_val() && !_sargs_in_quotes()) { _sargs_end_val(); _sargs_expect_key(); } @@ -416,7 +448,6 @@ void sargs_setup(const sargs_desc* desc) { /* the first character in buf is reserved and always zero, this is the 'empty string' */ _sargs.buf_pos = 1; _sargs_parse_cargs(desc->argc, desc->argv); - /* FIXME: parse args */ _sargs.valid = true; } |