Index: libgimpconfig/gimpscanner.c
===================================================================
RCS file: /cvs/gnome/gimp/libgimpconfig/gimpscanner.c,v
retrieving revision 1.28
diff -u -p -r1.28 gimpscanner.c
--- libgimpconfig/gimpscanner.c	7 Feb 2005 01:10:50 -0000	1.28
+++ libgimpconfig/gimpscanner.c	10 Mar 2005 01:19:02 -0000
@@ -33,11 +33,16 @@
 
 #include <sys/types.h>
 
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
 #include <glib-object.h>
 #include <glib/gstdio.h>
 
 #ifdef G_OS_WIN32
 #include <io.h>
+#include <windows.h>
 #endif
 
 #include "libgimpbase/gimpbase.h"
@@ -50,22 +55,31 @@
 #include "libgimp/libgimp-intl.h"
 
 
+/*  #define GIMP_SCANNER_PROFILE  */
+
+
 typedef struct
 {
-  gint      fd;
-  gchar    *name;
-  GError  **error;
+  gchar        *name;
+  gint          fd;
+  gssize        len;
+  gpointer      map;
+  GError      **error;
+#ifdef GIMP_SCANNER_PROFILE
+  GTimer       *timer;
+#endif
 } GimpScannerData;
 
 
 /*  local function prototypes  */
 
-static GScanner * gimp_scanner_new     (const gchar  *name,
-                                        gint          fd,
-                                        GError      **error);
-static void       gimp_scanner_message (GScanner     *scanner,
-                                        gchar        *message,
-                                        gboolean      is_error);
+static GScanner * gimp_scanner_new        (const gchar  *name,
+                                           gint          fd,
+                                           GError      **error);
+static gboolean   gimp_scanner_memory_map (GScanner     *scanner);
+static void       gimp_scanner_message    (GScanner     *scanner,
+                                           gchar        *message,
+                                           gboolean      is_error);
 
 
 /*  public functions  */
@@ -105,12 +119,10 @@ gimp_scanner_new_file (const gchar  *fil
       return NULL;
     }
 
-  /* gimp_scanner_new() takes a "name" for the scanner, not a filename. Thus
-   * do convert to UTF-8.
-   */
   scanner = gimp_scanner_new (gimp_filename_to_utf8 (filename), fd, error);
 
-  g_scanner_input_file (scanner, fd);
+  if (! gimp_scanner_memory_map (scanner))
+    g_scanner_input_file (scanner, fd);
 
   return scanner;
 }
@@ -157,10 +169,14 @@ gimp_scanner_new (const gchar  *name,
 
   data = g_new0 (GimpScannerData, 1);
 
-  data->name  = g_strdup (name);
   data->fd    = fd;
+  data->name  = g_strdup (name);
   data->error = error;
 
+#ifdef GIMP_SCANNER_PROFILE
+  data->timer = g_timer_new ();
+#endif
+
   scanner->user_data   = data;
   scanner->msg_handler = gimp_scanner_message;
 
@@ -174,6 +190,49 @@ gimp_scanner_new (const gchar  *name,
   return scanner;
 }
 
+static gboolean
+gimp_scanner_memory_map (GScanner *scanner)
+{
+#if defined(HAVE_MMAP) || defined(G_OS_WIN32)
+  GimpScannerData *data = scanner->user_data;
+  struct stat      st;
+
+  g_return_val_if_fail (data->map == NULL, FALSE);
+
+  if (fstat (data->fd, &st) != -1 && S_ISREG (st.st_mode))
+    {
+      gssize    len = st.st_size;
+      gpointer  map;
+
+#ifdef G_OS_WIN32
+      HANDLE    handle = CreateFileMapping ((HANDLE) _get_osfhandle (data->fd),
+                                            NULL, PAGE_READONLY, 0, 0, NULL);
+      map = MapViewOfFile (handle, FILE_MAP_READ, 0, 0, 0);
+      CloseHandle (handle);
+#else
+      map = mmap (NULL, len, PROT_READ, MAP_PRIVATE, data->fd, 0);
+#endif
+
+      if (map)
+        {
+#ifndef HAVE_BROKEN_MMAP
+          close (data->fd);
+          data->fd  = -1;
+#endif
+
+          data->map = map;
+          data->len = len;
+
+          g_scanner_input_text (scanner, map, len);
+
+          return TRUE;
+        }
+    }
+#endif
+
+  return FALSE;
+}
+
 /**
  * gimp_scanner_destroy:
  * @scanner:
@@ -189,12 +248,29 @@ gimp_scanner_destroy (GScanner *scanner)
 
   data = scanner->user_data;
 
+#ifdef HAVE_MMAP
+  if (data->map)
+    munmap (data->map, data->len);
+#endif
+
+#ifdef G_OS_WIN32
+  if (data->map)
+    UnmapViewOfFile (data->map);
+#endif
+
   if (data->fd > 0)
     {
       if (close (data->fd))
         g_warning ("%s: could not close file descriptor: %s",
                    G_STRFUNC, g_strerror (errno));
     }
+
+#ifdef GIMP_SCANNER_PROFILE
+  g_printerr ("GimpScanner (%s) took %g seconds\n",
+              data->name ? data->name : "<text>",
+              g_timer_elapsed (data->timer, NULL));
+  g_timer_destroy (data->timer);
+#endif
 
   g_free (data->name);
   g_free (data);
