efreet: use eina_file_map

SVN revision: 78179
This commit is contained in:
Sebastian Dransfeld 2012-10-18 11:19:28 +00:00
parent e327361844
commit 4468ee3a7f
1 changed files with 80 additions and 117 deletions

View File

@ -21,9 +21,6 @@ void *alloca (size_t);
#endif #endif
#include <ctype.h> #include <ctype.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mman.h>
#include <Ecore_File.h> #include <Ecore_File.h>
@ -97,92 +94,60 @@ efreet_ini_new(const char *file)
static Eina_Hash * static Eina_Hash *
efreet_ini_parse(const char *file) efreet_ini_parse(const char *file)
{ {
const char *buffer, *line_start; Eina_File *f;
FILE *f; Eina_File_Line *line;
Eina_Hash *data, *section = NULL; Eina_Hash *data, *section = NULL;
struct stat file_stat; Eina_Iterator *it;
int line_length, left;
if (!file) return NULL; f = eina_file_open(file, EINA_FALSE);
if (!f) goto error;
f = fopen(file, "rb"); data = eina_hash_string_small_new(EINA_FREE_CB(eina_hash_free));
if (!f) return NULL; if (!data) goto error;
if (fstat(fileno(f), &file_stat) || (file_stat.st_size < 1))
{
fclose(f);
return NULL;
}
if (!S_ISREG(file_stat.st_mode)) /* if not a regular file - close */
{
fclose(f);
return NULL;
}
left = file_stat.st_size;
/* let's make mmap safe and just get 0 pages for IO erro */ /* let's make mmap safe and just get 0 pages for IO erro */
eina_mmap_safety_enabled_set(EINA_TRUE); eina_mmap_safety_enabled_set(EINA_TRUE);
buffer = mmap(NULL, left, PROT_READ, MAP_SHARED, fileno(f), 0); it = eina_file_map_lines(f);
if (buffer == MAP_FAILED) if (!it) goto error;
EINA_ITERATOR_FOREACH(it, line)
{ {
fclose(f); const char *eq;
return NULL; unsigned int start = 0;
}
data = eina_hash_string_small_new(EINA_FREE_CB(eina_hash_free)); /* skip empty lines */
if (line->length == 0) continue;
line_start = buffer; /* skip white space at start of line */
while (left > 0) while ((start < line->length) && (isspace((unsigned char)line->start[start])))
{ start++;
int sep; /* skip empty lines */
if (start == line->length) continue;
/* find the end of line */ /* skip comments */
for (line_length = 0; if (line->start[start] == '#') continue;
(line_length < left) &&
(line_start[line_length] != '\n'); line_length++)
;
/* check for all white space */
while (isspace(line_start[0]) && (line_length > 0))
{
line_start++;
line_length--;
}
/* skip empty lines and comments */
if ((line_length == 0) || (line_start[0] == '\r') ||
(line_start[0] == '\n') || (line_start[0] == '#') ||
(line_start[0] == '\0'))
goto next_line;
/* new section */ /* new section */
if (line_start[0] == '[') if (line->start[start] == '[')
{ {
int header_length; const char *head_start;
const char *head_end;
/* find the ']' */ head_start = &(line->start[start]) + 1;
for (header_length = 1; head_end = memchr(line->start, ']', line->length);
(header_length < line_length) &&
(line_start[header_length] != ']'); ++header_length)
;
if (line_start[header_length] == ']') if (head_end)
{ {
const char *header; char *header;
size_t len;
header = alloca(header_length * sizeof(unsigned char)); len = head_end - head_start + 1;
if (!header) goto next_line; header = alloca(len);
memcpy((char*)header, line_start + 1, header_length - 1); memcpy(header, head_start, len - 1);
((char*)header)[header_length - 1] = '\0'; header[len - 1] = '\0';
section = eina_hash_string_small_new(EINA_FREE_CB(eina_stringshare_del)); section = eina_hash_string_small_new(EINA_FREE_CB(eina_stringshare_del));
eina_hash_del_by_key(data, header); eina_hash_del_by_key(data, header);
// if (old) INF("[efreet] Warning: duplicate section '%s' "
// "in file '%s'", header, file);
eina_hash_add(data, header, section); eina_hash_add(data, header, section);
} }
else else
@ -191,7 +156,7 @@ efreet_ini_parse(const char *file)
/* just printf for now till we figure out what to do */ /* just printf for now till we figure out what to do */
// ERR("Invalid file (%s) (missing ] on group name)", file); // ERR("Invalid file (%s) (missing ] on group name)", file);
} }
goto next_line; continue;
} }
if (!section) if (!section)
@ -200,62 +165,62 @@ efreet_ini_parse(const char *file)
goto error; goto error;
} }
/* find for '=' */ eq = memchr(line->start, '=', line->length);
for (sep = 0; (sep < line_length) && (line_start[sep] != '='); ++sep)
;
if (sep < line_length && line_start[sep] == '=') if (eq)
{ {
const char *key_start, *key_end;
const char *value_start, *value_end;
char *key, *value; char *key, *value;
int key_end, value_start, value_end; size_t len;
key_start = &(line->start[start]);
key_end = eq - 1;
/* trim whitespace from end of key */ /* trim whitespace from end of key */
for (key_end = sep - 1; while ((isspace((unsigned char)*key_end)) && (key_end > key_start))
(key_end > 0) && isspace(line_start[key_end]); --key_end) key_end--;
; key_end++;
if (!isspace(line_start[key_end])) key_end++; /* make sure we have a key */
if (key_start == key_end) continue;
value_start = eq + 1;
value_end = line->end;
/* line->end points to char after '\n' or '\r' */
value_end--;
/* trim whitespace from end of value */
while ((isspace((unsigned char)*value_end)) && (value_end > value_start))
value_end--;
value_end++;
/* trim whitespace from start of value */ /* trim whitespace from start of value */
for (value_start = sep + 1; while ((isspace((unsigned char)*value_start)) && (value_start < value_end))
(value_start < line_length) && value_start++;
isspace(line_start[value_start]); ++value_start)
;
/* trim \n off of end of value */ len = key_end - key_start + 1;
for (value_end = line_length; key = alloca(len);
(value_end > value_start) &&
((line_start[value_end] == '\n') ||
(line_start[value_end] == '\r')); --value_end)
;
if (line_start[value_end] != '\n' memcpy(key, key_start, len - 1);
&& line_start[value_end] != '\r' key[len - 1] = '\0';
&& value_end < line_length)
value_end++;
/* make sure we have a key. blank values are allowed */ /* empty value allowed */
if (key_end <= 0) if (value_end == value_start)
{ {
/* invalid file... */ eina_hash_del_by_key(section, key);
// INF("Invalid file (%s) (invalid key=value pair)", file); eina_hash_add(section, key, "");
goto next_line;
} }
else
{
len = value_end - value_start + 1;
value = alloca(len);
memcpy(value, value_start, len - 1);
value[len - 1] = '\0';
key = alloca(key_end + 1); eina_hash_del_by_key(section, key);
value = alloca(value_end - value_start + 1); eina_hash_add(section, key, efreet_ini_unescape(value));
if (!key || !value) goto next_line; }
memcpy(key, line_start, key_end);
key[key_end] = '\0';
memcpy(value, line_start + value_start,
value_end - value_start);
value[value_end - value_start] = '\0';
eina_hash_del_by_key(section, key);
eina_hash_add(section, key, efreet_ini_unescape(value));
} }
else else
{ {
@ -263,13 +228,9 @@ efreet_ini_parse(const char *file)
INF("Invalid file (%s) (missing = from key=value pair)", file); INF("Invalid file (%s) (missing = from key=value pair)", file);
goto error; goto error;
} }
next_line:
left -= line_length + 1;
line_start += line_length + 1;
} }
munmap((char*) buffer, file_stat.st_size); eina_iterator_free(it);
fclose(f); eina_file_close(f);
#if 0 #if 0
if (!eina_hash_population(data)) if (!eina_hash_population(data))
@ -281,6 +242,8 @@ next_line:
return data; return data;
error: error:
if (data) eina_hash_free(data); if (data) eina_hash_free(data);
if (it) eina_iterator_free(it);
if (f) eina_file_close(f);
return NULL; return NULL;
} }