diff options
author | Guillem Jover <guillem@hadrons.org> | 2009-10-24 00:15:57 +0200 |
---|---|---|
committer | Guillem Jover <guillem@hadrons.org> | 2009-10-24 01:47:26 +0200 |
commit | 04250f6a7c3e2d22a9861b82615329e1dc328c93 (patch) | |
tree | 9f7fb5d273f6b490f13c1f7d5b3c154f744eca3f | |
parent | 5c078ce2f581e1bdfc918326051c587e0cb1d0d6 (diff) | |
download | libbsd-04250f6a7c3e2d22a9861b82615329e1dc328c93.tar.gz |
Add strnvis and strnunvis functions
Taken from OpenBSD.
-rw-r--r-- | Versions | 3 | ||||
-rw-r--r-- | include/vis.h | 2 | ||||
-rw-r--r-- | src/unvis.c | 41 | ||||
-rw-r--r-- | src/vis.c | 61 |
4 files changed, 105 insertions, 2 deletions
@@ -44,5 +44,8 @@ LIBBSD_0.1 { LIBBSD_0.2 { strtonum; + + strnvis; + strnunvis; } LIBBSD_0.1; diff --git a/include/vis.h b/include/vis.h index 84de6fc..835d2d6 100644 --- a/include/vis.h +++ b/include/vis.h @@ -78,8 +78,10 @@ __BEGIN_DECLS char *vis(char *, int, int, int); int strvis(char *, const char *, int); int strvisx(char *, const char *, size_t, int); +int strnvis(char *, const char *, size_t, int); int strunvis(char *, const char *); int strunvisx(char *, const char *, int); +ssize_t strnunvis(char *, const char *, size_t); int unvis(char *, int, int *, int); __END_DECLS diff --git a/src/unvis.c b/src/unvis.c index 66d74a5..188edca 100644 --- a/src/unvis.c +++ b/src/unvis.c @@ -257,6 +257,47 @@ strunvis(char *dst, const char *src) return (dst - start); } +ssize_t +strnunvis(char *dst, const char *src, size_t sz) +{ + char c, p; + char *start = dst, *end = dst + sz - 1; + int state = 0; + + if (sz > 0) + *end = '\0'; + while ((c = *src++)) { + again: + switch (unvis(&p, c, &state, 0)) { + case UNVIS_VALID: + if (dst < end) + *dst = p; + dst++; + break; + case UNVIS_VALIDPUSH: + if (dst < end) + *dst = p; + dst++; + goto again; + case 0: + case UNVIS_NOCHAR: + break; + default: + if (dst <= end) + *dst = '\0'; + return (-1); + } + } + if (unvis(&p, c, &state, UNVIS_END) == UNVIS_VALID) { + if (dst < end) + *dst = p; + dst++; + } + if (dst <= end) + *dst = '\0'; + return (dst - start); +} + int strunvisx(char *dst, const char *src, int flag) { @@ -1,3 +1,4 @@ +/* $OpenBSD: vis.c,v 1.18 2005/08/29 18:38:41 otto Exp $ */ /*- * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -30,10 +31,20 @@ #include <sys/types.h> #include <limits.h> #include <ctype.h> -#include <stdio.h> +#include <string.h> #include <vis.h> #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') +#define isvisible(c) \ + (((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) && \ + (((c) != '*' && (c) != '?' && (c) != '[' && (c) != '#') || \ + (flag & VIS_GLOB) == 0) && isgraph((u_char)(c))) || \ + ((flag & VIS_SP) == 0 && (c) == ' ') || \ + ((flag & VIS_TAB) == 0 && (c) == '\t') || \ + ((flag & VIS_NL) == 0 && (c) == '\n') || \ + ((flag & VIS_SAFE) && ((c) == '\b' || \ + (c) == '\007' || (c) == '\r' || \ + isgraph((u_char)(c))))) /* * vis - visually encode characters @@ -149,12 +160,15 @@ done: } /* - * strvis, strvisx - visually encode characters from src into dst + * strvis, strnvis, strvisx - visually encode characters from src into dst * * Dst must be 4 times the size of src to account for possible * expansion. The length of dst, not including the trailing NUL, * is returned. * + * Strnvis will write no more than siz-1 bytes (and will NULL terminate). + * The number of bytes needed to fully encode the string is returned. + * * Strvisx encodes exactly len bytes from src into dst. * This is useful for encoding a block of data. */ @@ -174,6 +188,49 @@ strvis(dst, src, flag) } int +strnvis(char *dst, const char *src, size_t siz, int flag) +{ + char *start, *end; + char tbuf[5]; + int c, i; + + i = 0; + for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) { + if (isvisible(c)) { + i = 1; + *dst++ = c; + if (c == '\\' && (flag & VIS_NOSLASH) == 0) { + /* need space for the extra '\\' */ + if (dst < end) + *dst++ = '\\'; + else { + dst--; + i = 2; + break; + } + } + src++; + } else { + i = vis(tbuf, c, flag, *++src) - tbuf; + if (dst + i <= end) { + memcpy(dst, tbuf, i); + dst += i; + } else { + src--; + break; + } + } + } + if (siz > 0) + *dst = '\0'; + if (dst + i > end) { + /* adjust return value for truncation */ + while ((c = *src)) + dst += vis(tbuf, c, flag, *++src) - tbuf; + } + return (dst - start); +} + strvisx(dst, src, len, flag) char *dst; const char *src; |