Explorar el Código

2006-08-27 Gonzalo Paniagua Javier <[email protected]>

	* src/glib.h:
	* test/Makefile.am: Modified file.
	* test/tests.h:
	* src/Makefile.am: Modified file.
	* test/pattern.c:
	* src/gpattern.c: implemented the 3 pattern matching functions used.

	* test/ptrarray.c: fix the compare function to work with qsort.

	* test/file.c:
	* test/path.c:
	* src/gspawn.c:
	* src/gpath.c: made valgrind happy.


svn path=/trunk/mono/; revision=64428
Gonzalo Paniagua Javier hace 19 años
padre
commit
256c358fd0

+ 16 - 0
eglib/ChangeLog

@@ -1,3 +1,19 @@
+2006-08-27 Gonzalo Paniagua Javier <[email protected]>
+
+	* src/glib.h:
+	* test/Makefile.am: Modified file.
+	* test/tests.h:
+	* src/Makefile.am: Modified file.
+	* test/pattern.c:
+	* src/gpattern.c: implemented the 3 pattern matching functions used.
+
+	* test/ptrarray.c: fix the compare function to work with qsort.
+
+	* test/file.c:
+	* test/path.c:
+	* src/gspawn.c:
+	* src/gpath.c: made valgrind happy.
+
 2006-08-26 Gonzalo Paniagua Javier <[email protected]>
 
 	* test/file.c:

+ 0 - 5
eglib/TODO

@@ -21,11 +21,6 @@
 
 Important Groups:
 
-	* Pattern Matching
-	      2 g_pattern_spec_new
-	      2 g_pattern_spec_free
-	      2 g_pattern_match_string
-	
 	* Markup, used to load config files.
 	      2 g_markup_parse_context_parse
 	      2 g_markup_parse_context_new

+ 2 - 1
eglib/src/Makefile.am

@@ -22,7 +22,8 @@ libeglib_la_SOURCES = \
 	gspawn.c	\
 	gtimer.c	\
 	gdate.c		\
-	gfile.c
+	gfile.c		\
+	gpattern.c
 
 libeglib_la_CFLAGS = -Wall -Werror -D_FORTIFY_SOURCE=2
 

+ 7 - 0
eglib/src/glib.h

@@ -527,6 +527,13 @@ GFileError g_file_error_from_errno (gint err_no);
 gint       g_file_open_tmp (const gchar *tmpl, gchar **name_used, GError **error);
 gboolean   g_file_test (const gchar *filename, GFileTest test);
 
+/*
+ * Pattern matching
+ */
+typedef struct _GPatternSpec GPatternSpec;
+GPatternSpec * g_pattern_spec_new (const gchar *pattern);
+void           g_pattern_spec_free (GPatternSpec *pspec);
+gboolean       g_pattern_match_string (GPatternSpec *pspec, const gchar *string);
 
 #endif
 

+ 7 - 4
eglib/src/gpath.c

@@ -136,12 +136,14 @@ g_find_program_in_path (const gchar *program)
 {
 	char *p = g_strdup (getenv ("PATH"));
 	char *x = p, *l;
+	gchar *curdir = NULL;
 	char *save;
 
 	g_return_val_if_fail (program != NULL, NULL);
 
 	if (x == NULL || *x == '\0') {
-		x = g_get_current_dir ();
+		curdir = g_get_current_dir ();
+		x = curdir;
 	}
 
 	while ((l = strtok_r (x, G_SEARCHPATH_SEPARATOR_S, &save)) != NULL){
@@ -150,11 +152,13 @@ g_find_program_in_path (const gchar *program)
 		x = NULL;
 		probe_path = g_build_path (G_DIR_SEPARATOR_S, l, program, NULL);
 		if (access (probe_path, X_OK) == 0){
+			g_free (curdir);
 			g_free (p);
 			return probe_path;
 		}
 		g_free (probe_path);
 	}
+	g_free (curdir);
 	g_free (p);
 	return NULL;
 }
