[patch] gnome_desktop_item_new_from_string



Here's a patch to add the call I need for Nautilus.
I also fixed some bugs I found.
Is this the right list to send it to?

May I commit?

Index: libgnome-desktop/ChangeLog
===================================================================
RCS file: /cvs/gnome/gnome-desktop/libgnome-desktop/ChangeLog,v
retrieving revision 1.64
diff -p -u -r1.64 ChangeLog
--- libgnome-desktop/ChangeLog	2002/02/14 18:48:53	1.64
+++ libgnome-desktop/ChangeLog	2002/02/20 22:04:18
@@ -1,3 +1,48 @@
+2002-02-20  Darin Adler  <darin bentspoon com>
+
+	* gnome-desktop-item.h:
+	* gnome-desktop-item.c: (readbuf_getc): Handle case where you try
+	to keep reading and the handle is NULL by treating it as EOF. This
+	is also the case at the end of the string. Set a new
+	"past_first_read" flag, used to optimize rewinding for the vast
+	majority of desktop files that fit entirely in the buffer.
+	(readbuf_gets): More g_return_if_fail.
+	(readbuf_open): Add a GError parameter, and include the
+	GnomeVFSResult in the error. Allocate the buf, which is now a
+	separate object.
+	(readbuf_new_from_string): New function, which creates a readbuf
+	from an existing string.
+	(readbuf_rewind): Reset eof and pos to make this actually work.
+	Check the past_first_read flag to avoid re-reading if the entire
+	file fits in the buffer. Reset size to trigger a read if we decide
+	to re-read the buffer. Make it try to reopen the file instead of
+	just malfunctioning if the GnomeVFSFileHandle is already NULL.
+	(readbuf_close): Free the buf if needed.
+	(read_sort_order): Pass NULL for GError * to readbuf_open.
+	(gnome_desktop_item_new_from_uri): Use the GnomeVFSResult for the
+	error code, rather than errno. Get rid of unneeded
+	gnome_vfs_file_info_clear just before gnome_vfs_file_info_unref.
+	Use the new readbuf_open, since ditem_load now takes a ReadBuf *
+	instead of a URI.
+	(gnome_desktop_item_new_from_string): New.
+	(get_encoding): Do the check for valid UTF-8 as we read the file
+	rather than re-reading it again at the end. Also get the URI from
+	the ReadBuf rather than passing it separately for the "guess by
+	location" hack, which is not really necessary, since the validate
+	heuristic will get it right anyway. Also handle the case of a NULL
+	URI properly.
+	(setup_type): Rename filename to uri to make it clearer what's
+	really going on here.
+	(sanitize): Handle the case of a NULL URI. Also add a fallback
+	name for the case where you have neither a URI nor a name in the
+	file. Also fix a storage leak.
+	(ditem_load): Take a ReadBuf * parameters instead of a URI, so we
+	can share this between the file and non-file cases. Also fix an
+	error format string to avoid segfault.
+	(ditem_save): Share the error handling code for gnome_vfs_open
+	and gnome_vfs_create since they did the same thing. Also change
+	to use GnomeVFSResult instead of errno.
+
 2002-02-14  Nitin Madhukar Yewale <nitin yewale wipro com>
 
 	reviewed by: Mark McLoughlin <mark skynet ie>
Index: libgnome-desktop/gnome-desktop-item.c
===================================================================
RCS file: /cvs/gnome/gnome-desktop/libgnome-desktop/gnome-desktop-item.c,v
retrieving revision 1.90
diff -p -u -r1.90 gnome-desktop-item.c
--- libgnome-desktop/gnome-desktop-item.c	2002/02/11 14:09:48	1.90
+++ libgnome-desktop/gnome-desktop-item.c	2002/02/20 22:04:18
@@ -35,7 +35,6 @@
 #include <glib.h>
 #include <sys/types.h>
 #include <dirent.h>
-#include <errno.h>
 #include <unistd.h>
 #include <time.h>
 #include <string.h>
