[goffice] GOString: move from Gnumeric to here.
- From: Morten Welinder <mortenw src gnome org>
- To: svn-commits-list gnome org
- Subject: [goffice] GOString: move from Gnumeric to here.
- Date: Mon, 15 Jun 2009 17:14:33 -0400 (EDT)
commit 11b445c6eb4c9ec627d0a53a66616814be3461e2
Author: Morten Welinder <terra gnome org>
Date: Mon Jun 15 17:00:11 2009 -0400
GOString: move from Gnumeric to here.
goffice/app/go-conf-gconf.c | 2 +-
goffice/goffice.c | 4 +-
goffice/utils/Makefile.am | 2 +
goffice/utils/go-string.c | 555 +++++++++++++++++++++++++++++++++++++++++
goffice/utils/go-string.h | 80 ++++++
goffice/utils/goffice-utils.h | 2 +
6 files changed, 643 insertions(+), 2 deletions(-)
---
diff --git a/goffice/app/go-conf-gconf.c b/goffice/app/go-conf-gconf.c
index 19222f0..3c42d65 100644
--- a/goffice/app/go-conf-gconf.c
+++ b/goffice/app/go-conf-gconf.c
@@ -10,7 +10,7 @@ struct _GOConfNode {
static GConfClient *gconf_client = NULL;
void
-go_conf_init ()
+go_conf_init (void)
{
if (!gconf_client)
gconf_client = gconf_client_get_default ();
diff --git a/goffice/goffice.c b/goffice/goffice.c
index dc264d9..ee8709d 100644
--- a/goffice/goffice.c
+++ b/goffice/goffice.c
@@ -86,7 +86,7 @@ go_sys_lib_dir (void)
}
void
-libgoffice_init ()
+libgoffice_init (void)
{
static gboolean initialized = FALSE;
@@ -121,6 +121,7 @@ libgoffice_init ()
bindtextdomain (GETTEXT_PACKAGE, libgoffice_locale_dir);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
g_type_init ();
+ _go_string_init ();
go_conf_init ();
go_fonts_init ();
go_math_init ();
@@ -171,6 +172,7 @@ libgoffice_shutdown (void)
gog_plugin_services_shutdown ();
go_currency_date_format_shutdown ();
go_number_format_shutdown ();
+ _go_string_shutdown ();
#ifdef G_OS_WIN32
/* const_cast, we created these above */
g_free ((char *)libgoffice_data_dir);
diff --git a/goffice/utils/Makefile.am b/goffice/utils/Makefile.am
index 2848224..96bc198 100644
--- a/goffice/utils/Makefile.am
+++ b/goffice/utils/Makefile.am
@@ -18,6 +18,7 @@ libgoffice_utils_la_SOURCES = \
go-path.c \
go-pattern.c \
go-geometry.c \
+ go-string.c \
go-undo.c \
datetime.c \
formats.c \
@@ -49,6 +50,7 @@ libgoffice_utils_la_HEADERS = \
go-pattern.h \
go-units.h \
go-geometry.h \
+ go-string.h \
go-undo.h \
datetime.h \
go-format.h \
diff --git a/goffice/utils/go-string.c b/goffice/utils/go-string.c
new file mode 100644
index 0000000..817dc7f
--- /dev/null
+++ b/goffice/utils/go-string.c
@@ -0,0 +1,555 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * go-string.c : ref counted shared strings with richtext and phonetic support
+ *
+ * Copyright (C) 2008 Jody Goldberg (jody gnome org)
+ * Copyright (C) 2007-2008 Morten Welinder (terra gnome org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include <goffice/goffice-config.h>
+#include <goffice/goffice.h>
+#include <gsf/gsf-utils.h>
+#include <string.h>
+
+typedef struct {
+ GOString base;
+ guint32 hash;
+ guint32 flags; /* len in bytes (not characters) */
+ guint32 ref_count;
+} GOStringImpl;
+typedef struct _GOStringRichImpl {
+ GOStringImpl base;
+ PangoAttrList *markup;
+ GOStringPhonetic *phonetic;
+} GOStringRichImpl;
+
+#define GO_STRING_HAS_CASEFOLD (1u << 31)
+#define GO_STRING_HAS_COLLATE (1u << 30)
+#define GO_STRING_IS_RICH (1u << 29)
+#define GO_STRING_IS_SHARED (1u << 28) /* rich strings share this base */
+#define GO_STRING_IS_DEPENDENT (1u << 27) /* a rich string that shares an underlying */
+
+/* mask off just the len */
+#define GO_STRING_LEN(s) (((GOStringImpl const *)(s))->flags & ((1u << 27) - 1u))
+
+/* Collection of unique strings
+ * : GOStringImpl.base.hash -> GOStringImpl * */
+static GHashTable *go_strings_base;
+
+/* Collection of gslist keyed the basic string
+ * : str (directly on the pointer) -> GSList of GOStringRichImpl */
+static GHashTable *go_strings_shared;
+
+static inline GOStringImpl *
+go_string_impl_new (char const *str, guint32 hash, guint32 flags, guint32 ref_count)
+{
+ GOStringImpl *res = g_slice_new (GOStringImpl);
+ res->base.str = str;
+ res->hash = hash;
+ res->flags = flags;
+ res->ref_count = ref_count;
+ g_hash_table_replace (go_strings_base, res, res);
+ return res;
+}
+
+static void
+go_string_phonetic_unref (GOStringPhonetic *phonetic)
+{
+ /* TODO */
+}
+
+static GOString *
+replace_rich_base_with_plain (GOStringRichImpl *rich)
+{
+ GOStringImpl *res = go_string_impl_new (rich->base.base.str, rich->base.hash,
+ (rich->base.flags & (~GO_STRING_IS_RICH)) | GO_STRING_IS_SHARED, 2);
+
+ rich->base.flags |= GO_STRING_IS_DEPENDENT;
+ if ((rich->base.flags & GO_STRING_IS_SHARED)) {
+ GSList *shares = g_hash_table_lookup (go_strings_shared, res->base.str);
+ unsigned n = g_slist_length (shares);
+ g_assert (rich->base.ref_count > n);
+ rich->base.flags &= ~GO_STRING_IS_SHARED;
+ rich->base.ref_count -= n;
+ res->ref_count += n;
+ /* ignore result, assignment is just to make the compiler shutup */
+ shares = g_slist_insert (shares, res, 1);
+ } else
+ g_hash_table_insert (go_strings_shared, (gpointer) res->base.str,
+ g_slist_prepend (NULL, rich));
+
+ return &res->base;
+}
+
+/**
+ * go_string_new_len :
+ * @str : string (optionally %NULL)
+ * @len : guint32
+ *
+ * GOString duplicates @str if no string already exists.
+ *
+ * Returns: a reference to a #GOString containing @str, or %NULL if @str is NULL
+ **/
+GOString *
+go_string_new_len (char const *str, guint32 len)
+{
+ GOStringImpl key, *res;
+
+ if (NULL == str)
+ return NULL;
+
+ key.base.str = str;
+ key.flags = len;
+ key.hash = g_str_hash (str);
+ res = g_hash_table_lookup (go_strings_base, &key);
+ if (NULL == res) {
+ /* Copy str */
+ res = go_string_impl_new (g_strndup (str, len),
+ key.hash, key.flags, 1);
+ return &res->base;
+ } else if (G_UNLIKELY (res->flags & GO_STRING_IS_RICH))
+ /* if rich was there first move it to the shared */
+ return replace_rich_base_with_plain ((GOStringRichImpl *)res);
+ else
+ return go_string_ref (&res->base);
+}
+
+/**
+ * go_string_new_nocopy :
+ * @str : string (optionally %NULL)
+ * @len : guint32
+ *
+ * GOString takes ownership of @str
+ *
+ * Returns: a reference to a #GOString containing @str
+ **/
+GOString *
+go_string_new_nocopy_len (char *str, guint32 len)
+{
+ GOStringImpl key, *res;
+
+ if (NULL == str)
+ return NULL;
+
+ key.base.str = str;
+ key.flags = len;
+ key.hash = g_str_hash (str);
+ res = g_hash_table_lookup (go_strings_base, &key);
+ if (NULL == res) {
+ /* NO copy str */
+ res = go_string_impl_new (str, key.hash, key.flags, 1);
+ return &res->base;
+ }
+
+ if (str != res->base.str) g_free (str); /* Be extra careful */
+
+ /* if rich was there first move it to the shared */
+ if (G_UNLIKELY (res->flags & GO_STRING_IS_RICH))
+ return replace_rich_base_with_plain ((GOStringRichImpl *)res);
+
+ return go_string_ref (&res->base);
+}
+
+/**
+ * go_string_new :
+ * @str : string (optionally %NULL)
+ *
+ * GOString duplicates @str if no string already exists.
+ *
+ * Returns: a reference to a #GOString containing @str, or %NULL if @str is NULL
+ **/
+GOString *
+go_string_new (char const *str)
+{
+ return str ? go_string_new_len (str, strlen (str)) : NULL;
+}
+
+/**
+ * go_string_new_nocopy :
+ * @str : string
+ *
+ * GOString takes ownership of @str
+ *
+ * Returns: a reference to a #GOString containing @str
+ **/
+GOString *
+go_string_new_nocopy (char *str)
+{
+ return str ? go_string_new_nocopy_len (str, strlen (str)) : NULL;
+}
+
+/**
+ * go_string_new_rich :
+ * @str :
+ * @len : < 0 will call strlen
+ * @copy : %TRUE @str should be copied when adding to the string table.
+ * @markup : optionally %NULL list, GOString steals the ref
+ * @phonetic : optionally %NULL list of phonetic extensions, GOString steals the ref.
+ *
+ * Returns : a string.
+ **/
+GOString *
+go_string_new_rich (char const *str,
+ int len,
+ gboolean copy,
+ PangoAttrList *markup,
+ GOStringPhonetic *phonetic)
+{
+ GOStringImpl *base;
+ GOStringRichImpl *rich;
+
+ if (NULL == str) {
+ if (NULL != markup) pango_attr_list_unref (markup);
+ if (NULL != phonetic) go_string_phonetic_unref (phonetic);
+ return NULL;
+ }
+
+ /* TODO : when we use a better representation for attributes (eg array
+ * of GOFont indicies) look into sharing rich strings */
+
+ rich = g_slice_new (GOStringRichImpl);
+ rich->base.base.str = str;
+ rich->base.hash = g_str_hash (str);
+ rich->base.flags = ((len > 0) ? (guint32) len : strlen (str)) | GO_STRING_IS_RICH;
+ rich->base.ref_count = 1;
+ rich->markup = markup;
+ rich->phonetic = phonetic;
+ base = g_hash_table_lookup (go_strings_base, rich);
+ if (NULL == base) {
+ if (copy) rich->base.base.str = g_strndup (str, len);
+ g_hash_table_insert (go_strings_base, rich, rich);
+ } else {
+ go_string_ref (&base->base);
+ if (str != rich->base.base.str) { /* watch for people doing something stupid */
+ if (!copy) g_free ((char *)str);
+ rich->base.base.str = base->base.str;
+ }
+ rich->base.flags |= GO_STRING_IS_DEPENDENT;
+ if ((base->flags & GO_STRING_IS_SHARED)) {
+ GSList *shares = g_hash_table_lookup (go_strings_shared, rich->base.base.str);
+ /* ignore result, assignment is just to make the compiler shutup */
+ shares = g_slist_insert (shares, rich, 1);
+ } else {
+ base->flags |= GO_STRING_IS_SHARED;
+ g_hash_table_insert (go_strings_shared, (gpointer) rich->base.base.str,
+ g_slist_prepend (NULL, rich));
+ }
+ }
+
+ return &rich->base.base;
+}
+
+GOString *
+go_string_ref (GOString *gstr)
+{
+ if (NULL != gstr)
+ ((GOStringImpl *)gstr)->ref_count++;
+ return gstr;
+}
+
+void
+go_string_unref (GOString *gstr)
+{
+ GOStringImpl *impl = (GOStringImpl *)gstr;
+ if (NULL == gstr)
+ return;
+
+ g_return_if_fail (impl->ref_count > 0);
+
+ if ((--(impl->ref_count)) == 0) {
+ /* polite assertion failure */
+ g_return_if_fail (!(impl->flags & GO_STRING_IS_SHARED));
+
+ if ((impl->flags & GO_STRING_IS_RICH)) {
+ GOStringRichImpl *rich = (GOStringRichImpl *)gstr;
+ if (NULL != rich->markup) pango_attr_list_unref (rich->markup);
+ if (NULL != rich->phonetic) go_string_phonetic_unref (rich->phonetic);
+ }
+
+ if (G_UNLIKELY (impl->flags & GO_STRING_IS_DEPENDENT)) {
+ GOStringImpl *base = g_hash_table_lookup (go_strings_base, gstr);
+ GSList *shares = g_hash_table_lookup (go_strings_shared, gstr->str);
+ GSList *new_shares = g_slist_remove (shares, gstr);
+ if (new_shares != shares) {
+ if (new_shares == NULL) {
+ base->flags &= ~GO_STRING_IS_SHARED;
+ g_hash_table_remove (go_strings_shared, gstr->str);
+ } else
+ g_hash_table_replace (go_strings_shared, (gpointer)gstr->str, new_shares);
+ }
+ go_string_unref (&base->base);
+ } else {
+ g_hash_table_remove (go_strings_base, gstr);
+ g_free ((gpointer)gstr->str);
+ }
+ g_slice_free1 (sizeof (GOStringImpl), gstr);
+ }
+}
+
+unsigned int
+go_string_get_ref_count (GOString const *gstr)
+{
+ return gstr ? ((GOStringImpl const *)gstr)->ref_count : 0;
+}
+
+guint32
+go_string_hash (gconstpointer gstr)
+{
+ return gstr ? ((GOStringImpl const *)gstr)->hash : 0;
+}
+
+int
+go_string_cmp (gconstpointer gstr_a, gconstpointer gstr_b)
+{
+ return (gstr_a == gstr_b)
+ ? 0
+ : strcmp (go_string_get_collation (gstr_a),
+ go_string_get_collation (gstr_b));
+}
+
+int
+go_string_cmp_ignorecase (gconstpointer gstr_a, gconstpointer gstr_b)
+{
+ return (gstr_a == gstr_b)
+ ? 0
+ : strcmp (go_string_get_casefold (gstr_a),
+ go_string_get_casefold (gstr_b));
+}
+
+gboolean
+go_string_equal (gconstpointer gstr_a, gconstpointer gstr_b)
+{
+ GOString const *a = gstr_a;
+ GOString const *b = gstr_b;
+ return a == b || (NULL != a && NULL != b && a->str == b->str);
+}
+
+static void
+go_string_impl_append_extra (GOStringImpl *gstri, char *extra, unsigned int offset)
+{
+ guint32 len = strlen (extra);
+ gchar *res = g_realloc ((gpointer)gstri->base.str, offset + 4 + len + 1);
+ GSF_LE_SET_GUINT32(res + offset, len);
+ memcpy ((gpointer)(res + offset + 4), extra, len + 1);
+ g_free (extra);
+
+ if (res != gstri->base.str) {
+ /* update any shared strings */
+ if ((gstri->flags & GO_STRING_IS_SHARED)) {
+ GSList *shares = g_hash_table_lookup (go_strings_shared, gstri->base.str);
+ g_hash_table_remove (go_strings_shared, gstri->base.str);
+ g_hash_table_insert (go_strings_shared, res, shares);
+ for (; shares != NULL ; shares = shares->next)
+ ((GOStringImpl *)(shares->data))->base.str = res;
+ }
+ ((GOStringImpl *)gstri)->base.str = res;
+ }
+}
+
+char const *
+go_string_get_collation (GOString const *gstr)
+{
+ GOStringImpl *gstri = (GOStringImpl *)gstr;
+ unsigned int len;
+
+ if (NULL == gstr)
+ return "";
+
+ len = GO_STRING_LEN (gstri);
+ if (0 == (gstri->flags & GO_STRING_HAS_COLLATE)) {
+ gchar *collate = g_utf8_collate_key (gstri->base.str, len);
+ /* Keep it simple, drop the casefold to avoid issues with overlapping */
+ gstri->flags &= ~GO_STRING_HAS_CASEFOLD;
+ gstri->flags |= GO_STRING_HAS_COLLATE;
+ go_string_impl_append_extra (gstri, collate, len + 1);
+ }
+ return gstri->base.str + len + 1 + 4;
+}
+
+char const *
+go_string_get_casefold (GOString const *gstr)
+{
+ GOStringImpl *gstri = (GOStringImpl *)gstr;
+ unsigned int offset;
+
+ if (NULL == gstr)
+ return "";
+
+ offset = GO_STRING_LEN (gstri) + 1;
+ if (0 != (gstri->flags & GO_STRING_HAS_COLLATE))
+ offset += GSF_LE_GET_GUINT32(gstri->base.str + offset) + 4 + 1;
+
+ if (0 == (gstri->flags & GO_STRING_HAS_CASEFOLD)) {
+ gchar *casefold = g_utf8_casefold (gstri->base.str, GO_STRING_LEN (gstri));
+ gstri->flags |= GO_STRING_HAS_CASEFOLD;
+ go_string_impl_append_extra (gstri, casefold, offset);
+ }
+ return gstri->base.str + offset + 4;
+}
+
+static GOString *go_string_ERROR_val = NULL;
+
+/**
+ * go_string_ERROR :
+ *
+ * A convenience for g_return_val to share one error string without adding a
+ * reference to functions that do not add references to the result
+ *
+ * Returns : A string saying 'ERROR' but does not add a ref to it.
+ **/
+GOString *
+go_string_ERROR (void)
+{
+ return go_string_ERROR_val;
+}
+
+/*******************************************************************************/
+
+/* Internal comparison routine that actually does a strcmp, rather than
+ * assuming that only str == str are equal */
+static gboolean
+go_string_equal_internal (gconstpointer gstr_a, gconstpointer gstr_b)
+{
+ GOStringImpl const *a = gstr_a;
+ GOStringImpl const *b = gstr_b;
+ return a == b ||
+ ((a->hash == b->hash) &&
+ (GO_STRING_LEN (a) == GO_STRING_LEN (b)) &&
+ 0 == strcmp (a->base.str, b->base.str));
+}
+void
+_go_string_init (void)
+{
+ go_strings_base = g_hash_table_new (go_string_hash, go_string_equal_internal);
+ go_strings_shared = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ /* Do it here, so we always have it. */
+ go_string_ERROR_val = go_string_new ("<ERROR>");
+}
+
+static gboolean
+cb_string_pool_leak (G_GNUC_UNUSED gpointer key,
+ gpointer value,
+ G_GNUC_UNUSED gpointer user)
+{
+ GOString const *gstr = value;
+ g_printerr ("Leaking string [%s] with ref_count=%d.\n",
+ gstr->str, go_string_get_ref_count (gstr));
+ return TRUE;
+}
+
+void
+_go_string_shutdown (void)
+{
+ go_string_unref (go_string_ERROR_val);
+ go_string_ERROR_val = NULL;
+
+ g_hash_table_destroy (go_strings_shared);
+ go_strings_shared = NULL;
+
+ g_hash_table_foreach_remove (go_strings_base,
+ cb_string_pool_leak,
+ NULL);
+ g_hash_table_destroy (go_strings_base);
+ go_strings_base = NULL;
+}
+
+static void
+cb_collect_strings (G_GNUC_UNUSED gpointer key, gpointer str,
+ gpointer user_data)
+{
+ GSList **pstrs = user_data;
+ *pstrs = g_slist_prepend (*pstrs, str);
+}
+
+static gint
+cb_by_refcount_str (gconstpointer a_, gconstpointer b_)
+{
+ GOStringImpl const *a = a_;
+ GOStringImpl const *b = b_;
+
+ if (a->ref_count == b->ref_count)
+ return strcmp (a->base.str, b->base.str);
+ return (a->ref_count - b->ref_count);
+}
+
+/**
+ * _go_string_dump :
+ *
+ * Internal debugging utility to
+ **/
+void
+_go_string_dump (void)
+{
+ GSList *strs = NULL;
+ GSList *l;
+ int refs = 0, len = 0;
+ int count;
+
+ g_hash_table_foreach (go_strings_base, cb_collect_strings, &strs);
+ strs = g_slist_sort (strs, cb_by_refcount_str);
+ count = g_slist_length (strs);
+ for (l = strs; l; l = l->next) {
+ GOStringImpl const *s = l->data;
+ refs += s->ref_count;
+ len += GO_STRING_LEN (s);
+ }
+
+ for (l = g_slist_nth (strs, MAX (0, count - 100)); l; l = l->next) {
+ GOStringImpl const *s = l->data;
+ g_print ("%8d \"%s\"\n", s->ref_count, s->base.str);
+ }
+ g_print ("String table contains %d different strings.\n", count);
+ g_print ("String table contains a total of %d characters.\n", len);
+ g_print ("String table contains a total of %d refs.\n", refs);
+ g_slist_free (strs);
+}
+
+void
+go_string_foreach_base (GHFunc callback, gpointer data)
+{
+ g_hash_table_foreach (go_strings_base, callback, data);
+}
+
+static void
+value_transform_gostring_string (GValue const *src_val,
+ GValue *dest)
+{
+ GOString *src_str = src_val->data[0].v_pointer;
+ dest->data[0].v_pointer = src_str
+ ? g_strndup (src_str->str, GO_STRING_LEN (src_str))
+ : NULL;
+}
+
+/**
+ * go_string_get_type :
+ * Register #GOString as a type for #GValue
+ * Returns : #GType
+ **/
+GType
+go_string_get_type (void)
+{
+ static GType t = 0;
+
+ if (t == 0) {
+ t = g_boxed_type_register_static ("GOString",
+ (GBoxedCopyFunc)go_string_ref,
+ (GBoxedFreeFunc)go_string_unref);
+ g_value_register_transform_func (t, G_TYPE_STRING, value_transform_gostring_string);
+ }
+ return t;
+}
diff --git a/goffice/utils/go-string.h b/goffice/utils/go-string.h
new file mode 100644
index 0000000..856e8f9
--- /dev/null
+++ b/goffice/utils/go-string.h
@@ -0,0 +1,80 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * go-string.h : ref counted shared strings with richtext and phonetic support
+ *
+ * Copyright (C) 2008 Jody Goldberg (jody gnome org)
+ * Copyright (C) 2007-2008 Morten Welinder (terra gnome org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#ifndef GO_STRING_H
+#define GO_STRING_H
+
+#include <goffice/goffice.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GOStringPhonetic GOStringPhonetic; /* TODO : move */
+
+struct _GOString {
+ char const *str; /* utf-8 */
+ /* <private data> */
+};
+
+GType go_string_get_type (void); /* GBoxed support */
+
+GOString *go_string_new (char const *str);
+GOString *go_string_new_len (char const *str, guint32 len);
+GOString *go_string_new_nocopy (char *str);
+GOString *go_string_new_nocopy_len (char *str, guint32 len);
+GOString *go_string_new_rich (char const *str,
+ int byte_len,
+ gboolean copy,
+ PangoAttrList *markup,
+ GOStringPhonetic *phonetic);
+
+GOString *go_string_ref (GOString *gstr);
+void go_string_unref (GOString *gstr);
+
+char const *go_string_get_cstr (GOString const *gstr);
+guint32 go_string_get_len (GOString const *gstr);
+unsigned int go_string_get_ref_count (GOString const *gstr);
+char const *go_string_get_collation (GOString const *gstr);
+char const *go_string_get_casefold (GOString const *gstr);
+
+PangoAttrList *go_string_get_markup (GOString const *gstr);
+GOStringPhonetic *go_string_get_phonetic (GOString const *gstr);
+guint32 go_string_hash (gconstpointer gstr);
+int go_string_cmp (gconstpointer gstr_a, gconstpointer gstr_b);
+int go_string_cmp_ignorecase (gconstpointer gstr_a, gconstpointer gstr_b);
+gboolean go_string_equal (gconstpointer gstr_a, gconstpointer gstr_b);
+gboolean go_string_equal_ignorecase (gconstpointer gstr_a, gconstpointer gstr_b);
+gboolean go_string_equal_rich (gconstpointer gstr_a, gconstpointer gstr_b);
+
+GOString *go_string_ERROR (void);
+
+/*< private >*/
+void _go_string_init (void);
+void _go_string_shutdown (void);
+void _go_string_dump (void);
+
+
+/* semi-private */
+void go_string_foreach_base (GHFunc callback, gpointer data);
+
+G_END_DECLS
+
+#endif /* GO_STRING_H */
diff --git a/goffice/utils/goffice-utils.h b/goffice/utils/goffice-utils.h
index 4853f2a..2c8e00b 100644
--- a/goffice/utils/goffice-utils.h
+++ b/goffice/utils/goffice-utils.h
@@ -36,6 +36,7 @@ typedef struct _GOFormat GOFormat;
typedef struct _GODateConventions GODateConventions;
typedef struct _GOImage GOImage;
typedef struct _GOPath GOPath;
+typedef struct _GOString GOString;
typedef struct _GOStyle GOStyle;
typedef struct _GOStyledObject GOStyledObject;
@@ -100,6 +101,7 @@ G_END_DECLS
#include <goffice/utils/go-path.h>
#include <goffice/utils/go-pattern.h>
#include <goffice/utils/go-persist.h>
+#include <goffice/utils/go-string.h>
#include <goffice/utils/go-styled-object.h>
#include <goffice/utils/go-style.h>
#include <goffice/utils/go-undo.h>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]