diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-12 | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 9 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | docs/reference/glib/tmpl/glib-unused.sgml | 19 | ||||
-rw-r--r-- | docs/reference/gobject/tmpl/closures.sgml | 3 | ||||
-rw-r--r-- | glib.h | 1 | ||||
-rw-r--r-- | glib/Makefile.am | 2 | ||||
-rw-r--r-- | glib/glib.h | 1 | ||||
-rw-r--r-- | glib/glist.c | 10 | ||||
-rw-r--r-- | glib/glist.h | 2 | ||||
-rw-r--r-- | glib/gpattern.c | 299 | ||||
-rw-r--r-- | glib/gpattern.h | 58 | ||||
-rw-r--r-- | glist.c | 10 | ||||
-rw-r--r-- | glist.h | 2 | ||||
-rw-r--r-- | gobject/ChangeLog | 13 | ||||
-rw-r--r-- | gobject/gclosure.h | 2 | ||||
-rw-r--r-- | gobject/gparam.c | 31 | ||||
-rw-r--r-- | gobject/gparam.h | 3 | ||||
-rw-r--r-- | gpattern.c | 299 | ||||
-rw-r--r-- | gpattern.h | 58 |
26 files changed, 885 insertions, 2 deletions
@@ -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. diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index b0b919e0a..75ed6febc 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -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. diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index b0b919e0a..75ed6febc 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -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. diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index b0b919e0a..75ed6febc 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -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. diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index b0b919e0a..75ed6febc 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -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. diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index b0b919e0a..75ed6febc 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -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. diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index b0b919e0a..75ed6febc 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -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. diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index b0b919e0a..75ed6febc 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -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. diff --git a/Makefile.am b/Makefile.am index 846fde012..c378bd730 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/docs/reference/glib/tmpl/glib-unused.sgml b/docs/reference/glib/tmpl/glib-unused.sgml index 6d653cbfb..8cadf158a 100644 --- a/docs/reference/glib/tmpl/glib-unused.sgml +++ b/docs/reference/glib/tmpl/glib-unused.sgml @@ -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. diff --git a/docs/reference/gobject/tmpl/closures.sgml b/docs/reference/gobject/tmpl/closures.sgml index 9647d62d1..2ff565778 100644 --- a/docs/reference/gobject/tmpl/closures.sgml +++ b/docs/reference/gobject/tmpl/closures.sgml @@ -38,12 +38,13 @@ Closures @f: -<!-- ##### TYPEDEF GCallback ##### --> +<!-- ##### USER_FUNCTION GCallback ##### --> <para> </para> + <!-- ##### STRUCT GClosure ##### --> <para> @@ -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> diff --git a/glib/Makefile.am b/glib/Makefile.am index 846fde012..c378bd730 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -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 \ diff --git a/glib/glib.h b/glib/glib.h index 9cbd7e4d4..8b32accc9 100644 --- a/glib/glib.h +++ b/glib/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> diff --git a/glib/glist.c b/glib/glist.c index 3d24bd2a6..3518221fb 100644 --- a/glib/glist.c +++ b/glib/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/glib/glist.h b/glib/glist.h index c871b5381..81ec9b3a2 100644 --- a/glib/glist.h +++ b/glib/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, diff --git a/glib/gpattern.c b/glib/gpattern.c new file mode 100644 index 000000000..6ad1c27f7 --- /dev/null +++ b/glib/gpattern.c @@ -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 index 000000000..add239c6c --- /dev/null +++ b/glib/gpattern.h @@ -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__ */ @@ -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) @@ -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/gobject/ChangeLog b/gobject/ChangeLog index 7b2b7f574..b4bf3e0c6 100644 --- a/gobject/ChangeLog +++ b/gobject/ChangeLog @@ -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: diff --git a/gobject/gclosure.h b/gobject/gclosure.h index 39531d2db..ab8974de9 100644 --- a/gobject/gclosure.h +++ b/gobject/gclosure.h @@ -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, diff --git a/gobject/gparam.c b/gobject/gparam.c index 72af807e2..511717763 100644 --- a/gobject/gparam.c +++ b/gobject/gparam.c @@ -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 diff --git a/gobject/gparam.h b/gobject/gparam.h index a393613d9..744a3978a 100644 --- a/gobject/gparam.h +++ b/gobject/gparam.h @@ -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 index 000000000..6ad1c27f7 --- /dev/null +++ b/gpattern.c @@ -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 index 000000000..add239c6c --- /dev/null +++ b/gpattern.h @@ -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__ */ |