#50209 - need a G_TYPE_ for nun-nul terminated strings
- From: Owen Taylor <otaylor redhat com>
- To: timj gtk org
- Cc: gtk-devel-list gnome org
- Subject: #50209 - need a G_TYPE_ for nun-nul terminated strings
- Date: 27 Mar 2001 19:36:54 -0500
Text of bug
===
Some signals have string arguments that are not nul-terminated;
instead, a length is passed in. This breaks because G_TYPE_STRING
assumes nul termination and copies the string with g_strdup().
As with boxed types, we need to be able to pass a string to a signal
without copying it; e.g. insert_text can take extremely long strings,
which would be quite a performance hit to copy.
===
Currently, GtkEntry, GtkOldeditable just copy the text and nul-terminate.
GtkText uses G_TYPE_STRING for a potentially non-nul terminated
string.
I took a stab at an implementation of a G_TYPE_BYTES to fix
this; I'm not completely happy with the result, for two
reasons:
- It doesn't seem really seem that general purpose.
- It reintroduces arguments collected as multiple arguments,
which it was sort of nice to avoid. (The glib-genmarshal.c
changes are, in particularly fairly hacky for this reason)
Its possible that simply eating the copying hit is OK, though
Havoc points out, the text here could be an entire document.
My patch follows. The extra API, along with G_TYPE_BYTES, is:
===
void g_value_set_bytes (GValue *value,
const gchar *v_string,
guint v_length);
void g_value_set_static_bytes (GValue *value,
const gchar *v_string,
guint v_length);
G_CONST_RETURN gchar *g_value_get_bytes_str (GValue *value);
guint g_value_get_bytes_len (GValue *value);
void g_value_dup_bytes (GValue *value,
gchar **v_string,
guint *v_length);
===
Most likely g_value_dup_bytes should be replaced with
g_value_dup_bytes_str() to match g_value_get_bytes_str(). Probably
str/len should be spelled out. Possible guint here should be gint and
it should support -1 == nul-terminated.
Regards,
Owen
Index: glib-genmarshal.c
===================================================================
RCS file: /cvs/gnome/glib/gobject/glib-genmarshal.c,v
retrieving revision 1.7
diff -u -r1.7 glib-genmarshal.c
--- glib-genmarshal.c 2001/03/09 14:02:30 1.7
+++ glib-genmarshal.c 2001/03/28 00:33:16
@@ -128,7 +128,9 @@
static gboolean skip_ploc = FALSE;
static gboolean std_includes = TRUE;
+static const gchar bytes_ctype[] = "gpointer,gint";
+
/* --- functions --- */
static gboolean
complete_in_arg (InArgument *iarg)
@@ -148,6 +150,7 @@
{ "FLOAT", "FLOAT", "gfloat", "g_value_get_float", },
{ "DOUBLE", "DOUBLE", "gdouble", "g_value_get_double", },
{ "STRING", "STRING", "gpointer", "(char*) g_value_get_string", },
+ { "BYTES", "BYTES", bytes_ctype, NULL, }, /* Special cased */
{ "PARAM", "PARAM", "gpointer", "g_value_get_param", },
{ "BOXED", "BOXED", "gpointer", "g_value_get_boxed", },
{ "POINTER", "POINTER", "gpointer", "g_value_get_pointer", },
@@ -319,7 +322,7 @@
}
if (gen_cbody && !have_std_marshaller)
{
- /* cfile marhsal header */
+ /* cfile marshal header */
fprintf (fout, "void\n");
ind = fprintf (fout, "%s_%s (", marshaller_prefix, signame);
fprintf (fout, "GClosure *closure,\n");
@@ -339,6 +342,11 @@
if (iarg->getter)
fprintf (fout, "%s%s arg_%d,\n", indent (ind), pad (iarg->ctype), a++);
+ else if (iarg->ctype == bytes_ctype)
+ {
+ fprintf (fout, "%s%s arg_%d,\n", indent (ind), pad ("gpointer"), a);
+ fprintf (fout, "%s%s arg_%d,\n", indent (ind), pad ("gint"), a++);
+ }
}
fprintf (fout, "%s%s data2);\n", indent (ind), pad ("gpointer"));
@@ -361,7 +369,7 @@
{
InArgument *iarg = node->data;
- if (iarg->getter)
+ if (iarg->getter || iarg->ctype == bytes_ctype)
a++;
}
fprintf (fout, " g_return_if_fail (n_param_values == %u);\n", 1 + a);
@@ -389,6 +397,11 @@
if (iarg->getter)
fprintf (fout, "%s%s (param_values + %d),\n", indent (ind), iarg->getter, a++);
+ else if (iarg->ctype == bytes_ctype)
+ {
+ fprintf (fout, "%s(gchar *)g_value_get_bytes_str (param_values + %d),\n", indent (ind), a);
+ fprintf (fout, "%sg_value_get_bytes_len (param_values + %d),\n", indent (ind), a++);
+ }
}
fprintf (fout, "%sdata2);\n", indent (ind));
Index: gtype.h
===================================================================
RCS file: /cvs/gnome/glib/gobject/gtype.h,v
retrieving revision 1.24
diff -u -r1.24 gtype.h
--- gtype.h 2001/03/18 04:44:37 1.24
+++ gtype.h 2001/03/28 00:33:16
@@ -55,6 +55,7 @@
G_TYPE_FLOAT,
G_TYPE_DOUBLE,
G_TYPE_STRING,
+ G_TYPE_BYTES,
G_TYPE_POINTER,
G_TYPE_BOXED,
G_TYPE_PARAM,
@@ -89,7 +90,8 @@
G_TYPE_PARAM_POINTER = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 15),
G_TYPE_PARAM_VALUE_ARRAY = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 16),
G_TYPE_PARAM_CLOSURE = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 17),
- G_TYPE_PARAM_OBJECT = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 18)
+ G_TYPE_PARAM_OBJECT = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 18),
+ G_TYPE_PARAM_UNICHAR = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 19)
} GTypeFundamentals;
Index: gvaluetypes.c
===================================================================
RCS file: /cvs/gnome/glib/gobject/gvaluetypes.c,v
retrieving revision 1.11
diff -u -r1.11 gvaluetypes.c
--- gvaluetypes.c 2001/03/18 04:44:38 1.11
+++ gvaluetypes.c 2001/03/28 00:33:16
@@ -269,6 +269,82 @@
}
static void
+value_init_bytes (GValue *value)
+{
+ value->data[0].v_pointer = NULL;
+ value->data[1].v_uint = 0;
+ value->data[2].v_uint = 0;
+}
+
+static void
+value_free_bytes (GValue *value)
+{
+ if (!(value->data[2].v_uint & G_VALUE_NOCOPY_CONTENTS))
+ g_free (value->data[0].v_pointer);
+}
+
+static void
+value_copy_bytes (const GValue *src_value,
+ GValue *dest_value)
+{
+ dest_value->data[0].v_pointer = g_memdup (src_value->data[0].v_pointer, src_value->data[1].v_uint);
+ dest_value->data[1].v_uint = src_value->data[1].v_uint;
+ dest_value->data[2].v_uint = 0;
+}
+
+static gchar*
+value_collect_bytes (GValue *value,
+ guint n_collect_values,
+ GTypeCValue *collect_values,
+ guint collect_flags)
+{
+ if (!collect_values[0].v_pointer)
+ {
+ value->data[0].v_pointer = NULL;
+ value->data[1].v_uint = 0;
+ }
+ else
+ {
+ if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+ {
+ value->data[0].v_pointer = collect_values[0].v_pointer;
+ value->data[2].v_uint = G_VALUE_NOCOPY_CONTENTS;
+ }
+ else
+ {
+ value->data[0].v_pointer = g_memdup (collect_values[0].v_pointer, collect_values[1].v_int);
+ value->data[2].v_uint = 0;
+ }
+
+ value->data[1].v_uint = collect_values[1].v_int;
+ }
+
+ return NULL;
+}
+
+static gchar*
+value_lcopy_bytes (const GValue *value,
+ guint n_collect_values,
+ GTypeCValue *collect_values,
+ guint collect_flags)
+{
+ gchar **string_p = collect_values[0].v_pointer;
+ guint *uint_p = collect_values[1].v_pointer;
+
+ if (!string_p || !uint_p)
+ return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
+
+ if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+ *string_p = value->data[0].v_pointer;
+ else
+ *string_p = g_memdup (value->data[0].v_pointer, value->data[1].v_uint);
+
+ *uint_p = value->data[1].v_uint;
+
+ return NULL;
+}
+
+static void
value_init_pointer (GValue *value)
{
value->data[0].v_pointer = NULL;
@@ -466,6 +542,24 @@
g_assert (type == G_TYPE_STRING);
}
+ /* G_TYPE_BYTES
+ */
+ {
+ static const GTypeValueTable value_table = {
+ value_init_bytes, /* value_init */
+ value_free_bytes, /* value_free */
+ value_copy_bytes, /* value_copy */
+ NULL, /* value_peek_pointer */
+ "pi", /* collect_format */
+ value_collect_bytes, /* collect_value */
+ "pp", /* lcopy_format */
+ value_lcopy_bytes, /* lcopy_value */
+ };
+ info.value_table = &value_table;
+ type = g_type_register_fundamental (G_TYPE_BYTES, "gbytes", &info, &finfo, 0);
+ g_assert (type == G_TYPE_POINTER);
+ }
+
/* G_TYPE_POINTER
*/
{
Index: gvaluetypes.h
===================================================================
RCS file: /cvs/gnome/glib/gobject/gvaluetypes.h,v
retrieving revision 1.10
diff -u -r1.10 gvaluetypes.h
--- gvaluetypes.h 2001/03/18 04:44:38 1.10
+++ gvaluetypes.h 2001/03/28 00:33:17
@@ -37,6 +37,7 @@
#define G_VALUE_HOLDS_FLOAT(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_FLOAT))
#define G_VALUE_HOLDS_DOUBLE(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_DOUBLE))
#define G_VALUE_HOLDS_STRING(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_STRING))
+#define G_VALUE_HOLDS_BYTES(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_BYTES))
#define G_VALUE_HOLDS_POINTER(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_POINTER))
@@ -74,5 +75,21 @@
const gchar *v_string);
G_CONST_RETURN gchar* g_value_get_string (const GValue *value);
gchar* g_value_dup_string (const GValue *value);
+
+void g_value_set_bytes (GValue *value,
+ const gchar *v_string,
+ guint v_length);
+void g_value_set_static_bytes (GValue *value,
+ const gchar *v_string,
+ guint v_length);
+G_CONST_RETURN gchar *g_value_get_bytes_str (GValue *value);
+guint g_value_get_bytes_len (GValue *value);
+void g_value_dup_bytes (GValue *value,
+ gchar **v_string,
+ guint *v_length);
+
void g_value_set_pointer (GValue *value,
gpointer v_pointer);
gpointer g_value_get_pointer (const GValue *value);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]