string_unquote_withdelim.c (2303B)
1 /* ISC license. */ 2 3 #include <errno.h> 4 5 #include <skalibs/bytestr.h> 6 #include <skalibs/fmtscan.h> 7 #include <skalibs/skamisc.h> 8 #include <skalibs/posixishard.h> 9 10 #define PUSH0 0x40 11 #define PUSH 0x20 12 #define PUSHSPEC 0x10 13 #define STORE 0x08 14 #define CALC 0x04 15 #define SYNTAXERROR 0x02 16 #define BROKENPIPE 0x01 17 18 int string_unquote_withdelim (char *d, size_t *w, char const *s, size_t len, size_t *r, char const *delim, size_t delimlen) 19 { 20 static unsigned char const actions[5][9] = 21 { 22 { 0, 0, PUSH, PUSH, PUSH, PUSH, PUSH, PUSH, 0 }, 23 { PUSH, PUSH, 0, PUSH, PUSHSPEC, PUSH, PUSHSPEC, PUSH, BROKENPIPE }, 24 { PUSH0, PUSH0, PUSH0|PUSH, 0, PUSH0|PUSH, PUSH0|PUSH, PUSH0|PUSH, PUSH0|PUSH, PUSH0 }, 25 { SYNTAXERROR, SYNTAXERROR, STORE, SYNTAXERROR, STORE, STORE, SYNTAXERROR, SYNTAXERROR, BROKENPIPE }, 26 { SYNTAXERROR, SYNTAXERROR, CALC, SYNTAXERROR, CALC, CALC, SYNTAXERROR, SYNTAXERROR, BROKENPIPE } 27 } ; 28 static unsigned char const states[5][9] = 29 { 30 { 1, 5, 0, 0, 0, 0, 0, 0, 5 }, 31 { 0, 0, 2, 0, 0, 0, 0, 0, 6 }, 32 { 1, 5, 0, 3, 0, 0, 0, 0, 5 }, 33 { 6, 6, 4, 6, 4, 4, 6, 6, 6 }, 34 { 6, 6, 0, 6, 0, 0, 6, 6, 6 } 35 } ; 36 unsigned char class[256] = "7777777777777777777777777777777777777777777777772555555555777777777777777777777777777777777707777445554777777767776667673777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777" ; 37 size_t i = 0 ; 38 unsigned char store = 0 ; 39 unsigned char state = 0 ; 40 for (; i < delimlen ; i++) 41 if (class[(unsigned char)delim[i]] == '7') 42 class[(unsigned char)delim[i]] = '1' ; 43 else return (errno = EINVAL, 0) ; 44 *w = 0 ; 45 46 for (i = 0 ; state < 5 ; i++) 47 { 48 unsigned char c = i < len ? class[(unsigned char)s[i]] - '0' : 8 ; 49 unsigned char action = actions[state][c] ; 50 state = states[state][c] ; 51 if (action & PUSH0) d[(*w)++] = 0 ; 52 if (action & PUSH) d[(*w)++] = s[i] ; 53 if (action & PUSHSPEC) d[(*w)++] = s[i] == 's' ? ' ' : 7 + byte_chr("abtnvfr", 7, s[i]) ; 54 if (action & STORE) store = fmtscan_num(s[i], 16) << 4 ; 55 if (action & CALC) d[(*w)++] = store | fmtscan_num(s[i], 16) ; 56 if (action & SYNTAXERROR) errno = EPROTO ; 57 if (action & BROKENPIPE) errno = EPIPE ; 58 } 59 *r = i - 1 ; 60 return (state == 5) ; 61 }