@@ -186,7 +190,6 @@ const gchar *
 g_get_home_dir (void)
 {
 	if (home_dir == NULL){
-		struct passwd *p;
 		uid_t uid;
 
 		pthread_mutex_lock (&home_lock);
@@ -199,8 +202,8 @@ g_get_home_dir (void)
 			setpwent ();
 			
 			while (getpwent_r (&pwbuf, buf, sizeof (buf), &track) == 0){
-				if (p->pw_uid == uid){
-					home_dir = g_strdup (p->pw_dir);
+				if (pwbuf.pw_uid == uid){
+					home_dir = g_strdup (pwbuf.pw_dir);
 					break;
 				}
 			}

+ 208 - 0
eglib/src/gpattern.c

@@ -0,0 +1,208 @@
+/*
+ * Simple pattern matching
+ *
+ * Author:
+ *   Gonzalo Paniagua Javier ([email protected]
+ *
+ * (C) 2006 Novell, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+typedef enum {
+	MATCH_LITERAL,
+	MATCH_ANYCHAR,
+	MATCH_ANYTHING,
+	MATCH_ANYTHING_END
+} MatchType;
+
+typedef struct {
+	MatchType type;
+	gchar *str;
+} PData;
+
+struct _GPatternSpec {
+	GSList *pattern;
+};
+
+static GSList *
+compile_pattern (const gchar *pattern)
+{
+	GSList *list;
+	gint i, len;
+	PData *data;
+	gchar c;
+	MatchType last = -1;
+	GString *str;
+	gboolean free_str;
+
+	if (pattern == NULL)
+		return NULL;
+
+	list = NULL;
+	free_str = TRUE;
+	str = g_string_new ("");
+	for (i = 0, len = strlen (pattern); i < len; i++) {
+		c = pattern [i];
+		if (c == '*' || c == '?') {
+			if (str->len > 0) {
+				data = g_new0 (PData, 1);
+				data->type = MATCH_LITERAL;
+				data->str = g_string_free (str, FALSE);
+				list = g_slist_append (list, data);
+				str = g_string_new ("");
+			}
+
+			if (last == MATCH_ANYTHING && c == '*')
+				continue;
+
+			data = g_new0 (PData, 1);
+			data->type = (c == '*') ? MATCH_ANYTHING : MATCH_ANYCHAR;
+			list = g_slist_append (list, data);
+			last = data->type;
+		} else {
+			g_string_append_c (str, c);
+			last = MATCH_LITERAL;
+		}
+	}
+
+	if (last == MATCH_ANYTHING && str->len == 0) {
+		data->type = MATCH_ANYTHING_END;
+		free_str = TRUE;
+	} else if (str->len > 0) {
+		data = g_new0 (PData, 1);
+		data->type = MATCH_LITERAL;
+		data->str = str->str;
+		free_str = FALSE;
+		list = g_slist_append (list, data);
+	}
+	g_string_free (str, free_str);
+	return list;
+}
+
+#ifdef DEBUG_PATTERN
+static void
+print_pattern (gpointer data, gpointer user_data)
+{
+	PData *d = (PData *) data;
+
+	printf ("Type: %s", d->type == MATCH_LITERAL ? "literal" : d->type == MATCH_ANYCHAR ? "any char" : "anything");
+	if (d->type == MATCH_LITERAL)
+		printf (" String: %s", d->str);
+	printf ("\n");
+}
+#endif
+
+GPatternSpec *
+g_pattern_spec_new (const gchar *pattern)
+{
+	GPatternSpec *spec;
+
+	g_return_val_if_fail (pattern != NULL, NULL);
+	spec = g_new0 (GPatternSpec, 1);
+	if (pattern) {
+		spec->pattern = compile_pattern (pattern);
+#ifdef DEBUG_PATTERN
+		g_slist_foreach (spec->pattern, print_pattern, NULL);
+		printf ("\n");
+#endif
+	}
+	return spec;
+}
+
+static void
+free_pdata (gpointer data, gpointer user_data)
+{
+	PData *d = (PData *) data;
+
+	if (d->str)
+		g_free (d->str);
+	g_free (d);
+}
+
+void
+g_pattern_spec_free (GPatternSpec *pspec)
+{
+	if (pspec) {
+		g_slist_foreach (pspec->pattern, free_pdata, NULL);
+		g_slist_free (pspec->pattern);
+		pspec->pattern = NULL;
+	}
+	g_free (pspec);
+}
+
+static gboolean
+match_string (GSList *list, const gchar *str, gint idx, gint max)
+{
+	gint len;
+
+	while (list && idx < max) {
+		PData *data = (PData *) list->data;
+
+		if (data->type == MATCH_ANYTHING_END)
+			return TRUE;
+
+		if (data->type == MATCH_LITERAL) {
+			len = strlen (data->str);
+			if (strncmp (&str [idx], data->str, len) != 0)
+				return FALSE;
+			idx += len;
+			list = list->next;
+			if (list) {
+				/* 
+				 * When recursing, we need this to avoid returning FALSE
+				 * because 'list' will not be NULL
+				 */
+				data = (PData *) list->data;
+				if (data->type == MATCH_ANYTHING_END)
+					return TRUE;
+			}
+		} else if (data->type == MATCH_ANYCHAR) {
+			idx++;
+			list = list->next;
+		} else if (data->type == MATCH_ANYTHING) {
+			while (idx < max) {
+				if (match_string (list->next, str, idx++, max))
+					return TRUE;
+			}
+			return FALSE;
+		} else {
+			g_assert_not_reached ();
+		}
+	}
+
+	return (list == NULL && idx >= max);
+}
+gboolean
+g_pattern_match_string (GPatternSpec *pspec, const gchar *string)
+{
+	g_return_val_if_fail (pspec != NULL, FALSE);
+	g_return_val_if_fail (string != NULL, FALSE);
+
+	if (pspec->pattern == NULL)
+		return FALSE;
+	return match_string (pspec->pattern, string, 0, strlen (string));
+}
+

