[gdome] copying strings from gdome2 to external code



Hi!

What is the intended way to copy a complete string from gdome2 into an
external format (e.g. std::string in C++)? The only way I could figure
out from the documentation was to iterate over the string length,
copying out the characters using gdome_xml_str_charAt. But this
approach has an algorithmic complexity of O(n^2) on most systems
because of the bounds check using strlen.

If this is in fact the intended way to do this, I would suggest to
incorporate the attached patch, which caches the string length from
gdome_xml_str_length, and uses gdome_xml_str_length instead of strlen
in all other GdomeDOMString functions. This way, string copying is
O(n) as it is supposed to be.

Also, it may be just my personal preference but I think a properly
written application could should do the bounds check by itself
anyway. So you might consider enabling the bounds check only for debug
builds, so during development programmers will still get the warning,
but in production it will run without slowdown. In this case, the
caching would not even be needed (having the advantage of keeping
binary compatibility with previous versions).

Best regards

Isidor Zeuner
diff --git a/libgdome/gdome.h b/libgdome/gdome.h
index 2566db9..a9db47d 100644
--- a/libgdome/gdome.h
+++ b/libgdome/gdome.h
@@ -94,6 +94,7 @@ struct _GdomeDOMString {
 	gchar *str;
 	gint refcnt;
 	void (*unref) (GdomeDOMString *self);
+	int cached_length;
 };
 
 typedef struct _GdomeNode GdomeNode;
diff --git a/libgdome/gdomecore/gdome-xml-str.c b/libgdome/gdomecore/gdome-xml-str.c
index bf36cb8..4bb1660 100644
--- a/libgdome/gdomecore/gdome-xml-str.c
+++ b/libgdome/gdomecore/gdome-xml-str.c
@@ -79,6 +79,7 @@ gdome_xml_str_mkref (const gchar *str) {
   ds->refcnt = 1;
 	ds->unref = gdome_xml_str_const_unref;
 	ds->str = (gchar *)str;
+	ds->cached_length = -1;
 	return ds;
 }
 
@@ -103,6 +104,7 @@ gdome_xml_str_mkref_own (gchar *str) {
 	ds->refcnt = 1;
 	ds->unref = gdome_xml_str_unref_own;
   ds->str = str;
+	ds->cached_length = -1;
 	return ds;
 }
 
@@ -128,6 +130,7 @@ gdome_xml_str_mkref_xml (xmlChar *str) {
   ds->refcnt = 1;
 	ds->unref = gdome_xml_str_unref_xml;
 	ds->str = str;
+	ds->cached_length = -1;
 	return ds;
 }
 
@@ -153,6 +156,7 @@ gdome_xml_str_mkref_dup (const gchar *str) {
 	ds->refcnt = 1;
 	ds->unref = gdome_xml_str_unref_own;
   ds->str = g_strdup(str);
+	ds->cached_length = -1;
 	return ds;
 }
 
@@ -233,7 +237,7 @@ gchar
 gdome_xml_str_charAt (GdomeDOMString *self, int index)
 {
 	g_return_val_if_fail (self != NULL, '\0');
-	if (index < 0 || index >= strlen (self->str)) {
+	if (index < 0 || index >= gdome_xml_str_length (self)) {
 		g_warning ("gdome_str_charAt: out bound error\n");
 		return '\0';
 	}
@@ -281,8 +285,8 @@ gdome_xml_str_endsWith (GdomeDOMString *self, GdomeDOMString *suffix)
 	if (suffix == NULL) {
 		return TRUE;
   }
-  len_self = strlen (self->str);
-  len_str = strlen (suffix->str);
+  len_self = gdome_xml_str_length (self);
+  len_str = gdome_xml_str_length (suffix);
 
   if (len_str > len_self)
     return FALSE;
@@ -302,7 +306,7 @@ gdome_xml_str_endsWith (GdomeDOMString *self, GdomeDOMString *suffix)
 GdomeBoolean
 gdome_xml_str_isEmpty (GdomeDOMString *self)
 {
-	if (self != NULL && strlen (self->str) > 0)
+	if (self != NULL && gdome_xml_str_length (self) > 0)
 		return FALSE;
 	return TRUE;
 }
@@ -318,7 +322,15 @@ gdome_xml_str_length (GdomeDOMString *self)
 {
   g_return_val_if_fail (self != NULL, 0);
 
-  return strlen (self->str);
+  if (
+      -1 == self->cached_length
+  ) {
+      self->cached_length = strlen(
+          self->str
+      );
+  }
+
+  return self->cached_length;
 }
 
 /**
@@ -337,8 +349,8 @@ gdome_xml_str_startsWith (GdomeDOMString *self, GdomeDOMString *prefix)
 	if (prefix == NULL) {
 		return TRUE;
   }
-  len_self = strlen (self->str);
-  len_str = strlen (prefix->str);
+  len_self = gdome_xml_str_length (self);
+  len_str = gdome_xml_str_length (prefix);
 
   if (len_str > len_self)
     return FALSE;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]