diff options
author | Daniel Willmann <d.willmann@samsung.com> | 2013-03-14 17:21:48 +0000 |
---|---|---|
committer | Daniel Willmann <d.willmann@samsung.com> | 2013-03-14 17:21:48 +0000 |
commit | f90726cf35bb89f14af7b57d8360848a8228dce9 (patch) | |
tree | aeb183db50a4a51fbc89542c34a4b8878522f18f /src/lib/eina/eina_file_win32.c | |
parent | 8aed36e91400df78554623debd9f3154fa9d0657 (diff) | |
download | efl-f90726cf35bb89f14af7b57d8360848a8228dce9.tar.gz |
Revert "eina: improve portability of Eina_File."
This reverts commit c002d113f11310b5367bfcd300c0add84bf6f57f.
This commit reliably breaks builds with clang. Please test with
export CC=clang before you commit again.
export CC=clang
./autogen.sh --enable-multisense && make -j 10
The error Jenkins gets (I confirmed locally):
/bin/bash: line 1: 13549 Segmentation fault (core dumped) EFL_RUN_IN_TREE=1 ./bin/edje/edje_cc -id . -fd . -id ./tests/emotion/data tests/emotion/data/theme.edc tests/emotion/data/theme.edj
Diffstat (limited to 'src/lib/eina/eina_file_win32.c')
-rw-r--r-- | src/lib/eina/eina_file_win32.c | 366 |
1 files changed, 315 insertions, 51 deletions
diff --git a/src/lib/eina/eina_file_win32.c b/src/lib/eina/eina_file_win32.c index cb73c0a75b..8fc6bb4c0d 100644 --- a/src/lib/eina/eina_file_win32.c +++ b/src/lib/eina/eina_file_win32.c @@ -41,7 +41,6 @@ #include "eina_list.h" #include "eina_lock.h" #include "eina_log.h" -#include "eina_file_common.h" /*============================================================================* * Local * @@ -105,6 +104,42 @@ struct _Eina_File_Direct_Iterator char dir[1]; }; +struct _Eina_File +{ + const char *filename; + + Eina_Hash *map; + Eina_Hash *rmap; + void *global_map; + + Eina_Lock lock; + + ULONGLONG length; + ULONGLONG mtime; + + int refcount; + int global_refcount; + + HANDLE handle; + HANDLE fm; + + Eina_Bool shared : 1; + Eina_Bool delete_me : 1; +}; + +struct _Eina_File_Map +{ + void *map; + + unsigned long int offset; + unsigned long int length; + + int refcount; +}; + +static Eina_Hash *_eina_file_cache = NULL; +static Eina_Lock _eina_file_lock_cache; + static int _eina_file_log_dom = -1; static Eina_Bool @@ -380,8 +415,8 @@ _eina_file_win32_direct_ls_iterator_free(Eina_File_Direct_Iterator *it) free(it); } -void -eina_file_real_close(Eina_File *file) +static void +_eina_file_real_close(Eina_File *file) { eina_hash_free(file->rmap); eina_hash_free(file->map); @@ -424,6 +459,175 @@ _eina_file_map_key_hash(const unsigned long int *key, int key_length EINA_UNUSED ^ eina_hash_int64(&key[1], sizeof (unsigned long int)); } +static char * +_eina_file_win32_escape(const char *path, size_t *length) +{ + char *result; + char *p; + char *q; + size_t len; + + result = strdup(path ? path : ""); + if (!result) + return NULL; + + p = result; + while (*p) + { + if (*p == '\\') *p = '/'; + p++; + } + p = result; + q = result; + + if (!result) + return NULL; + + if (length) len = *length; + else len = strlen(result); + + while ((p = strchr(p, '/'))) + { + // remove double `/' + if (p[1] == '/') + { + memmove(p, p + 1, --len - (p - result)); + result[len] = '\0'; + } + else + if (p[1] == '.' + && p[2] == '.') + { + // remove `/../' + if (p[3] == '/') + { + char tmp; + + len -= p + 3 - q; + memmove(q, p + 3, len - (q - result)); + result[len] = '\0'; + p = q; + + /* Update q correctly. */ + tmp = *p; + *p = '\0'; + q = strrchr(result, '/'); + if (!q) q = result; + *p = tmp; + } + else + // remove '/..$' + if (p[3] == '\0') + { + len -= p + 2 - q; + result[len] = '\0'; + q = p; + ++p; + } + else + { + q = p; + ++p; + } + } + else + { + q = p; + ++p; + } + } + + if (length) + *length = len; + + 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.end >= it->end) + return EINA_FALSE; + + match = *it->current.end; + while ((*it->current.end == '\n' || *it->current.end == '\r') + && it->current.end < it->end) + { + if (match == *it->current.end) + it->current.index++; + it->current.end++; + } + it->current.index++; + + if (it->current.end == it->end) + return EINA_FALSE; + + eol = _eina_fine_eol(it->current.end, + it->boundary, + it->end); + it->boundary = (uintptr_t) eol & 0x3FF; + if (it->boundary == 0) it->boundary = 4096; + + it->current.start = it->current.end; + + it->current.end = eol; + it->current.length = eol - it->current.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 */ @@ -480,64 +684,44 @@ eina_file_shutdown(void) return EINA_TRUE; } +/*============================================================================* + * API * + *============================================================================*/ -/* ================================================================ * - * Simplified logic for portability layer with eina_file_common * - * ================================================================ */ - -Eina_Bool -eina_file_path_relative(const char *path) -{ - if (!evil_path_is_absolute(path)) return EINA_TRUE; - return EINA_FALSE; -} - -Eina_Tmpstr * -eina_file_current_directory_get(const char *path, size_t len) -{ - char *cwd; - char *tmp; - DWORD l; - - l = GetCurrentDirectory(0, NULL); - if (l <= 0) return NULL; - - cwd = alloca(sizeof(char) * (l + 1)); - GetCurrentDirectory(l + 1, cwd); - len += l + 2; - tmp = alloca(sizeof (char) * len); - snprintf(tmp, len, "%s\\%s", cwd, path); - tmp[len - 1] = '\0'; - - return eina_tmpstr_add_length(tmp, len); -} -char * -eina_file_cleanup(Eina_Tmpstr *path) +EAPI char * +eina_file_path_sanitize(const char *path) { - char *result; - char *p; + char *result = NULL; + size_t len; - result = strdup(path ? path : ""); - eina_tmpstr_del(path); + if (!path) return NULL; - if (!result) - return NULL; + len = strlen(path); - p = result; - while (*p) + if (!evil_path_is_absolute(path)) { - if (*p == '\\') *p = '/'; - p++; + DWORD l; + + l = GetCurrentDirectory(0, NULL); + if (l > 0) + { + char *cwd; + char *tmp; + + cwd = alloca(sizeof(char) * (l + 1)); + GetCurrentDirectory(l + 1, cwd); + len += l + 2; + tmp = alloca(sizeof (char) * len); + snprintf(tmp, len, "%s\\%s", cwd, path); + tmp[len - 1] = '\0'; + result = tmp; + } } - return result; + return _eina_file_win32_escape(result ? result : path, &len); } -/*============================================================================* - * API * - *============================================================================*/ - EAPI Eina_Bool eina_file_dir_list(const char *dir, Eina_Bool recursive, @@ -813,7 +997,7 @@ eina_file_open(const char *path, Eina_Bool shared) { file->delete_me = EINA_TRUE; eina_hash_del(_eina_file_cache, file->filename, file); - eina_file_real_close(file); + _eina_file_real_close(file); file = NULL; } @@ -869,6 +1053,45 @@ eina_file_open(const char *path, Eina_Bool shared) return NULL; } +EAPI void +eina_file_close(Eina_File *file) +{ + EINA_SAFETY_ON_NULL_RETURN(file); + + eina_lock_take(&file->lock); + file->refcount--; + eina_lock_release(&file->lock); + + if (file->refcount != 0) return ; + eina_lock_take(&_eina_file_lock_cache); + + eina_hash_del(_eina_file_cache, file->filename, file); + _eina_file_real_close(file); + + eina_lock_release(&_eina_file_lock_cache); +} + +EAPI size_t +eina_file_size_get(Eina_File *file) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0); + return file->length; +} + +EAPI time_t +eina_file_mtime_get(Eina_File *file) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0); + return file->mtime; +} + +EAPI const char * +eina_file_filename_get(Eina_File *file) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); + return file->filename; +} + EAPI Eina_Iterator *eina_file_xattr_get(Eina_File *file EINA_UNUSED) { return NULL; @@ -907,6 +1130,47 @@ eina_file_map_all(Eina_File *file, Eina_File_Populate rule EINA_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.start = it->map; + it->current.end = it->current.start; + it->current.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) |