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