added g_list_nth_prev() which walks ->prev instead of ->next.
authorTim Janik <timj@gtk.org>
Tue, 3 Apr 2001 13:15:41 +0000 (13:15 +0000)
committerTim Janik <timj@src.gnome.org>
Tue, 3 Apr 2001 13:15:41 +0000 (13:15 +0000)
Tue Apr  3 13:46:22 2001  Tim Janik  <timj@gtk.org>

        * glist.[hc]: added g_list_nth_prev() which walks ->prev instead
        of ->next.

        * gpattern.[hc]: added shell-style pattern matching code from beast,
        derived from the gtk_pattern_*() code, but with a couple of bug fixes
        and a number of optimizations.

Tue Apr  3 14:06:00 2001  Tim Janik  <timj@gtk.org>

        * gparam.[hc]: added g_param_spec_pool_list() to list pspecs per
        owner_type. the pspecs are not referenced, so the caller is
        supposed to have some idea about owner_type not randomly
        nuking his pspec's. if this is going to provide problems in
        the future, we can either auto-ref the pspecs, or add a
        _foreach variant, though the latter would have to invoke
        the callback while pspec's mutex is acquired, so i just
        went for the _list variant for now.

        * gclosure.h (G_CALLBACK): made GCallback a void (*) (void) fucntion.

26 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
Makefile.am
docs/reference/glib/tmpl/glib-unused.sgml
docs/reference/gobject/tmpl/closures.sgml
glib.h
glib/Makefile.am
glib/glib.h
glib/glist.c
glib/glist.h
glib/gpattern.c [new file with mode: 0644]
glib/gpattern.h [new file with mode: 0644]
glist.c
glist.h
gobject/ChangeLog
gobject/gclosure.h
gobject/gparam.c
gobject/gparam.h
gpattern.c [new file with mode: 0644]
gpattern.h [new file with mode: 0644]

index b0b919e..75ed6fe 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Tue Apr  3 13:46:22 2001  Tim Janik  <timj@gtk.org>
+
+       * glist.[hc]: added g_list_nth_prev() which walks ->prev instead
+       of ->next.
+
+       * gpattern.[hc]: added shell-style pattern matching code from beast,
+       derived from the gtk_pattern_*() code, but with a couple of bug fixes
+       and a number of optimizations.
+
 2001-04-03  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * gthreadpool.c: Added documentation.
index b0b919e..75ed6fe 100644 (file)
@@ -1,3 +1,12 @@
+Tue Apr  3 13:46:22 2001  Tim Janik  <timj@gtk.org>
+
+       * glist.[hc]: added g_list_nth_prev() which walks ->prev instead
+       of ->next.
+
+       * gpattern.[hc]: added shell-style pattern matching code from beast,
+       derived from the gtk_pattern_*() code, but with a couple of bug fixes
+       and a number of optimizations.
+
 2001-04-03  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * gthreadpool.c: Added documentation.
index b0b919e..75ed6fe 100644 (file)
@@ -1,3 +1,12 @@
+Tue Apr  3 13:46:22 2001  Tim Janik  <timj@gtk.org>
+
+       * glist.[hc]: added g_list_nth_prev() which walks ->prev instead
+       of ->next.
+
+       * gpattern.[hc]: added shell-style pattern matching code from beast,
+       derived from the gtk_pattern_*() code, but with a couple of bug fixes
+       and a number of optimizations.
+
 2001-04-03  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * gthreadpool.c: Added documentation.
index b0b919e..75ed6fe 100644 (file)
@@ -1,3 +1,12 @@
+Tue Apr  3 13:46:22 2001  Tim Janik  <timj@gtk.org>
+
+       * glist.[hc]: added g_list_nth_prev() which walks ->prev instead
+       of ->next.
+
+       * gpattern.[hc]: added shell-style pattern matching code from beast,
+       derived from the gtk_pattern_*() code, but with a couple of bug fixes
+       and a number of optimizations.
+
 2001-04-03  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * gthreadpool.c: Added documentation.