@@ -95,25 +94,30 @@ typedef enum {
 	ENCODING_LEGACY_MIXED
 } Encoding;
 
-static GnomeDesktopItem * ditem_load (const char *uri,
-				      gboolean no_translations,
-				      GError **error);
-static gboolean ditem_save (GnomeDesktopItem *item,
-			    const char *uri,
-			    GError **error);
-
 /*
  * GnomeVFS reading utils, that look like the libc buffered io stuff
  */
+
+#define READ_BUF_SIZE (32 * 1024)
+
 typedef struct {
 	GnomeVFSHandle *handle;
 	char *uri;
 	gboolean eof;
-	char buf[BUFSIZ];
+	char *buf;
+	gboolean buf_needs_free;
 	gsize size;
 	gsize pos;
+	gboolean past_first_read;
 } ReadBuf;
 
+static GnomeDesktopItem *ditem_load (ReadBuf           *rb,
+				     gboolean           no_translations,
+				     GError           **error);
+static gboolean          ditem_save (GnomeDesktopItem  *item,
+				     const char        *uri,
+				     GError           **error);
+
 static int
 readbuf_getc (ReadBuf *rb)
 {
@@ -123,24 +127,29 @@ readbuf_getc (ReadBuf *rb)
 	if (rb->size == 0 ||
 	    rb->pos == rb->size) {
 		GnomeVFSFileSize bytes_read;
-		/* FIXME: handle other errors */
-		if (gnome_vfs_read (rb->handle,
-				    rb->buf,
-				    BUFSIZ,
-				    &bytes_read) != GNOME_VFS_OK) {
+
+		/* FIXME: handle errors other than EOF */
+		if (rb->handle == NULL
+		    || gnome_vfs_read (rb->handle,
+				       rb->buf,
+				       READ_BUF_SIZE,
+				       &bytes_read) != GNOME_VFS_OK) {
+			bytes_read = 0;
+		}
+
+		if (bytes_read == 0) {
 			rb->eof = TRUE;
 			return EOF;
 		}
+
+		if (rb->size != 0)
+			rb->past_first_read = TRUE;
 		rb->size = bytes_read;
 		rb->pos = 0;
 
-		if (rb->size == 0) {
-			rb->eof = TRUE;
-			return EOF;
-		}
 	}
 
-	return (int)rb->buf[rb->pos++];
+	return (guchar) rb->buf[rb->pos++];
 }
 
 /* Note, does not include the trailing \n */
@@ -150,6 +159,7 @@ readbuf_gets (char *buf, gsize bufsize, 
 	int c;
 	gsize pos;
 
+	g_return_val_if_fail (buf != NULL, NULL);
 	g_return_val_if_fail (rb != NULL, NULL);
 
 	pos = 0;
@@ -157,14 +167,12 @@ readbuf_gets (char *buf, gsize bufsize, 
 
 	do {
 		c = readbuf_getc (rb);
-		if (c == EOF ||
-		    c == '\n')
+		if (c == EOF || c == '\n')
 			break;
 		buf[pos++] = c;
 	} while (pos < bufsize-1);
 
-	if (c == EOF &&
-	    pos == 0)
+	if (c == EOF && pos == 0)
 		return NULL;
 
 	buf[pos++] = '\0';
@@ -173,40 +181,69 @@ readbuf_gets (char *buf, gsize bufsize, 
 }
 
 static ReadBuf *
-readbuf_open (const char *uri)
+readbuf_open (const char *uri, GError **error)
 {
+	GnomeVFSResult result;
 	GnomeVFSHandle *handle;
 	ReadBuf *rb;
 
 	g_return_val_if_fail (uri != NULL, NULL);
 
-	if (gnome_vfs_open (&handle, uri,
-			    GNOME_VFS_OPEN_READ) != GNOME_VFS_OK)
+	result = gnome_vfs_open (&handle, uri,
+				 GNOME_VFS_OPEN_READ);
+	if (result != GNOME_VFS_OK) {
+		g_set_error (error,
+			     /* FIXME: better errors */
+			     GNOME_DESKTOP_ITEM_ERROR,
+			     GNOME_DESKTOP_ITEM_ERROR_CANNOT_OPEN,
+			     _("Error reading file '%s': %s"),
+			     uri, gnome_vfs_result_to_string (result));
 		return NULL;
+	}
 
 	rb = g_new0 (ReadBuf, 1);
 	rb->handle = handle;
 	rb->uri = g_strdup (uri);
-	rb->eof = FALSE;
-	rb->size = 0;
-	rb->pos = 0;
+	rb->buf = g_malloc (READ_BUF_SIZE);
+	rb->buf_needs_free = TRUE;
 
 	return rb;
 }
 
+static ReadBuf *
+readbuf_new_from_string (const char *uri, const char *string, gssize length)
+{
+	ReadBuf *rb;
+
+	g_return_val_if_fail (string != NULL, NULL);
+	g_return_val_if_fail (length >= 0, NULL);
+
+	rb = g_new0 (ReadBuf, 1);
+	rb->uri = g_strdup (uri);
+	rb->buf = (char *) string;
+	rb->size = length;
+
+	return rb;
+}
+
 static gboolean
 readbuf_rewind (ReadBuf *rb)
 {
-	if (gnome_vfs_seek (rb->handle,
-			    GNOME_VFS_SEEK_START, 0) == GNOME_VFS_OK)
+	rb->eof = FALSE;
+	rb->pos = 0;
+	if (!rb->past_first_read)
 		return TRUE;
-
-	gnome_vfs_close (rb->handle);
-	rb->handle = NULL;
+	rb->size = 0;
+	if (rb->handle != NULL) {
+		if (gnome_vfs_seek (rb->handle,
+				    GNOME_VFS_SEEK_START, 0) == GNOME_VFS_OK)
+			return TRUE;
+		gnome_vfs_close (rb->handle);
+		rb->handle = NULL;
+	}
 	if (gnome_vfs_open (&rb->handle, rb->uri,
 			    GNOME_VFS_OPEN_READ) == GNOME_VFS_OK)
 		return TRUE;
-
 	return FALSE;
 }
 
@@ -215,14 +252,12 @@ readbuf_close (ReadBuf *rb)
 {
 	if (rb->handle != NULL)
 		gnome_vfs_close (rb->handle);
-	rb->handle = NULL;
 	g_free (rb->uri);
-	rb->uri = NULL;
-
+	if (rb->buf_needs_free)
+		g_free (rb->buf);
 	g_free (rb);
 }
 
-
 static GnomeDesktopItemType G_GNUC_CONST
 type_from_string (const char *type)
 {
@@ -361,7 +396,7 @@ read_sort_order (GnomeDesktopItem *item,
 	ReadBuf *rb;
 
 	file = g_build_filename (dir, ".order", NULL);
-	rb = readbuf_open (file);
+	rb = readbuf_open (file, NULL);
 	g_free (file);
 
 	if (rb == NULL)
@@ -469,19 +504,22 @@ gnome_desktop_item_new_from_uri (const c
 	char *subfn, *dir;
 	GnomeVFSFileInfo *info;
 	time_t mtime = 0;
+	ReadBuf *rb;
+	GnomeVFSResult result;
 
 	g_return_val_if_fail (uri != NULL, NULL);
 
 	info = gnome_vfs_file_info_new ();
 
-	if (gnome_vfs_get_file_info (uri, info,
-				     GNOME_VFS_FILE_INFO_DEFAULT) != GNOME_VFS_OK) {
+	result = gnome_vfs_get_file_info (uri, info,
+				          GNOME_VFS_FILE_INFO_DEFAULT);
+	if (result != GNOME_VFS_OK) {
 		g_set_error (error,
 			     /* FIXME: better errors */
 			     GNOME_DESKTOP_ITEM_ERROR,
 			     GNOME_DESKTOP_ITEM_ERROR_CANNOT_OPEN,
 			     _("Error reading file '%s': %s"),
-			     uri, strerror (errno));
+			     uri, gnome_vfs_result_to_string (result));
 
 		gnome_vfs_file_info_unref (info);
 
@@ -512,11 +550,17 @@ gnome_desktop_item_new_from_uri (const c
                 subfn = g_strdup (uri);
 	}
 
-	gnome_vfs_file_info_clear (info);
 	gnome_vfs_file_info_unref (info);
+
+	rb = readbuf_open (subfn, error);
+	
+	if (rb == NULL) {
+		g_free (subfn);
+		return NULL;
+	}
 
-	retval = ditem_load (subfn,
-			     flags & GNOME_DESKTOP_ITEM_LOAD_NO_TRANSLATIONS,
+	retval = ditem_load (rb,
+			     (flags & GNOME_DESKTOP_ITEM_LOAD_NO_TRANSLATIONS) != 0,
 			     error);
 
         if (retval == NULL) {
@@ -547,6 +591,45 @@ gnome_desktop_item_new_from_uri (const c
 }
 
 /**
+ * gnome_desktop_item_new_from_string:
+ * @string: string to load the GnomeDesktopItem from
+ * @length: length of string, or -1 to use strlen
+ * @flags: Flags to influence the loading process
+ * @error: place to put errors
+ *
+ * This function turns the contents of the string into a GnomeDesktopItem.
+ *
+ * Returns: The newly loaded item.
+ */
+GnomeDesktopItem *
+gnome_desktop_item_new_from_string (const char *uri,
+				    const char *string,
+				    gssize length,
+				    GnomeDesktopItemLoadFlags flags,
+				    GError **error)
+{
+	GnomeDesktopItem *retval;
+	ReadBuf *rb;
+
+	g_return_val_if_fail (string != NULL, NULL);
+	g_return_val_if_fail (length >= -1, NULL);
+
+	rb = readbuf_new_from_string (uri, string, length);
+
+	retval = ditem_load (rb,
+			     (flags & GNOME_DESKTOP_ITEM_LOAD_NO_TRANSLATIONS) != 0,
+			     error);
+
+        if (retval == NULL) {
+		return NULL;
+	}
+	
+	/* FIXME: Sort order? */
+
+        return retval;
+}
+
+/**
  * gnome_desktop_item_save:
  * @item: A desktop item
  * @under: A new uri (location) for this #GnomeDesktopItem
@@ -2636,15 +2719,13 @@ get_encoding_from_locale (const char *lo
 }
 
 static Encoding
-get_encoding (const char *uri, ReadBuf *rb)
+get_encoding (ReadBuf *rb)
 {
-	gboolean     old_kde = FALSE;
-	GnomeVFSURI *tmp_uri;
-	int          c;
-	char         buf [BUFSIZ];
-	char        *path;
-
-	gchar *contents = NULL;
+	gboolean old_kde = FALSE;
+	int      c;
+	char     buf [BUFSIZ];
+	char    *path;
+	gboolean all_valid_utf8 = TRUE;
 
 	while (readbuf_gets (buf, sizeof (buf), rb) != NULL) {
 		if (strncmp (GNOME_DESKTOP_ITEM_ENCODING,
@@ -2672,42 +2753,28 @@ get_encoding (const char *uri, ReadBuf *
 			/* don't break yet, we still want to support
 			 * Encoding even here */
 		}
+		if (all_valid_utf8 && ! g_utf8_validate (buf, -1, NULL))
+			all_valid_utf8 = FALSE;
 	}
 
 	if (old_kde)
 		return ENCODING_LEGACY_MIXED;
 
 	/* try to guess by location */
-	if (strstr (uri, "gnome/apps/") != NULL) {
+	if (rb->uri != NULL && strstr (rb->uri, "gnome/apps/") != NULL) {
 		/* old gnome */
 		return ENCODING_LEGACY_MIXED;
 	}
-
 
-	/* FIXME: fix for gnome-vfs */
-	/* A dillema, new KDE files are in UTF-8 but have no Encoding
+	/* A dilemma, new KDE files are in UTF-8 but have no Encoding
 	 * info, at this time we really can't tell.  The best thing to
 	 * do right now is to just assume UTF-8 if the whole file
 	 * validates as utf8 I suppose */
 
-	tmp_uri = gnome_vfs_uri_new (uri);
-	path = gnome_vfs_uri_get_path (tmp_uri);
-	g_free (tmp_uri);
-
-	if (!g_file_get_contents (path, &contents, NULL, NULL))
-		return ENCODING_LEGACY_MIXED;
-
-	if (contents == NULL) /* Ooooooops ! */
-		return ENCODING_LEGACY_MIXED;
-
-	if (g_utf8_validate (contents, -1, NULL)) {
-		g_free (contents);
+	if (all_valid_utf8)
 		return ENCODING_UTF8;
-	} else {
-		g_free (contents);
+	else
 		return ENCODING_LEGACY_MIXED;
-	}
-
 }
 
 static char *
@@ -2890,12 +2957,12 @@ insert_key (GnomeDesktopItem *item,
 }
 
 static void
-setup_type (GnomeDesktopItem *item, const char *filename)
+setup_type (GnomeDesktopItem *item, const char *uri)
 {
 	const char *type = g_hash_table_lookup (item->main_hash,
 						GNOME_DESKTOP_ITEM_TYPE);
-	if (type == NULL && filename != NULL) {
-		char *base = g_path_get_basename (filename);
+	if (type == NULL && uri != NULL) {
+		char *base = g_path_get_basename (uri);
 		if (base != NULL &&
 		    strcmp (base, ".directory") == 0) {
 			/* This gotta be a directory */
@@ -2940,7 +3007,7 @@ try_english_key (GnomeDesktopItem *item,
 
 
 static void
-sanitize (GnomeDesktopItem *item, const char *file)
+sanitize (GnomeDesktopItem *item, const char *uri)
 {
 	const char *type;
 
@@ -2961,11 +3028,14 @@ sanitize (GnomeDesktopItem *item, const 
 	if (lookup (item, GNOME_DESKTOP_ITEM_NAME) == NULL) {
 		char *name = try_english_key (item, GNOME_DESKTOP_ITEM_NAME);
 		/* If no name, use the basename */
+		if (name == NULL && uri != NULL)
+			name = g_path_get_basename (uri);
+		/* If no uri either, use same default as gnome_desktop_item_new */
 		if (name == NULL)
-			name = g_path_get_basename (file);
+			name = g_strdup (_("No name"));
 		g_hash_table_replace (item->main_hash,
 				      g_strdup (GNOME_DESKTOP_ITEM_NAME), 
-				      g_path_get_basename (file));
+				      name);
 		item->keys = g_list_prepend
 			(item->keys, g_strdup (GNOME_DESKTOP_ITEM_NAME));
 	}
@@ -2998,11 +3068,10 @@ enum {
 };
 
 static GnomeDesktopItem *
-ditem_load (const char *uri,
+ditem_load (ReadBuf *rb,
 	    gboolean no_translations,
 	    GError **error)
 {
-	ReadBuf *rb;
 	int state;
 	char CharBuffer [1024];
 	char *next = CharBuffer;
@@ -3012,20 +3081,8 @@ ditem_load (const char *uri,
 	Section *cur_section = NULL;
 	char *key = NULL;
 	gboolean old_kde = FALSE;
-
-	rb = readbuf_open (uri);
-	
-	if (rb == NULL) {
-		g_set_error (error,
-			     /* FIXME: better errors */
-			     GNOME_DESKTOP_ITEM_ERROR,
-			     GNOME_DESKTOP_ITEM_ERROR_CANNOT_OPEN,
-			     _("Error reading file '%s': %s"),
-			     uri, strerror (errno));
-		return NULL;
-	}
 
-	encoding = get_encoding (uri, rb);
+	encoding = get_encoding (rb);
 	if (encoding == ENCODING_UNKNOWN) {
 		readbuf_close (rb);
 		/* spec says, don't read this file */
@@ -3033,19 +3090,19 @@ ditem_load (const char *uri,
 			     GNOME_DESKTOP_ITEM_ERROR,
 			     GNOME_DESKTOP_ITEM_ERROR_UNKNOWN_ENCODING,
 			     _("Unknown encoding of: %s"),
-			     uri);
+			     rb->uri);
 		return NULL;
 	}
 
 	/* Rewind since get_encoding goes through the file */
-	if ( ! readbuf_rewind (rb)) {
+	if (! readbuf_rewind (rb)) {
 		readbuf_close (rb);
 		/* spec says, don't read this file */
 		g_set_error (error,
 			     GNOME_DESKTOP_ITEM_ERROR,
 			     GNOME_DESKTOP_ITEM_ERROR_CANNOT_OPEN,
-			     _("Error rewinding file '%s': %s"),
-			     uri);
+			     _("Error rewinding file '%s'"),
+			     rb->uri);
 		return NULL;
 	}
 
@@ -3202,10 +3259,10 @@ rb->eof=FALSE;
 	/* Here we do a little bit of sanitazition */
 
 	/* sanitize some things */
-	sanitize (item, uri);
+	sanitize (item, rb->uri);
 
 	/* make sure that we set up the type */
-	setup_type (item, uri);
+	setup_type (item, rb->uri);
 
 	return item;
 }
@@ -3255,26 +3312,15 @@ ditem_save (GnomeDesktopItem *item, cons
 	GnomeVFSHandle *handle;
 	GnomeVFSResult result;
 	result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_WRITE);
-	if (result == GNOME_VFS_ERROR_NOT_FOUND) {
+	if (result == GNOME_VFS_ERROR_NOT_FOUND)
 		result = gnome_vfs_create (&handle, uri, GNOME_VFS_OPEN_WRITE, TRUE, GNOME_VFS_PERM_USER_ALL);
-		if (result != GNOME_VFS_OK) {
-			g_set_error (error,
-				     /* FIXME: better errors */
-				     GNOME_DESKTOP_ITEM_ERROR,
-				     GNOME_DESKTOP_ITEM_ERROR_CANNOT_OPEN,
-				     _("Error writing file '%s': %s"),
-				     uri, strerror (errno));
-
-			return FALSE;
-		}
-	}
 	if (result != GNOME_VFS_OK) {
 		g_set_error (error,
 			     /* FIXME: better errors */
 			     GNOME_DESKTOP_ITEM_ERROR,
 			     GNOME_DESKTOP_ITEM_ERROR_CANNOT_OPEN,
 			     _("Error writing file '%s': %s"),
-			     uri, strerror (errno));
+			     uri, gnome_vfs_result_to_string (result));
 
 		return FALSE;
 	}
Index: libgnome-desktop/gnome-desktop-item.h
===================================================================
RCS file: /cvs/gnome/gnome-desktop/libgnome-desktop/gnome-desktop-item.h,v
retrieving revision 1.36
diff -p -u -r1.36 gnome-desktop-item.h
--- libgnome-desktop/gnome-desktop-item.h	2002/01/17 02:09:59	1.36
+++ libgnome-desktop/gnome-desktop-item.h	2002/02/20 22:04:18
@@ -137,6 +137,11 @@ GnomeDesktopItem *      gnome_desktop_it
 GnomeDesktopItem *      gnome_desktop_item_new_from_uri      (const char                 *uri,
 							      GnomeDesktopItemLoadFlags   flags,
 							      GError                    **error);
+GnomeDesktopItem *      gnome_desktop_item_new_from_string   (const char                 *uri,
+							      const char                 *string,
+							      gssize                      length,
+							      GnomeDesktopItemLoadFlags   flags,
+							      GError                    **error);
 GnomeDesktopItem *      gnome_desktop_item_copy              (const GnomeDesktopItem     *item);
 
 /* if under is NULL save in original location */
===================================================================

    -- Darin



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]