Eina: implement eina_file_map_lines() on Windows
authorcaro <caro>
Wed, 4 Jul 2012 18:47:19 +0000 (18:47 +0000)
committercaro <caro@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 4 Jul 2012 18:47:19 +0000 (18:47 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/eina@73298 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

ChangeLog
NEWS
src/lib/eina_file_win32.c

index 22d070f..db8b643 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
         passthrough to malloc for debgging purposes and memory footrpint
         comparisons at runtime.
 
+2012-07-01 Vincent Torri
+
+        * remove --enable-coverage from configure options,
+
+2012-07-04 Vincent Torri
+
+        * implement eina_file_map_lines() on Windows
diff --git a/NEWS b/NEWS
index f53279e..a5360b1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,11 @@ Fixes:
     * Portability issue with Eina_Value test suite when unsigned where not promoted to
     unsigned long (case on Itanium).
     * Fix issue in the XML parser when a tag was in a comment or a CDATA.
+    * Implement eina_file_map_lines() on Windows
+
+Removal:
+    * configure options: --disable-posix-threads, --disable-win32-threads,
+      --enable-coverage
 
 Eina 1.2.0
 
index 2baa29f..f507bf9 100644 (file)
@@ -91,6 +91,7 @@ void *alloca (size_t);
 #define MAP_FAILED ((void *)-1)
 
 typedef struct _Eina_File_Iterator        Eina_File_Iterator;
+typedef struct _Eina_Lines_Iterator       Eina_Lines_Iterator;
 typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator;
 typedef struct _Eina_File_Map             Eina_File_Map;
 
@@ -106,6 +107,19 @@ struct _Eina_File_Iterator
    char            dir[1];
 };
 
+struct _Eina_Lines_Iterator
+{
+   Eina_Iterator iterator;
+
+   Eina_File *fp;
+   const char *map;
+   const char *end;
+
+   int boundary;
+
+   Eina_File_Lines current;
+};
+
 struct _Eina_File_Direct_Iterator
 {
    Eina_Iterator         iterator;
@@ -561,6 +575,90 @@ _eina_file_win32_escape(const char *path, size_t *length)
    return result;
 }
 
+/* search '\r' and '\n' by preserving cache locality and page locality
+   in doing a search inside 4K boundary.
+ */
+static inline const char *
+_eina_fine_eol(const char *start, int boundary, const char *end)
+{
+   const char *cr;
+   const char *lf;
+   unsigned long long chunk;
+
+   while (start < end)
+     {
+        chunk = start + boundary < end ? boundary : end - start;
+        cr = memchr(start, '\r', chunk);
+        lf = memchr(start, '\n', chunk);
+        if (cr)
+          {
+             if (lf && lf < cr)
+               return lf + 1;
+             return cr + 1;
+          }
+        else if (lf)
+           return lf + 1;
+
+        start += chunk;
+        boundary = 4096;
+     }
+
+   return end;
+}
+
+static Eina_Bool
+_eina_file_map_lines_iterator_next(Eina_Lines_Iterator *it, void **data)
+{
+   const char *eol;
+   unsigned char match;
+
+   if (it->current.line.end >= it->end)
+     return EINA_FALSE;
+
+   match = *it->current.line.end;
+   while ((*it->current.line.end == '\n' || *it->current.line.end == '\r')
+          && it->current.line.end < it->end)
+     {
+        if (match == *it->current.line.end)
+          it->current.line.index++;
+        it->current.line.end++;
+     }
+   it->current.line.index++;
+
+   if (it->current.line.end == it->end)
+     return EINA_FALSE;
+
+   eol = _eina_fine_eol(it->current.line.end,
+                        it->boundary,
+                        it->end);
+   it->boundary = (uintptr_t) eol & 0x3FF;
+   if (it->boundary == 0) it->boundary = 4096;
+
+   it->current.line.start = it->current.line.end;
+
+   it->current.line.end = eol;
+   it->current.length = eol - it->current.line.start - 1;
+
+   *data = &it->current;
+   return EINA_TRUE;
+}
+
+static Eina_File *
+_eina_file_map_lines_iterator_container(Eina_Lines_Iterator *it)
+{
+   return it->fp;
+}
+
+static void
+_eina_file_map_lines_iterator_free(Eina_Lines_Iterator *it)
+{
+   eina_file_map_free(it->fp, (void*) it->map);
+   eina_file_close(it->fp);
+
+   EINA_MAGIC_SET(&it->iterator, 0);
+   free(it);
+}
+
 
 /**
  * @endcond
@@ -1062,6 +1160,47 @@ eina_file_map_all(Eina_File *file, Eina_File_Populate rule __UNUSED__)
    return NULL;
 }
 
+EAPI Eina_Iterator *
+eina_file_map_lines(Eina_File *file)
+{
+   Eina_Lines_Iterator *it;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
+
+   if (file->length == 0) return NULL;
+
+   it = calloc(1, sizeof (Eina_Lines_Iterator));
+   if (!it) return NULL;
+
+   EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
+
+   it->map = eina_file_map_all(file, EINA_FILE_SEQUENTIAL);
+   if (!it->map)
+     {
+        free(it);
+        return NULL;
+     }
+
+   eina_lock_take(&file->lock);
+   file->refcount++;
+   eina_lock_release(&file->lock);
+
+   it->fp = file;
+   it->boundary = 4096;
+   it->current.line.start = it->map;
+   it->current.line.end = it->current.line.start;
+   it->current.line.index = 0;
+   it->current.length = 0;
+   it->end = it->map + it->fp->length;
+
+   it->iterator.version = EINA_ITERATOR_VERSION;
+   it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_map_lines_iterator_next);
+   it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_map_lines_iterator_container);
+   it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_map_lines_iterator_free);
+
+   return &it->iterator;
+}
+
 EAPI void *
 eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
                   unsigned long int offset, unsigned long int length)