index b0b919e..75ed6fe 100644 (file)
@@ -1,3 +1,12 @@
+Tue Apr  3 13:46:22 2001  Tim Janik  <timj@gtk.org>
+
+       * glist.[hc]: added g_list_nth_prev() which walks ->prev instead
+       of ->next.
+
+       * gpattern.[hc]: added shell-style pattern matching code from beast,
+       derived from the gtk_pattern_*() code, but with a couple of bug fixes
+       and a number of optimizations.
+
 2001-04-03  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * gthreadpool.c: Added documentation.
index b0b919e..75ed6fe 100644 (file)
@@ -1,3 +1,12 @@
+Tue Apr  3 13:46:22 2001  Tim Janik  <timj@gtk.org>
+
+       * glist.[hc]: added g_list_nth_prev() which walks ->prev instead
+       of ->next.
+
+       * gpattern.[hc]: added shell-style pattern matching code from beast,
+       derived from the gtk_pattern_*() code, but with a couple of bug fixes
+       and a number of optimizations.
+
 2001-04-03  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * gthreadpool.c: Added documentation.
index b0b919e..75ed6fe 100644 (file)
@@ -1,3 +1,12 @@
+Tue Apr  3 13:46:22 2001  Tim Janik  <timj@gtk.org>
+
+       * glist.[hc]: added g_list_nth_prev() which walks ->prev instead
+       of ->next.
+
+       * gpattern.[hc]: added shell-style pattern matching code from beast,
+       derived from the gtk_pattern_*() code, but with a couple of bug fixes
+       and a number of optimizations.
+
 2001-04-03  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * gthreadpool.c: Added documentation.
index b0b919e..75ed6fe 100644 (file)
@@ -1,3 +1,12 @@
+Tue Apr  3 13:46:22 2001  Tim Janik  <timj@gtk.org>
+
+       * glist.[hc]: added g_list_nth_prev() which walks ->prev instead
+       of ->next.
+
+       * gpattern.[hc]: added shell-style pattern matching code from beast,
+       derived from the gtk_pattern_*() code, but with a couple of bug fixes
+       and a number of optimizations.
+
 2001-04-03  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * gthreadpool.c: Added documentation.
index 846fde0..c378bd7 100644 (file)
@@ -60,6 +60,7 @@ libglib_1_3_la_SOURCES =      \
        gmem.c                  \
        gmessages.c             \
        gnode.c                 \
+       gpattern.c              \
        gprimes.c               \
        gqsort.c                \
        gqueue.c                \
@@ -115,6 +116,7 @@ glibinclude_HEADERS =   \
        gmem.h          \
        gmessages.h     \
        gnode.h         \
+       gpattern.h      \
        gprimes.h       \
        gqsort.h        \
        gquark.h        \
index 6d653cb..8cadf15 100644 (file)
@@ -149,6 +149,25 @@ priority are stored in the order in which they were added.
 type of source.
 @Returns: TRUE if an event source was found and removed.
 
+<!-- ##### FUNCTION g_static_private_get_for_thread ##### -->
+<para>
+
+</para>
+
+@private_key: 
+@thread: 
+@Returns: 
+
+<!-- ##### FUNCTION g_static_private_set_for_thread ##### -->
+<para>
+
+</para>
+
+@private_key: 
+@thread: 
+@data: 
+@notify: 
+
 <!-- ##### MACRO g_string ##### -->
 <para>
 Turns the argument into a string literal by using the '#' stringizing operator.
index 9647d62..2ff5657 100644 (file)
@@ -38,12 +38,13 @@ Closures
 @f: 
 
 
-<!-- ##### TYPEDEF GCallback ##### -->
+<!-- ##### USER_FUNCTION GCallback ##### -->
 <para>
 
 </para>
 
 
+
 <!-- ##### STRUCT GClosure ##### -->
 <para>
 
diff --git a/glib.h b/glib.h
index 9cbd7e4..8b32acc 100644 (file)
--- a/glib.h
+++ b/glib.h
@@ -48,6 +48,7 @@
 #include <gmem.h>
 #include <gmessages.h>
 #include <gnode.h>
+#include <gpattern.h>
 #include <gprimes.h>
 #include <gqsort.h>
 #include <gquark.h>
index 846fde0..c378bd7 100644 (file)
@@ -60,6 +60,7 @@ libglib_1_3_la_SOURCES =      \
        gmem.c                  \
        gmessages.c             \
        gnode.c                 \