+ 1 - 0
eglib/src/gspawn.c

@@ -190,6 +190,7 @@ g_spawn_command_line_sync (const gchar *command_line,
 		exit (1); /* TODO: What now? */
 	}
 
+	g_strfreev (argv);
 	if (standard_output)
 		close (stdout_pipe [1]);
 

+ 2 - 1
eglib/test/Makefile.am

@@ -19,7 +19,8 @@ SOURCES = \
 	shell.c		\
 	spawn.c		\
 	timer.c		\
-	file.c
+	file.c		\
+	pattern.c
 
 test_eglib_SOURCES = $(SOURCES)
 test_glib_SOURCES = $(SOURCES)

+ 2 - 1
eglib/test/file.c

@@ -52,7 +52,7 @@ test_open_tmp ()
 {
 	GError *error;
 	gint fd;
-	gchar *name;
+	gchar *name = GINT_TO_POINTER (-1);
 
 	fd = g_file_open_tmp (NULL, NULL, NULL);
 	if (fd < 0)
@@ -86,6 +86,7 @@ test_open_tmp ()
 		return FAILED ("No name returned.");
 	close (fd);
 	unlink (name);
+	g_free (name);
 	return OK;
 }
 

+ 2 - 0
eglib/test/path.c

@@ -159,11 +159,13 @@ test_ppath2 ()
 		g_setenv ("PATH", path, TRUE);
 		return FAILED ("Found something interesting here: %s", s);
 	}
+	g_free (s);
 	s = g_find_program_in_path ("test-glib");
 	if (s == NULL) {
 		g_setenv ("PATH", path, TRUE);
 		return FAILED ("It should find 'test-glib' in the current directory.");
 	}
