Add strnvis and strnunvis functions Taken from OpenBSD.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
diff --git a/Versions b/Versions
index 271839d..3e99cf4 100644
--- a/Versions
+++ b/Versions
@@ -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)
{
diff --git a/src/vis.c b/src/vis.c
index 4ad31d5..189fde8 100644
--- a/src/vis.c
+++ b/src/vis.c
@@ -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;