diff options
Diffstat (limited to 'src/libstddjb/string_quote_nodelim_mustquote.c')
-rw-r--r-- | src/libstddjb/string_quote_nodelim_mustquote.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/libstddjb/string_quote_nodelim_mustquote.c b/src/libstddjb/string_quote_nodelim_mustquote.c new file mode 100644 index 0000000..e52bce3 --- /dev/null +++ b/src/libstddjb/string_quote_nodelim_mustquote.c @@ -0,0 +1,62 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/bytestr.h> +#include <skalibs/fmtscan.h> +#include <skalibs/stralloc.h> +#include <skalibs/skamisc.h> + +int string_quote_nodelim_mustquote (stralloc *sa, char const *s, unsigned int len, char const *delim, unsigned int delimlen) +{ + char class[256] = "dddddddaaaaaaaddddddddddddddddddcccccccccccccccceeeeeeeeeeccccccccccccccccccccccccccccccccccbcccceeeeeecccccccecccececececcccccddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" ; + + unsigned int base = sa->len ; + unsigned int i = 0 ; + int wasnull = !sa->s ; + + for (; i < delimlen ; i++) + if (class[(unsigned char)delim[i]] == 'c') + class[(unsigned char)delim[i]] = 'b' ; + else return (errno = EINVAL, 0) ; + + for (i = 0 ; i < len ; i++) + { + switch (class[(unsigned char)s[i]]) + { + case 'a' : + { + static char const tab[7] = "abtnvfr" ; + char fmt[2] = "\\" ; + fmt[1] = tab[s[i] - 7] ; + if (!stralloc_catb(sa, fmt, 2)) goto err ; + break ; + } + case 'b' : + { + char fmt[2] = "\\" ; + fmt[1] = s[i] ; + if (!stralloc_catb(sa, fmt, 2)) goto err ; + break ; + } + case 'c' : + case 'e' : + { + if (!stralloc_catb(sa, s+i, 1)) goto err ; + break ; + } + case 'd' : + { + char fmt[5] = "\\0x" ; + ucharn_fmt(fmt+3, s+i, 1) ; + if (!stralloc_catb(sa, fmt, 5)) goto err ; + break ; + } + default : errno = EFAULT ; goto err ; /* can't happen */ + } + } + return 1 ; + + err: + if (wasnull) stralloc_free(sa) ; else sa->len = base ; + return 0 ; +} |