Fix g_string_chunk_insert_len to accept nuls

Contrary to what the documentation says, g_string_chunk_insert_len
was stopping at the first nul. Also add a test. Fixes bug 585088.
This commit is contained in:
Matthias Clasen 2009-06-10 23:50:45 -04:00
parent 9e43937d03
commit 6224d3d2ec
2 changed files with 49 additions and 28 deletions

View File

@ -247,22 +247,22 @@ g_string_chunk_insert (GStringChunk *chunk,
* g_string_chunk_insert_const: * g_string_chunk_insert_const:
* @chunk: a #GStringChunk * @chunk: a #GStringChunk
* @string: the string to add * @string: the string to add
* *
* Adds a copy of @string to the #GStringChunk, unless the same * Adds a copy of @string to the #GStringChunk, unless the same
* string has already been added to the #GStringChunk with * string has already been added to the #GStringChunk with
* g_string_chunk_insert_const(). * g_string_chunk_insert_const().
* *
* This function is useful if you need to copy a large number * This function is useful if you need to copy a large number
* of strings but do not want to waste space storing duplicates. * of strings but do not want to waste space storing duplicates.
* But you must remember that there may be several pointers to * But you must remember that there may be several pointers to
* the same string, and so any changes made to the strings * the same string, and so any changes made to the strings
* should be done very carefully. * should be done very carefully.
* *
* Note that g_string_chunk_insert_const() will not return a * Note that g_string_chunk_insert_const() will not return a
* pointer to a string added with g_string_chunk_insert(), even * pointer to a string added with g_string_chunk_insert(), even
* if they do match. * if they do match.
* *
* Returns: a pointer to the new or existing copy of @string * Returns: a pointer to the new or existing copy of @string
* within the #GStringChunk * within the #GStringChunk
*/ */
gchar* gchar*
@ -291,26 +291,26 @@ g_string_chunk_insert_const (GStringChunk *chunk,
* g_string_chunk_insert_len: * g_string_chunk_insert_len:
* @chunk: a #GStringChunk * @chunk: a #GStringChunk
* @string: bytes to insert * @string: bytes to insert
* @len: number of bytes of @string to insert, or -1 to insert a * @len: number of bytes of @string to insert, or -1 to insert a
* nul-terminated string * nul-terminated string
* *
* Adds a copy of the first @len bytes of @string to the #GStringChunk. * Adds a copy of the first @len bytes of @string to the #GStringChunk.
* The copy is nul-terminated. * The copy is nul-terminated.
* *
* Since this function does not stop at nul bytes, it is the caller's * Since this function does not stop at nul bytes, it is the caller's
* responsibility to ensure that @string has at least @len addressable * responsibility to ensure that @string has at least @len addressable
* bytes. * bytes.
* *
* The characters in the returned string can be changed, if necessary, * The characters in the returned string can be changed, if necessary,
* though you should not change anything after the end of the string. * though you should not change anything after the end of the string.
* *
* Return value: a pointer to the copy of @string within the #GStringChunk * Return value: a pointer to the copy of @string within the #GStringChunk
* *
* Since: 2.4 * Since: 2.4
**/ */
gchar* gchar*
g_string_chunk_insert_len (GStringChunk *chunk, g_string_chunk_insert_len (GStringChunk *chunk,
const gchar *string, const gchar *string,
gssize len) gssize len)
{ {
gssize size; gssize size;
@ -322,7 +322,7 @@ g_string_chunk_insert_len (GStringChunk *chunk,
size = strlen (string); size = strlen (string);
else else
size = len; size = len;
if ((chunk->storage_next + size + 1) > chunk->this_size) if ((chunk->storage_next + size + 1) > chunk->this_size)
{ {
gsize new_size = nearest_power (chunk->default_size, size + 1); gsize new_size = nearest_power (chunk->default_size, size + 1);
@ -338,9 +338,7 @@ g_string_chunk_insert_len (GStringChunk *chunk,
*(pos + size) = '\0'; *(pos + size) = '\0';
strncpy (pos, string, size); memcpy (pos, string, size);
if (len > 0)
size = strlen (pos);
chunk->storage_next += size + 1; chunk->storage_next += size + 1;

View File

@ -49,6 +49,28 @@ test_string_chunks (void)
g_string_chunk_free (string_chunk); g_string_chunk_free (string_chunk);
} }
static void
test_string_chunk_insert (void)
{
const gchar s0[] = "Testing GStringChunk";
const gchar s1[] = "a\0b\0c\0d\0";
const gchar s2[] = "Hello, world";
GStringChunk *chunk;
gchar *str[3];
chunk = g_string_chunk_new (512);
str[0] = g_string_chunk_insert (chunk, s0);
str[1] = g_string_chunk_insert_len (chunk, s1, 8);
str[2] = g_string_chunk_insert (chunk, s2);
g_assert (memcmp (s0, str[0], sizeof s0) == 0);
g_assert (memcmp (s1, str[1], sizeof s1) == 0);
g_assert (memcmp (s2, str[2], sizeof s2) == 0);
g_string_chunk_free (chunk);
}
static void static void
test_string_new (void) test_string_new (void)
{ {
@ -376,6 +398,7 @@ main (int argc,
g_test_init (&argc, &argv, NULL); g_test_init (&argc, &argv, NULL);
g_test_add_func ("/string/test-string-chunks", test_string_chunks); g_test_add_func ("/string/test-string-chunks", test_string_chunks);
g_test_add_func ("/string/test-string-chunk-insert", test_string_chunk_insert);
g_test_add_func ("/string/test-string-new", test_string_new); g_test_add_func ("/string/test-string-new", test_string_new);
g_test_add_func ("/string/test-string-printf", test_string_printf); g_test_add_func ("/string/test-string-printf", test_string_printf);
g_test_add_func ("/string/test-string-assign", test_string_assign); g_test_add_func ("/string/test-string-assign", test_string_assign);