+       gpattern.c              \
        gprimes.c               \
        gqsort.c                \
        gqueue.c                \
@@ -115,6 +116,7 @@ glibinclude_HEADERS =   \
        gmem.h          \
        gmessages.h     \
        gnode.h         \
+       gpattern.h      \
        gprimes.h       \
        gqsort.h        \
        gquark.h        \
index 9cbd7e4..8b32acc 100644 (file)
@@ -48,6 +48,7 @@
 #include <gmem.h>
 #include <gmessages.h>
 #include <gnode.h>
+#include <gpattern.h>
 #include <gprimes.h>
 #include <gqsort.h>
 #include <gquark.h>
index 3d24bd2..3518221 100644 (file)
@@ -483,6 +483,16 @@ g_list_nth (GList *list,
   return list;
 }
 
+GList*
+g_list_nth_prev (GList *list,
+                guint  n)
+{
+  while ((n-- > 0) && list)
+    list = list->prev;
+  
+  return list;
+}
+
 gpointer
 g_list_nth_data (GList     *list,
                 guint      n)
index c871b53..81ec9b3 100644 (file)
@@ -71,6 +71,8 @@ GList*   g_list_reverse        (GList            *list);
 GList*   g_list_copy           (GList            *list);
 GList*   g_list_nth            (GList            *list,
                                guint             n);
