mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 15:36:14 +01:00
92dfa96114
Fri Oct 12 18:24:02 2001 Tim Janik <timj@gtk.org> * glib/gpattern.[hc]: make struct _GPatternSpec and GMatchType private. (g_pattern_equal): new function to return equality of two patterns (required because GPatternSpec is private now). (g_pattern_spec_new): fix bug wrg wildcard counting which produced incorrect pattern specs (discovered by Matthias Clasen). optimized code so we just keep one compiled pattern string now. correctly canonicalize patterns. reduce string walks, optimize decision about MATCH_ALL vs. MATCH_ALL_TAIL. (g_pattern_match_string): call just g_pattern_match() with NULL reversed string. (g_pattern_match): allow NULL reversed strings now, reverse_dup strings on demand. * tests/patterntest.c (test_compilation): added an extended testcase for pattern matching from Matthias Clasen <matthiasc@poet.de>. Sat Oct 13 06:58:23 2001 Tim Janik <timj@gtk.org> * glib/tmpl/patterns.sgml: amended documentation.
226 lines
5.8 KiB
C
226 lines
5.8 KiB
C
/* GLIB - Library of useful routines for C programming
|
||
* Copyright (C) 2001 Matthias Clasen <matthiasc@poet.de>
|
||
*
|
||
* 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 "glib.h"
|
||
|
||
|
||
/* keep enum and structure of gpattern.c and patterntest.c in sync */
|
||
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;
|
||
struct _GPatternSpec
|
||
{
|
||
GMatchType match_type;
|
||
guint pattern_length;
|
||
gchar *pattern;
|
||
};
|
||
|
||
|
||
static gchar *
|
||
match_type_name (GMatchType match_type)
|
||
{
|
||
switch (match_type)
|
||
{
|
||
case G_MATCH_ALL:
|
||
return "G_MATCH_ALL";
|
||
break;
|
||
case G_MATCH_ALL_TAIL:
|
||
return "G_MATCH_ALL_TAIL";
|
||
break;
|
||
case G_MATCH_HEAD:
|
||
return "G_MATCH_HEAD";
|
||
break;
|
||
case G_MATCH_TAIL:
|
||
return "G_MATCH_TAIL";
|
||
break;
|
||
case G_MATCH_EXACT:
|
||
return "G_MATCH_EXACT";
|
||
break;
|
||
default:
|
||
return "unknown GMatchType";
|
||
break;
|
||
}
|
||
}
|
||
|
||
static gboolean
|
||
test_compilation (gchar *src,
|
||
GMatchType match_type,
|
||
gchar *pattern)
|
||
{
|
||
GPatternSpec *spec;
|
||
|
||
g_print ("compiling \"%s\" \t", src);
|
||
spec = g_pattern_spec_new (src);
|
||
|
||
if (spec->match_type != match_type)
|
||
{
|
||
g_print ("failed \t(match_type: %s, expected %s)\n",
|
||
match_type_name (spec->match_type),
|
||
match_type_name (match_type));
|
||
return FALSE;
|
||
}
|
||
|
||
if (strcmp (spec->pattern, pattern) != 0)
|
||
{
|
||
g_print ("failed \t(pattern: \"%s\", expected \"%s\")\n",
|
||
spec->pattern,
|
||
pattern);
|
||
return FALSE;
|
||
}
|
||
|
||
if (spec->pattern_length != strlen (spec->pattern))
|
||
{
|
||
g_print ("failed \t(pattern_length: %d, expected %d)\n",
|
||
spec->pattern_length,
|
||
strlen (spec->pattern));
|
||
return FALSE;
|
||
}
|
||
|
||
g_print ("passed (%s: \"%s\")\n",
|
||
match_type_name (spec->match_type),
|
||
spec->pattern);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
test_match (gchar *pattern,
|
||
gchar *string,
|
||
gboolean match)
|
||
{
|
||
g_print ("matching \"%s\" against \"%s\" \t", string, pattern);
|
||
|
||
if (g_pattern_match_simple (pattern, string) != match)
|
||
{
|
||
g_print ("failed \t(unexpected %s)\n", (match ? "mismatch" : "match"));
|
||
return FALSE;
|
||
}
|
||
|
||
g_print ("passed (%s)\n", match ? "match" : "nomatch");
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
test_equal (gchar *pattern1,
|
||
gchar *pattern2,
|
||
gboolean expected)
|
||
{
|
||
GPatternSpec *p1 = g_pattern_spec_new (pattern1);
|
||
GPatternSpec *p2 = g_pattern_spec_new (pattern2);
|
||
gboolean equal = g_pattern_spec_equal (p1, p2);
|
||
|
||
g_print ("comparing \"%s\" with \"%s\" \t", pattern1, pattern2);
|
||
|
||
if (expected != equal)
|
||
{
|
||
g_print ("failed \t{%s, %u, \"%s\"} %s {%s, %u, \"%s\"}\n",
|
||
match_type_name (p1->match_type), p1->pattern_length, p1->pattern,
|
||
expected ? "!=" : "==",
|
||
match_type_name (p2->match_type), p2->pattern_length, p2->pattern);
|
||
}
|
||
else
|
||
g_print ("passed (%s)\n", equal ? "equal" : "unequal");
|
||
|
||
g_pattern_spec_free (p1);
|
||
g_pattern_spec_free (p2);
|
||
|
||
return expected == equal;
|
||
}
|
||
|
||
#define TEST_COMPILATION(src, type, pattern) { \
|
||
total++; \
|
||
if (test_compilation (src, type, pattern)) \
|
||
passed++; \
|
||
else \
|
||
failed++; \
|
||
}
|
||
|
||
#define TEST_MATCH(pattern, string, match) { \
|
||
total++; \
|
||
if (test_match (pattern, string, match)) \
|
||
passed++; \
|
||
else \
|
||
failed++; \
|
||
}
|
||
|
||
#define TEST_EQUAL(pattern1, pattern2, match) { \
|
||
total++; \
|
||
if (test_equal (pattern1, pattern2, match)) \
|
||
passed++; \
|
||
else \
|
||
failed++; \
|
||
}
|
||
|
||
int
|
||
main (int argc, char** argv)
|
||
{
|
||
gint total = 0;
|
||
gint passed = 0;
|
||
gint failed = 0;
|
||
gchar *string;
|
||
|
||
TEST_COMPILATION("*A?B*", G_MATCH_ALL, "*A?B*");
|
||
TEST_COMPILATION("ABC*DEFGH", G_MATCH_ALL_TAIL, "HGFED*CBA");
|
||
TEST_COMPILATION("ABCDEF*GH", G_MATCH_ALL, "ABCDEF*GH");
|
||
TEST_COMPILATION("ABC**?***??**DEF*GH", G_MATCH_ALL, "ABC*?*??*DEF*GH");
|
||
TEST_COMPILATION("*A?AA", G_MATCH_ALL_TAIL, "AA?A*");
|
||
TEST_COMPILATION("ABCD*", G_MATCH_HEAD, "ABCD");
|
||
TEST_COMPILATION("*ABCD", G_MATCH_TAIL, "DCBA");
|
||
TEST_COMPILATION("ABCDE", G_MATCH_EXACT, "ABCDE");
|
||
|
||
TEST_EQUAL ("*A?B*", "*A?B*", TRUE);
|
||
TEST_EQUAL ("A*BCD", "A*BCD", TRUE);
|
||
TEST_EQUAL ("ABCD*", "ABCD****", TRUE);
|
||
TEST_EQUAL ("A1*", "A1*", TRUE);
|
||
TEST_EQUAL ("*YZ", "*YZ", TRUE);
|
||
TEST_EQUAL ("A1x", "A1x", TRUE);
|
||
TEST_EQUAL ("AB*CD", "AB**CD", TRUE);
|
||
TEST_EQUAL ("AB*CD", "AB*?*CD", FALSE);
|
||
TEST_EQUAL ("ABC*", "ABC?", FALSE);
|
||
|
||
TEST_MATCH("*x", "x", TRUE);
|
||
TEST_MATCH("*x", "xx", TRUE);
|
||
TEST_MATCH("*x", "yyyx", TRUE);
|
||
TEST_MATCH("*x", "yyxy", FALSE);
|
||
TEST_MATCH("?x", "x", FALSE);
|
||
TEST_MATCH("?x", "xx", TRUE);
|
||
TEST_MATCH("?x", "yyyx", FALSE);
|
||
TEST_MATCH("?x", "yyxy", FALSE);
|
||
TEST_MATCH("*?x", "xx", TRUE);
|
||
TEST_MATCH("?*x", "xx", TRUE);
|
||
TEST_MATCH("*?x", "x", FALSE);
|
||
TEST_MATCH("?*x", "x", FALSE);
|
||
TEST_MATCH("*?*x", "yx", TRUE);
|
||
TEST_MATCH("*?*x", "xxxx", TRUE);
|
||
|
||
string = g_convert ("<EFBFBD>x", -1, "UTF-8", "Latin1", NULL, NULL, NULL);
|
||
TEST_MATCH("*x", string, TRUE);
|
||
TEST_MATCH("?x", string, TRUE);
|
||
TEST_MATCH("??x", string, FALSE);
|
||
|
||
g_print ("\n%u tests passed, %u failed\n", passed, failed);
|
||
|
||
return 0;
|
||
}
|