+	g_free (s);
 	g_setenv ("PATH", path, TRUE);
 	return OK;
 }

+ 58 - 0
eglib/test/pattern.c

@@ -0,0 +1,58 @@
+#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "test.h"
+
+#define MATCH(pat,string,error_if,msg) \
+	spec = g_pattern_spec_new (pat); \
+	res = g_pattern_match_string (spec, string); \
+	if (res == error_if) \
+		return FAILED (msg " returned %s", res ? "TRUE" : "FALSE"); \
+	g_pattern_spec_free (spec);
+
+#define TEST_MATCH(pat,string,n) MATCH (pat, string, FALSE, "MATCH " #n)
+#define TEST_NO_MATCH(pat,string,n) MATCH (pat, string,TRUE, "NO_MATCH " #n)
+
+RESULT
+test_pattern_spec ()
+{
+	GPatternSpec *spec;
+	gboolean res;
+
+	/* spec = g_pattern_spec_new (NULL); */
+	printf ("%s\n", g_get_home_dir ());
+	TEST_MATCH ("*", "hola", 1);
+	TEST_MATCH ("hola", "hola", 2);
+	TEST_MATCH ("????", "hola", 3);
+	TEST_MATCH ("???a", "hola", 4);
+	TEST_MATCH ("h??a", "hola", 5);
+	TEST_MATCH ("h??*", "hola", 6);
+	TEST_MATCH ("h*", "hola", 7);
+	TEST_MATCH ("*hola", "hola", 8);
+	TEST_MATCH ("*l*", "hola", 9);
+	TEST_MATCH ("h*??", "hola", 10);
+	TEST_MATCH ("h*???", "hola", 11);
+	TEST_MATCH ("?o??", "hola", 12);
+	TEST_MATCH ("*h*o*l*a*", "hola", 13);
+	TEST_MATCH ("h*o*l*a", "hola", 14);
+	TEST_MATCH ("h?*?", "hola", 15);
+
+	TEST_NO_MATCH ("", "hola", 1);
+	TEST_NO_MATCH ("?????", "hola", 2);
+	TEST_NO_MATCH ("???", "hola", 3);
+	TEST_NO_MATCH ("*o", "hola", 4);
+	TEST_NO_MATCH ("h", "hola", 5);
+	TEST_NO_MATCH ("h*????", "hola", 6);
+
+	return OK;
+}
+
+static Test pattern_tests [] = {
+	{"g_pattern_spec*", test_pattern_spec},
+	{NULL, NULL}
+};
+
+DEFINE_TEST_GROUP_INIT(pattern_tests_init, pattern_tests)
+

+ 3 - 1
eglib/test/ptrarray.c

@@ -198,7 +198,9 @@ RESULT ptrarray_remove()
 
 static gint ptrarray_sort_compare(gconstpointer a, gconstpointer b)
 {
-	return strcmp(a, b);
+	gchar *stra = *(gchar **) a;
+	gchar *strb = *(gchar **) b;
+	return strcmp(stra, strb);
 }
 
 RESULT ptrarray_sort()

+ 2 - 0
eglib/test/tests.h

@@ -15,6 +15,7 @@ DEFINE_TEST_GROUP_INIT_H(shell_tests_init);
 DEFINE_TEST_GROUP_INIT_H(spawn_tests_init);
 DEFINE_TEST_GROUP_INIT_H(timer_tests_init);
 DEFINE_TEST_GROUP_INIT_H(file_tests_init);
+DEFINE_TEST_GROUP_INIT_H(pattern_tests_init);
 
 static Group test_groups [] = {	
 	{"string",    string_tests_init}, 
@@ -32,6 +33,7 @@ static Group test_groups [] = {
 	{"spawn",     spawn_tests_init},
 	{"timer",     timer_tests_init},
 	{"file",      file_tests_init},
+	{"pattern",   pattern_tests_init},
 	{NULL, NULL}
 };