Eina: implement eina_file_map_lines() on Windows

SVN revision: 73298
This commit is contained in:
Vincent Torri 2012-07-04 18:47:19 +00:00
parent 0b2f05e697
commit 3ef67a7c87
3 changed files with 151 additions and 0 deletions

View File

@ -303,3 +303,10 @@
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

View File

@ -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

View 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)