+GList*   g_list_nth_prev       (GList            *list,
+                               guint             n);
 GList*   g_list_find           (GList            *list,
                                gconstpointer     data);
 GList*   g_list_find_custom    (GList            *list,
diff --git a/glib/gpattern.c b/glib/gpattern.c
new file mode 100644 (file)
index 0000000..6ad1c27
--- /dev/null
@@ -0,0 +1,299 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997, 1999  Peter Mattis, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gpattern.h"
+
+#include "gmacros.h"
+#include "gmessages.h"
+#include "gmem.h"
+#include <string.h>
+
+
+/* --- functions --- */
+static inline gboolean
+g_pattern_ph_match (const gchar *match_pattern,
+                   const gchar *match_string)
+{
+  register const gchar *pattern, *string;
+  register gchar ch;
+
+  pattern = match_pattern;
+  string = match_string;
+
+  ch = *pattern;
+  pattern++;
+  while (ch)
+    {
+      switch (ch)
+       {
+       case '?':
+         if (!*string)
+           return FALSE;
+         string++;
+         break;
+
+       case '*':
+         do
+           {
+             ch = *pattern;
+             pattern++;
+             if (ch == '?')
+               {
+                 if (!*string)
+                   return FALSE;
+                 string++;
+               }
+           }
+         while (ch == '*' || ch == '?');
+         if (!ch)
+           return TRUE;
+         do
+           {
+             while (ch != *string)
+               {
+                 if (!*string)
+                   return FALSE;
+                 string++;
+               }
+             string++;
+             if (g_pattern_ph_match (pattern, string))
+               return TRUE;
+           }
+         while (*string);
+         break;
+
+       default:
+         if (ch == *string)
+           string++;
+         else
+           return FALSE;
+         break;
+       }
+
+      ch = *pattern;
+      pattern++;
+    }
+
+  return *string == 0;
+}
+
+gboolean
+g_pattern_match (GPatternSpec *pspec,
+                guint         string_length,
+                const gchar  *string,
+                const gchar  *string_reversed)
+{
+  g_return_val_if_fail (pspec != NULL, FALSE);
+  g_return_val_if_fail (string != NULL, FALSE);
+  g_return_val_if_fail (string_reversed != NULL, FALSE);
+
+  switch (pspec->match_type)
+    {
+    case G_MATCH_ALL:
+      return g_pattern_ph_match (pspec->pattern, string);
+
+    case G_MATCH_ALL_TAIL:
+      return g_pattern_ph_match (pspec->pattern_reversed, string_reversed);
+
+    case G_MATCH_HEAD:
+      if (pspec->pattern_length > string_length)
+       return FALSE;
+      else if (pspec->pattern_length == string_length)
+       return strcmp (pspec->pattern, string) == 0;
+      else if (pspec->pattern_length)
+       return strncmp (pspec->pattern, string, pspec->pattern_length) == 0;
+      else
+       return TRUE;
+
+    case G_MATCH_TAIL:
+      if (pspec->pattern_length > string_length)
+       return FALSE;
+      else if (pspec->pattern_length == string_length)
+       return strcmp (pspec->pattern_reversed, string_reversed) == 0;
+      else if (pspec->pattern_length)
+       return strncmp (pspec->pattern_reversed,
+                       string_reversed,
+                       pspec->pattern_length) == 0;
+      else
+       return TRUE;
+
+    case G_MATCH_EXACT:
+      if (pspec->pattern_length != string_length)
+       return FALSE;
+      else
+       return strcmp (pspec->pattern_reversed, string_reversed) == 0;
+
+    default:
+      g_return_val_if_fail (pspec->match_type < G_MATCH_LAST, FALSE);
+      return FALSE;
+    }
+}
+
+GPatternSpec*
+g_pattern_spec_new (const gchar *pattern)
+{
+  GPatternSpec *pspec;
+  gchar *p, *t;
+  const gchar *h;
+  guint hw = 0, tw = 0, hj = 0, tj = 0;
+
+  g_return_val_if_fail (pattern != NULL, NULL);
+
+  pspec = g_new (GPatternSpec, 1);
+  pspec->pattern_length = strlen (pattern);
+  pspec->pattern = strcpy (g_new (gchar, pspec->pattern_length + 1), pattern);
+  pspec->pattern_reversed = g_new (gchar, pspec->pattern_length + 1);
+  t = pspec->pattern_reversed + pspec->pattern_length;
+  *(t--) = 0;
+  h = pattern;
+  while (t >= pspec->pattern_reversed)
+    {
+      register gchar c = *(h++);
+
+      if (c == '*')
+       {
+         if (t < h)
+           hw++;
+         else
+           tw++;
+       }
+      else if (c == '?')
+       {
+         if (t < h)
+           hj++;
+         else
+           tj++;
+       }
+
+      *(t--) = c;
+    }
+  pspec->match_type = hw > tw || (hw == tw && hj > tj) ? G_MATCH_ALL_TAIL : G_MATCH_ALL;
+
+  if (hj || tj)
+    return pspec;
+
+  if (hw == 0 && tw == 0)
+    {
+      pspec->match_type = G_MATCH_EXACT;
+      return pspec;
+    }
+
+  if (hw)
+    {
+      p = pspec->pattern;
+      while (*p == '*')
+       p++;
+      if (p > pspec->pattern && !strchr (p, '*'))
+       {
+         gchar *tmp;
+
+         pspec->match_type = G_MATCH_TAIL;
+         pspec->pattern_length = strlen (p);
+         tmp = pspec->pattern;
+         pspec->pattern = strcpy (g_new (gchar, pspec->pattern_length + 1), p);
+         g_free (tmp);
+         g_free (pspec->pattern_reversed);
+         pspec->pattern_reversed = g_new (gchar, pspec->pattern_length + 1);
+         t = pspec->pattern_reversed + pspec->pattern_length;
+         *(t--) = 0;
+         h = pspec->pattern;
+         while (t >= pspec->pattern_reversed)
+           *(t--) = *(h++);
+         return pspec;
+       }
+    }
+
+  if (tw)
+    {
+      p = pspec->pattern_reversed;
+      while (*p == '*')
+       p++;
+      if (p > pspec->pattern_reversed && !strchr (p, '*'))
+       {
+         gchar *tmp;
+
+         pspec->match_type = G_MATCH_HEAD;
+         pspec->pattern_length = strlen (p);
+         tmp = pspec->pattern_reversed;
+         pspec->pattern_reversed = strcpy (g_new (gchar, pspec->pattern_length + 1), p);
+         g_free (tmp);
+         g_free (pspec->pattern);
+         pspec->pattern = g_new (gchar, pspec->pattern_length + 1);
+         t = pspec->pattern + pspec->pattern_length;
+         *(t--) = 0;
+         h = pspec->pattern_reversed;
+         while (t >= pspec->pattern)
+           *(t--) = *(h++);
+       }
+    }
+
+  return pspec;
+}
+
+gboolean
+g_pattern_match_string (GPatternSpec *pspec,
+                       const gchar  *string)
+{
+  gchar *string_reversed, *t;
+  const gchar *h;
+  guint length;
+  gboolean ergo;
+
+  g_return_val_if_fail (pspec != NULL, FALSE);
+  g_return_val_if_fail (string != NULL, FALSE);
+
+  length = strlen (string);
+  string_reversed = g_new (gchar, length + 1);
+  t = string_reversed + length;
+  *(t--) = 0;
+  h = string;
+  while (t >= string_reversed)
+    *(t--) = *(h++);
+
+  ergo = g_pattern_match (pspec, length, string, string_reversed);
+  g_free (string_reversed);
+
+  return ergo;
+}
+
+gboolean
+g_pattern_match_simple (const gchar *pattern,
+                       const gchar *string)
+{
+  GPatternSpec *pspec;
+  gboolean ergo;
+
+  g_return_val_if_fail (pattern != NULL, FALSE);
+  g_return_val_if_fail (string != NULL, FALSE);
+
+  pspec = g_pattern_spec_new (pattern);
+  ergo = g_pattern_match_string (pspec, string);
+  g_pattern_spec_free (pspec);
+
+  return ergo;
+}
+
+void
+g_pattern_spec_free (GPatternSpec *pspec)
+{
+  g_return_if_fail (pspec != NULL);
+
+  g_free (pspec->pattern);
+  g_free (pspec->pattern_reversed);
+  g_free (pspec);
+}
diff --git a/glib/gpattern.h b/glib/gpattern.h
new file mode 100644 (file)
index 0000000..add239c
--- /dev/null
@@ -0,0 +1,58 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997, 1999  Peter Mattis, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __G_PATTERN_H__
+#define __G_PATTERN_H__
+
+#include <gtypes.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+  G_MATCH_ALL,       /* "*A?A*" */
+  G_MATCH_ALL_TAIL,  /* "*A?AA" */
+  G_MATCH_HEAD,      /* "AAAA*" */
+  G_MATCH_TAIL,      /* "*AAAA" */
+  G_MATCH_EXACT,     /* "AAAAA" */
+  G_MATCH_LAST
+} GMatchType;
+
+typedef struct _GPatternSpec    GPatternSpec;
+struct _GPatternSpec
+{
+  GMatchType match_type;
+  guint      pattern_length;
+  gchar     *pattern;
+  gchar     *pattern_reversed;
+};
+
+GPatternSpec* g_pattern_spec_new       (const gchar  *pattern);
+void          g_pattern_spec_free      (GPatternSpec *pspec);
+gboolean      g_pattern_match          (GPatternSpec *pspec,
+                                       guint         string_length,
+                                       const gchar  *string,
+                                       const gchar  *string_reversed);
+gboolean      g_pattern_match_string   (GPatternSpec *pspec,
+                                       const gchar  *string);
+gboolean      g_pattern_match_simple   (const gchar  *pattern,
+                                       const gchar  *string);
+
+G_END_DECLS
+
+#endif /* __G_PATTERN_H__ */
diff --git a/glist.c b/glist.c
index 3d24bd2..3518221 100644 (file)
--- a/glist.c
+++ b/glist.c
@@ -483,6 +483,16 @@ g_list_nth (GList *list,
   return list;
 }
 
