efl/src/lib/efl/interfaces/efl_file.c

236 lines
5.7 KiB
C

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Efl.h>
typedef struct _Efl_File_Data Efl_File_Data;
struct _Efl_File_Data
{
Eina_Stringshare *vpath; /* efl_file_set */
Eina_Stringshare *key; /* efl_file_key_set */
Eina_File *file; /* efl_file_mmap_set */
time_t mtime;
Eina_Bool file_opened : 1; /* if `file` was opened implicitly during load */
Eina_Bool setting : 1; /* set when this file is internally calling methods to avoid infinite recursion */
Eina_Bool loaded : 1; /* whether the currently set file properties have been loaded */
};
EOLIAN static void
_efl_file_unload(Eo *obj, Efl_File_Data *pd)
{
if (!pd->loaded) return;
if (!pd->file) return;
if (!pd->file_opened) return;
pd->setting = 1;
eina_file_close(pd->file); // close matching open (dup in _efl_file_mmap_set) OK
pd->file = NULL;
efl_file_mmap_set(obj, NULL);
pd->setting = 0;
pd->loaded = pd->file_opened = EINA_FALSE;
}
EOLIAN static Eina_Error
_efl_file_load(Eo *obj, Efl_File_Data *pd)
{
Eina_Error ret = 0;
if (pd->loaded) return 0;
EINA_SAFETY_ON_NULL_RETURN_VAL(pd->vpath, ENOENT);
errno = 0;
if (!pd->file)
{
Eina_File *f;
f = eina_file_open(pd->vpath, EINA_FALSE);
if (!f) return errno ?: ENOENT;
pd->file_opened = EINA_TRUE;
pd->setting = 1;
ret = efl_file_mmap_set(obj, f);
pd->setting = 0;
if (ret) pd->file_opened = EINA_FALSE;
eina_file_close(f); // close matching open OK
}
pd->loaded = !ret;
return ret;
}
EOLIAN static Eina_Error
_efl_file_mmap_set(Eo *obj, Efl_File_Data *pd, const Eina_File *f)
{
Eina_Error err = 0;
Eina_File *file = NULL;
if (f == pd->file) return 0;
if (f)
{
file = eina_file_dup(f);
if (!file) return errno;
}
if (pd->file) eina_file_close(pd->file); // close matching open (dup above) OK
pd->file = file;
pd->loaded = EINA_FALSE;
if (!pd->setting)
{
/* avoid infinite recursion */
pd->setting = 1;
err = efl_file_set(obj, eina_file_filename_get(pd->file));
pd->setting = 0;
}
return err;
}
EOLIAN static const Eina_File *
_efl_file_mmap_get(const Eo *obj EINA_UNUSED, Efl_File_Data *pd)
{
return pd->file;
}
EOLIAN static Eina_Error
_efl_file_file_set(Eo *obj, Efl_File_Data *pd, const char *file)
{
char *tmp;
Eina_Error err = 0;
Eina_Bool same;
struct stat st;
tmp = (char*)(file);
if (tmp)
tmp = eina_vpath_resolve(tmp);
same = !eina_stringshare_replace(&pd->vpath, tmp ?: file);
free(tmp);
if (file)
{
err = stat(pd->vpath, &st);
if (same && (!err)) same = st.st_mtime == pd->mtime;
}
if (same) return err;
pd->mtime = file && (!err) ? st.st_mtime : 0;
pd->loaded = EINA_FALSE;
if (pd->setting)
err = 0; /* this is from mmap_set, which may provide a virtual file */
else
{
pd->setting = 1;
err = efl_file_mmap_set(obj, NULL);
pd->setting = 0;
}
return err;
}
EOLIAN static Eina_Stringshare *
_efl_file_file_get(const Eo *obj EINA_UNUSED, Efl_File_Data *pd)
{
return pd->vpath;
}
EOLIAN static void
_efl_file_key_set(Eo *obj EINA_UNUSED, Efl_File_Data *pd, const char *key)
{
if (eina_stringshare_replace(&pd->key, key))
pd->loaded = 0;
}
EOLIAN static Eina_Stringshare *
_efl_file_key_get(const Eo *obj EINA_UNUSED, Efl_File_Data *pd)
{
return pd->key;
}
EOLIAN static Eina_Bool
_efl_file_loaded_get(const Eo *obj EINA_UNUSED, Efl_File_Data *pd)
{
return pd->loaded;
}
EOLIAN static void
_efl_file_efl_object_destructor(Eo *obj, Efl_File_Data *pd)
{
eina_stringshare_del(pd->vpath);
eina_stringshare_del(pd->key);
eina_file_close(pd->file); // close matching open (dup in _efl_file_mmap_set) OK
pd->vpath = NULL;
pd->key = NULL;
pd->file = NULL;
efl_destructor(efl_super(obj, EFL_FILE_MIXIN));
}
EOLIAN static Eo *
_efl_file_efl_object_finalize(Eo *obj, Efl_File_Data *pd)
{
obj = efl_finalize(efl_super(obj, EFL_FILE_MIXIN));
if (!obj) return NULL;
if (pd->file || pd->vpath) efl_file_load(obj);
return obj;
}
////////////////////////////////////////////////////////////////////////////
EAPI Eina_Bool
efl_file_simple_load(Eo *obj, const char *file, const char *key)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
efl_ref(obj);
if (efl_file_set(obj, file))
{
EINA_LOG_ERR("File set to '%s' on '%s' failed.", file, efl_debug_name_get(obj));
goto fail;
}
efl_file_key_set(obj, key);
if (file)
{
if (efl_file_load(obj)) goto fail;
efl_unref(obj);
return EINA_TRUE;
}
efl_file_unload(obj);
efl_unref(obj);
return EINA_TRUE;
fail:
efl_unref(obj);
return EINA_FALSE;
}
EAPI Eina_Bool
efl_file_simple_mmap_load(Eo *obj, const Eina_File *file, const char *key)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
efl_ref(obj);
EINA_SAFETY_ON_TRUE_GOTO(efl_file_mmap_set(obj, file), fail);
efl_file_key_set(obj, key);
if (file)
{
if (efl_file_load(obj)) goto fail;
efl_unref(obj);
return EINA_TRUE;
}
efl_file_unload(obj);
efl_unref(obj);
return EINA_TRUE;
fail:
efl_unref(obj);
return EINA_FALSE;
}
EAPI void
efl_file_simple_get(const Eo *obj, const char **file, const char **key)
{
efl_ref((Eo*)obj);
if (file) *file = efl_file_get(obj);
if (key) *key = efl_file_key_get(obj);
efl_unref((Eo*)obj);
}
EAPI void
efl_file_simple_mmap_get(const Eo *obj, const Eina_File **file, const char **key)
{
efl_ref((Eo*)obj);
if (file) *file = efl_file_mmap_get(obj);
if (key) *key = efl_file_key_get(obj);
efl_unref((Eo*)obj);
}
#include "interfaces/efl_file.eo.c"
#include "interfaces/efl_file_save.eo.c"