commit: r1676 - in neon/trunk: src test
joe at manyfish.co.uk
joe at manyfish.co.uk
Wed Aug 5 09:58:52 EDT 2009
Author: joe
Date: Wed Aug 5 06:58:52 2009
New Revision: 1676
Modified:
neon/trunk/src/ne_string.c
neon/trunk/src/ne_string.h
neon/trunk/test/string-tests.c
Log:
* src/ne_string.c (ne_buffer_qappend): New function.
* src/ne_string.h (ne_buffer_qappend): New prototype.
* test/string-tests.c (qappend): New test case.
Modified: neon/trunk/src/ne_string.c
==============================================================================
--- neon/trunk/src/ne_string.c (original)
+++ neon/trunk/src/ne_string.c Wed Aug 5 06:58:52 2009
@@ -1,6 +1,6 @@
/*
String utility functions
- Copyright (C) 1999-2007, Joe Orton <joe at manyfish.co.uk>
+ Copyright (C) 1999-2007, 2009, Joe Orton <joe at manyfish.co.uk>
strcasecmp/strncasecmp implementations are:
Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -252,6 +252,68 @@
buf->used = strlen(buf->data) + 1;
}
+
+/* ascii_quote[n] gives the number of bytes needed by
+ * ne_buffer_qappend() to append character 'n'. */
+static const unsigned char ascii_quote[256] = {
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
+};
+
+static const char hex_chars[16] = "0123456789ABCDEF";
+
+void ne_buffer_qappend(ne_buffer *buf, const unsigned char *data, size_t len)
+{
+ const unsigned char *p, *dend = data + len;
+ size_t needed;
+ char *q, *qs;
+
+ /* Determine the expected number of bytes needed to append the
+ * string. */
+ for (p = data, needed = 0; p < dend; p++) {
+ needed += ascii_quote[*p];
+ }
+
+ ne_buffer_grow(buf, buf->used + needed);
+
+ /* buf->used >= 1, so this is safe. */
+ qs = q = buf->data + buf->used - 1;
+
+ /* Append the string, quoting along the way. */
+ for (p = data; p < dend; p++) {
+ if (ascii_quote[*p] == 1) {
+ *q++ = *p;
+ }
+ else {
+ *q++ = '\\';
+ *q++ = 'x';
+ *q++ = hex_chars[(*p >> 4) & 0x0f];
+ *q++ = hex_chars[*p & 0x0f];
+ }
+ }
+
+ /* NUL terminate after the last character */
+ *q = '\0';
+
+ /* used already accounts for a NUL, so increment by number of
+ * characters appended, *before* the NUL. */
+ buf->used += q - qs;
+}
+
static const char b64_alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
@@ -345,9 +407,9 @@
return outp - *out;
}
-/* Character map array; array[n] = isprint(n) ? 0x20 : n. Used by
- * ne_strclean as a locale-independent isprint(). */
-static const unsigned char ascii_printable[256] = {
+/* Character map array; ascii_clean[n] = isprint(n) ? n : 0x20. Used
+ * by ne_strclean as a locale-independent isprint(). */
+static const unsigned char ascii_clean[256] = {
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
@@ -387,7 +449,7 @@
unsigned char *pnt;
for (pnt = (unsigned char *)str; *pnt; pnt++)
- *pnt = (char)ascii_printable[*pnt];
+ *pnt = (char)ascii_clean[*pnt];
return str;
}
Modified: neon/trunk/src/ne_string.h
==============================================================================
--- neon/trunk/src/ne_string.h (original)
+++ neon/trunk/src/ne_string.h Wed Aug 5 06:58:52 2009
@@ -1,6 +1,6 @@
/*
String utility functions
- Copyright (C) 1999-2008, Joe Orton <joe at manyfish.co.uk>
+ Copyright (C) 1999-2009, Joe Orton <joe at manyfish.co.uk>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -90,6 +90,11 @@
* a NUL terminator. (A NUL terminator is appended to buf) */
void ne_buffer_append(ne_buffer *buf, const char *data, size_t len);
+/* Append 'len' bytes of 'data' to buf. All non-ASCII bytes, and
+ * ASCII control characters, are escaped. (Note that this includes
+ * the NUL byte). */
+void ne_buffer_qappend(ne_buffer *buf, const unsigned char *data, size_t len);
+
/* Print a string to the end of the buffer using printf-style format
* string 'format' and subsqeuent arguments. At most 'max' characters
* are appended; the number of characters appended (excluding the NUL
Modified: neon/trunk/test/string-tests.c
==============================================================================
--- neon/trunk/test/string-tests.c (original)
+++ neon/trunk/test/string-tests.c Wed Aug 5 06:58:52 2009
@@ -1,6 +1,6 @@
/*
String handling tests
- Copyright (C) 2001-2007, Joe Orton <joe at manyfish.co.uk>
+ Copyright (C) 2001-2007, 2009, Joe Orton <joe at manyfish.co.uk>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -610,6 +610,38 @@
return OK;
}
+static int qappend(void)
+{
+ static const struct {
+ const char *in;
+ size_t inlen;
+ const char *out;
+ } ts[] = {
+ { "", 0, "" },
+ { "a", 1, "a" },
+ { "b", 2, "b\\x00" },
+ { "alpha\0alpha", 11, "alpha\\x00alpha" },
+ { "a\tb", 3, "a\\x09b" },
+ { NULL }
+ };
+ unsigned n;
+
+ for (n = 0; ts[n].in; n++) {
+ ne_buffer *buf = ne_buffer_create();
+
+ ne_buffer_qappend(buf, (const unsigned char *)ts[n].in, ts[n].inlen);
+
+ ONCMP(buf->data, ts[n].out);
+
+ ONV(strlen(buf->data) + 1 != buf->used,
+ ("bad buffer length for '%s': %" NE_FMT_SIZE_T,
+ ts[n].out, buf->used));
+
+ ne_buffer_destroy(buf);
+ }
+
+ return OK;
+}
ne_test tests[] = {
T(simple),
@@ -638,6 +670,7 @@
T(casecmp),
T(casencmp),
T(buf_print),
+ T(qappend),
T(NULL)
};
More information about the neon-commits
mailing list