+GList*
+g_list_nth_prev (GList *list,
+                guint  n)
+{
+  while ((n-- > 0) && list)
+    list = list->prev;
+  
+  return list;
+}
+
 gpointer
 g_list_nth_data (GList     *list,
                 guint      n)
diff --git a/glist.h b/glist.h
index c871b53..81ec9b3 100644 (file)
--- a/glist.h
+++ b/glist.h
@@ -71,6 +71,8 @@ GList*   g_list_reverse        (GList            *list);
 GList*   g_list_copy           (GList            *list);
 GList*   g_list_nth            (GList            *list,
                                guint             n);
+GList*   g_list_nth_prev       (GList            *list,
+                               guint             n);
 GList*   g_list_find           (GList            *list,
                                gconstpointer     data);
 GList*   g_list_find_custom    (GList            *list,
index 7b2b7f5..b4bf3e0 100644 (file)
@@ -1,3 +1,16 @@
+Tue Apr  3 14:06:00 2001  Tim Janik  <timj@gtk.org>
+
+       * gparam.[hc]: added g_param_spec_pool_list() to list pspecs per
+       owner_type. the pspecs are not referenced, so the caller is
+       supposed to have some idea about owner_type not randomly
+       nuking his pspec's. if this is going to provide problems in
+       the future, we can either auto-ref the pspecs, or add a
+       _foreach variant, though the latter would have to invoke
+       the callback while pspec's mutex is acquired, so i just
+       went for the _list variant for now.
+
+       * gclosure.h (G_CALLBACK): made GCallback a void (*) (void) fucntion.
+
 Sat Mar 31 23:55:58 2001  Tim Janik  <timj@gtk.org>
 
        * gtype.h:
index 39531d2..ab8974d 100644 (file)
@@ -33,7 +33,7 @@ G_BEGIN_DECLS
 /* -- typedefs --- */
 typedef struct _GClosure                GClosure;
 typedef struct _GClosureNotifyData      GClosureNotifyData;
-typedef        gpointer                         GCallback;
+typedef void  (*GCallback)              (void);
 typedef void  (*GClosureNotify)                (gpointer        data,
                                         GClosure       *closure);
 typedef void  (*GClosureMarshal)       (GClosure       *closure,
index 72af807..5117177 100644 (file)
@@ -711,6 +711,37 @@ g_param_spec_pool_lookup (GParamSpecPool *pool,
   return NULL;
 }
 
+static void
+pool_list (gpointer key,
+          gpointer value,
+          gpointer user_data)
+{
+  GParamSpec *pspec = value;
+  gpointer *data = user_data;
+  GType owner_type = GPOINTER_TO_UINT (data[1]);
+
+  if (owner_type == pspec->owner_type)
+    data[0] = g_list_prepend (data[0], pspec);
+}
+
+GList*
+g_param_spec_pool_list (GParamSpecPool *pool,
+                       GType           owner_type)
+{
+  gpointer data[2];
+
+  g_return_val_if_fail (pool != NULL, NULL);
+  g_return_val_if_fail (owner_type > 0, NULL);
+  
+  G_SLOCK (&pool->smutex);
+  data[0] = NULL;
+  data[1] = GUINT_TO_POINTER (owner_type);
+  g_hash_table_foreach (pool->hash_table, pool_list, &data);
+  G_SUNLOCK (&pool->smutex);
+
+  return data[0];
+}
+
 
 /* --- auxillary functions --- */
 typedef struct
index a393613..744a397 100644 (file)
@@ -165,6 +165,9 @@ GParamSpec* g_param_spec_pool_lookup        (GParamSpecPool *pool,
                                                 const gchar    *param_name,
                                                 GType           owner_type,
                                                 gboolean        walk_ancestors);
+GList*         g_param_spec_pool_list          (GParamSpecPool *pool,
+                                                GType           owner_type);
+
 
 
 /* contracts:
diff --git a/gpattern.c b/gpattern.c
new file mode 100644 (file)
index 0000000..6ad1c27
--- /dev/null
@@ -0,0 +1,299 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997, 1999  Peter Mattis, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gpattern.h"
+
+#include "gmacros.h"
+#include "gmessages.h"
+#include "gmem.h"
+#include <string.h>
+
+
+/* --- functions --- */
+static inline gboolean
+g_pattern_ph_match (const gchar *match_pattern,
+                   const gchar *match_string)
+{
+  register const gchar *pattern, *string;
+  register gchar ch;
+
+  pattern = match_pattern;
+  string = match_string;
+
+  ch = *pattern;
+  pattern++;
+  while (ch)
+    {
+      switch (ch)
+       {
+       case '?':
+         if (!*string)
+           return FALSE;
+         string++;
+         break;
+
+       case '*':
+         do
+           {
+             ch = *pattern;
+             pattern++;
+             if (ch == '?')
+               {
+                 if (!*string)
+                   return FALSE;
+                 string++;
+               }
+           }
+         while (ch == '*' || ch == '?');
+         if (!ch)
+           return TRUE;
+         do
+           {
+             while (ch != *string)
+               {
+                 if (!*string)
+                   return FALSE;
+                 string++;
+               }
+             string++;
+             if (g_pattern_ph_match (pattern, string))
+               return TRUE;
+           }
+         while (*string);
+         break;
+
+       default:
+         if (ch == *string)
+           string++;
+         else
+           return FALSE;
+         break;
+       }
+
+      ch = *pattern;
+      pattern++;
+    }
+
+  return *string == 0;
+}
+
+gboolean
+g_pattern_match (GPatternSpec *pspec,
+                guint         string_length,
+                const gchar  *string,
+                const gchar  *string_reversed)
+{
+  g_return_val_if_fail (pspec != NULL, FALSE);
+  g_return_val_if_fail (string != NULL, FALSE);
+  g_return_val_if_fail (string_reversed != NULL, FALSE);
+
+  switch (pspec->match_type)
+    {
+    case G_MATCH_ALL:
+      return g_pattern_ph_match (pspec->pattern, string);
+
+    case G_MATCH_ALL_TAIL:
+      return g_pattern_ph_match (pspec->pattern_reversed, string_reversed);
+
+    case G_MATCH_HEAD:
+      if (pspec->pattern_length > string_length)
+       return FALSE;
+      else if (pspec->pattern_length == string_length)
+       return strcmp (pspec->pattern, string) == 0;
+      else if (pspec->pattern_length)
+       return strncmp (pspec->pattern, string, pspec->pattern_length) == 0;
+      else
+       return TRUE;
+
+    case G_MATCH_TAIL:
+      if (pspec->pattern_length > string_length)
+       return FALSE;
+      else if (pspec->pattern_length == string_length)
+       return strcmp (pspec->pattern_reversed, string_reversed) == 0;
+      else if (pspec->pattern_length)
+       return strncmp (pspec->pattern_reversed,
+                       string_reversed,
+                       pspec->pattern_length) == 0;
+      else
+       return TRUE;
+
+    case G_MATCH_EXACT:
+      if (pspec->pattern_length != string_length)
+       return FALSE;
+      else
+       return strcmp (pspec->pattern_reversed, string_reversed) == 0;
+
+    default:
+      g_return_val_if_fail (pspec->match_type < G_MATCH_LAST, FALSE);
+      return FALSE;
+    }
+}
+
+GPatternSpec*
+g_pattern_spec_new (const gchar *pattern)
+{
+  GPatternSpec *pspec;
+  gchar *p, *t;
+  const gchar *h;
+  guint hw = 0, tw = 0, hj = 0, tj = 0;
+
+  g_return_val_if_fail (pattern != NULL, NULL);
+
+  pspec = g_new (GPatternSpec, 1);
+  pspec->pattern_length = strlen (pattern);
+  pspec->pattern = strcpy (g_new (gchar, pspec->pattern_length + 1), pattern);
+  pspec->pattern_reversed = g_new (gchar, pspec->pattern_length + 1);
+  t = pspec->pattern_reversed + pspec->pattern_length;
+  *(t--) = 0;
+  h = pattern;
+  while (t >= pspec->pattern_reversed)
+    {
+      register gchar c = *(h++);
+
+      if (c == '*')
+       {
+         if (t < h)
+           hw++;
+         else
+           tw++;
+       }
+      else if (c == '?')
+       {
+         if (t < h)
+           hj++;
+         else
+           tj++;
+       }
+
+      *(t--) = c;
+    }
+  pspec->match_type = hw > tw || (hw == tw && hj > tj) ? G_MATCH_ALL_TAIL : G_MATCH_ALL;
+
+  if (hj || tj)
+    return pspec;
+
+  if (hw == 0 && tw == 0)
+    {
+      pspec->match_type = G_MATCH_EXACT;
+      return pspec;
+    }
+
+  if (hw)
+    {
+      p = pspec->pattern;
+      while (*p == '*')
+       p++;
+      if (p > pspec->pattern && !strchr (p, '*'))
+       {
+         gchar *tmp;
+
+         pspec->match_type = G_MATCH_TAIL;
+         pspec->pattern_length = strlen (p);
+         tmp = pspec->pattern;
+         pspec->pattern = strcpy (g_new (gchar, pspec->pattern_length + 1), p);
+         g_free (tmp);
+         g_free (pspec->pattern_reversed);
+         pspec->pattern_reversed = g_new (gchar, pspec->pattern_length + 1);
+         t = pspec->pattern_reversed + pspec->pattern_length;
+         *(t--) = 0;
+         h = pspec->pattern;
+         while (t >= pspec->pattern_reversed)
+           *(t--) = *(h++);
+         return pspec;
+       }
+    }
+
+  if (tw)
+    {
+      p = pspec->pattern_reversed;
+      while (*p == '*')
+       p++;
+      if (p > pspec->pattern_reversed && !strchr (p, '*'))
+       {
+         gchar *tmp;
+
+         pspec->match_type = G_MATCH_HEAD;
+         pspec->pattern_length = strlen (p);
+         tmp = pspec->pattern_reversed;
+         pspec->pattern_reversed = strcpy (g_new (gchar, pspec->pattern_length + 1), p);
+         g_free (tmp);
+         g_free (pspec->pattern);
+         pspec->pattern = g_new (gchar, pspec->pattern_length + 1);
+         t = pspec->pattern + pspec->pattern_length;
+         *(t--) = 0;
+         h = pspec->pattern_reversed;
+         while (t >= pspec->pattern)
+           *(t--) = *(h++);
+       }
+    }
+
+  return pspec;
+}
+
+gboolean
+g_pattern_match_string (GPatternSpec *pspec,
+                       const gchar  *string)
+{
+  gchar *string_reversed, *t;
+  const gchar *h;
+  guint length;
+  gboolean ergo;
+
+  g_return_val_if_fail (pspec != NULL, FALSE);
+  g_return_val_if_fail (string != NULL, FALSE);
+
+  length = strlen (string);
+  string_reversed = g_new (gchar, length + 1);
+  t = string_reversed + length;
+  *(t--) = 0;
+  h = string;
+  while (t >= string_reversed)
+    *(t--) = *(h++);
+
+  ergo = g_pattern_match (pspec, length, string, string_reversed);
+  g_free (string_reversed);
+
+  return ergo;
+}
+
+gboolean
+g_pattern_match_simple (const gchar *pattern,
+                       const gchar *string)
+{
+  GPatternSpec *pspec;
+  gboolean ergo;
+
+  g_return_val_if_fail (pattern != NULL, FALSE);
+  g_return_val_if_fail (string != NULL, FALSE);
+
+  pspec = g_pattern_spec_new (pattern);
+  ergo = g_pattern_match_string (pspec, string);
+  g_pattern_spec_free (pspec);
+
+  return ergo;
+}
+
+void
+g_pattern_spec_free (GPatternSpec *pspec)
+{
+  g_return_if_fail (pspec != NULL);
+
+  g_free (pspec->pattern);
+  g_free (pspec->pattern_reversed);
+  g_free (pspec);
+}
diff --git a/gpattern.h b/gpattern.h
new file mode 100644 (file)
index 0000000..add239c
--- /dev/null
@@ -0,0 +1,58 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997, 1999  Peter Mattis, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __G_PATTERN_H__
+#define __G_PATTERN_H__
+
+#include <gtypes.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+  G_MATCH_ALL,       /* "*A?A*" */
+  G_MATCH_ALL_TAIL,  /* "*A?AA" */
+  G_MATCH_HEAD,      /* "AAAA*" */
+  G_MATCH_TAIL,      /* "*AAAA" */
+  G_MATCH_EXACT,     /* "AAAAA" */
+  G_MATCH_LAST
+} GMatchType;
+
+typedef struct _GPatternSpec    GPatternSpec;
+struct _GPatternSpec
+{
+  GMatchType match_type;
+  guint      pattern_length;
+  gchar     *pattern;
+  gchar     *pattern_reversed;
+};
+
+GPatternSpec* g_pattern_spec_new       (const gchar  *pattern);
+void          g_pattern_spec_free      (GPatternSpec *pspec);
+gboolean      g_pattern_match          (GPatternSpec *pspec,
+                                       guint         string_length,
+                                       const gchar  *string,
+                                       const gchar  *string_reversed);
+gboolean      g_pattern_match_string   (GPatternSpec *pspec,
+                                       const gchar  *string);
+gboolean      g_pattern_match_simple   (const gchar  *pattern,
+                                       const gchar  *string);
+
+G_END_DECLS
+
+#endif /* __G_PATTERN_H__ */