2014-09-16 08:22:34 -04:00
|
|
|
/**
|
2013-08-07 21:00:09 -04:00
|
|
|
* Copyright 2013 (c) Anna Schumaker.
|
2013-07-27 11:40:16 -04:00
|
|
|
*/
|
2014-06-05 10:19:22 -04:00
|
|
|
#include <core/file.h>
|
2015-10-08 09:41:51 -04:00
|
|
|
#include <core/string.h>
|
|
|
|
#include <errno.h>
|
2013-07-27 11:40:16 -04:00
|
|
|
|
2015-08-24 08:31:00 -04:00
|
|
|
#ifdef CONFIG_TESTING
|
2014-04-26 13:31:22 -04:00
|
|
|
const std::string OCARINA_DIR = "ocarina-test";
|
2013-07-27 11:40:16 -04:00
|
|
|
#elif CONFIG_DEBUG
|
2014-04-26 13:31:22 -04:00
|
|
|
const std::string OCARINA_DIR = "ocarina-debug";
|
2013-07-27 11:40:16 -04:00
|
|
|
#else
|
2014-04-26 13:31:22 -04:00
|
|
|
const std::string OCARINA_DIR = "ocarina";
|
2013-07-27 11:40:16 -04:00
|
|
|
#endif
|
|
|
|
|
2015-10-08 09:41:51 -04:00
|
|
|
#define REPORT_ERROR() \
|
|
|
|
printf("%s (%s:%d): %s\n", __func__, __FILE__, __LINE__, strerror(errno))
|
|
|
|
|
|
|
|
|
2014-11-01 21:30:06 -04:00
|
|
|
static const std::string find_ocarina_dir()
|
2013-07-28 19:57:07 -04:00
|
|
|
{
|
2014-11-01 21:30:06 -04:00
|
|
|
std::string res(g_get_user_data_dir());
|
|
|
|
res += "/" + OCARINA_DIR;
|
|
|
|
return res;
|
2013-07-27 11:40:16 -04:00
|
|
|
}
|
|
|
|
|
2015-09-10 09:20:43 -04:00
|
|
|
static bool __file_mkdir()
|
|
|
|
{
|
|
|
|
return g_mkdir_with_parents(find_ocarina_dir().c_str(), 0755) == 0;
|
|
|
|
}
|
|
|
|
|
2014-11-01 21:30:06 -04:00
|
|
|
|
2015-09-10 10:33:24 -04:00
|
|
|
void file_init(struct file *file, const std::string &name, unsigned int version)
|
2013-07-28 19:57:07 -04:00
|
|
|
{
|
2015-09-10 10:33:24 -04:00
|
|
|
file->f_mode = NOT_OPEN;
|
|
|
|
file->f_version = version;
|
|
|
|
file->f_prev = 0;
|
2015-10-08 09:41:51 -04:00
|
|
|
file->f_file = NULL;
|
2015-09-10 10:33:24 -04:00
|
|
|
file->f_name = name;
|
2013-07-28 19:57:07 -04:00
|
|
|
}
|
|
|
|
|
2015-09-10 08:17:53 -04:00
|
|
|
const std::string file_path(struct file *file)
|
2013-07-27 11:40:16 -04:00
|
|
|
{
|
2014-05-18 10:15:51 -04:00
|
|
|
std::string res = "";
|
2014-04-26 13:31:22 -04:00
|
|
|
|
2015-09-10 08:17:53 -04:00
|
|
|
if (file->f_name != "") {
|
2014-11-01 21:30:06 -04:00
|
|
|
res = find_ocarina_dir();
|
2015-09-10 08:17:53 -04:00
|
|
|
res += "/" + file->f_name;
|
2014-04-26 13:31:22 -04:00
|
|
|
}
|
2014-05-18 10:15:51 -04:00
|
|
|
return res;
|
2013-07-27 11:40:16 -04:00
|
|
|
}
|
2013-07-28 19:57:07 -04:00
|
|
|
|
2015-09-10 08:10:38 -04:00
|
|
|
const unsigned int file_version(struct file *file)
|
2013-07-28 22:33:40 -04:00
|
|
|
{
|
2015-09-10 08:10:38 -04:00
|
|
|
if (file->f_mode == OPEN_READ)
|
|
|
|
return file->f_prev;
|
|
|
|
return file->f_version;
|
2013-07-28 22:33:40 -04:00
|
|
|
}
|
|
|
|
|
2015-09-10 08:23:09 -04:00
|
|
|
bool file_exists(struct file *file)
|
2013-07-28 19:57:07 -04:00
|
|
|
{
|
2015-09-10 08:23:09 -04:00
|
|
|
return g_file_test(file_path(file).c_str(), G_FILE_TEST_EXISTS);
|
2014-03-02 14:44:24 -05:00
|
|
|
}
|
|
|
|
|
2015-09-10 09:20:43 -04:00
|
|
|
static bool __file_open_common(struct file *file, OpenMode mode)
|
2013-07-28 19:57:07 -04:00
|
|
|
{
|
2015-10-08 09:41:51 -04:00
|
|
|
if (mode == OPEN_READ) {
|
|
|
|
((std::fstream *)file)->open(file_path(file).c_str(), std::fstream::in);
|
|
|
|
if (file->fail())
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
file->f_file = g_fopen(file_path(file).c_str(), "w");
|
|
|
|
if (!file->f_file) {
|
|
|
|
REPORT_ERROR();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2013-07-28 19:57:07 -04:00
|
|
|
|
2015-09-10 09:20:43 -04:00
|
|
|
file->f_mode = mode;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool __file_open_read(struct file *file)
|
|
|
|
{
|
|
|
|
if (!file_exists(file))
|
|
|
|
return false;
|
|
|
|
if (!__file_open_common(file, OPEN_READ))
|
2014-03-09 10:34:06 -04:00
|
|
|
return false;
|
2013-07-28 19:57:07 -04:00
|
|
|
|
2015-09-10 09:20:43 -04:00
|
|
|
*file >> file->f_prev;
|
2015-10-08 15:40:42 -04:00
|
|
|
file_readl(file);
|
2014-03-09 10:34:06 -04:00
|
|
|
return true;
|
2013-07-28 19:57:07 -04:00
|
|
|
}
|
|
|
|
|
2015-09-10 09:20:43 -04:00
|
|
|
static bool __file_open_write(struct file *file)
|
2013-07-28 19:57:07 -04:00
|
|
|
{
|
2015-09-10 09:20:43 -04:00
|
|
|
if (!__file_mkdir())
|
2014-03-09 10:34:06 -04:00
|
|
|
return false;
|
2015-09-10 09:20:43 -04:00
|
|
|
if (!__file_open_common(file, OPEN_WRITE))
|
2014-03-09 10:34:06 -04:00
|
|
|
return false;
|
2015-10-08 09:41:51 -04:00
|
|
|
return file_writef(file, "%d\n", file->f_version) > 0;
|
2013-07-28 19:57:07 -04:00
|
|
|
}
|
|
|
|
|
2015-09-10 09:46:33 -04:00
|
|
|
bool file_open(struct file *file, OpenMode mode)
|
2013-07-28 19:57:07 -04:00
|
|
|
{
|
2015-09-10 09:46:33 -04:00
|
|
|
if ((file->f_name == "") || (mode == NOT_OPEN) ||
|
|
|
|
(file->f_mode != NOT_OPEN))
|
2014-03-09 10:34:06 -04:00
|
|
|
return false;
|
2013-07-28 19:57:07 -04:00
|
|
|
|
2015-09-10 09:20:43 -04:00
|
|
|
if (mode == OPEN_READ)
|
2015-09-10 09:46:33 -04:00
|
|
|
return __file_open_read(file);
|
|
|
|
return __file_open_write(file);
|
2013-07-28 19:57:07 -04:00
|
|
|
}
|
|
|
|
|
2015-09-10 09:12:48 -04:00
|
|
|
void file_close(struct file *file)
|
2013-07-28 19:57:07 -04:00
|
|
|
{
|
2015-10-08 09:41:51 -04:00
|
|
|
if (file->f_mode != NOT_OPEN) {
|
2015-09-10 09:12:48 -04:00
|
|
|
file->close();
|
2015-10-08 09:41:51 -04:00
|
|
|
if (file->f_file)
|
|
|
|
fclose(file->f_file);
|
|
|
|
file->f_file = NULL;
|
|
|
|
}
|
2015-09-10 09:12:48 -04:00
|
|
|
file->f_mode = NOT_OPEN;
|
2013-07-28 22:33:40 -04:00
|
|
|
}
|
|
|
|
|
2015-10-08 15:40:42 -04:00
|
|
|
std::string file_readl(struct file *file)
|
2013-07-28 22:33:40 -04:00
|
|
|
{
|
2014-01-22 19:21:11 -05:00
|
|
|
char c;
|
2013-07-28 22:33:40 -04:00
|
|
|
std::string res;
|
2014-01-22 19:21:11 -05:00
|
|
|
|
|
|
|
/* Ignore leading whitespace */
|
2015-10-08 15:40:42 -04:00
|
|
|
while (file->peek() == ' ')
|
|
|
|
file->read(&c, 1);
|
2014-01-22 19:21:11 -05:00
|
|
|
|
2015-10-08 15:40:42 -04:00
|
|
|
std::getline(*static_cast<std::fstream *>(file), res);
|
2013-07-28 22:33:40 -04:00
|
|
|
return res;
|
2013-07-28 19:57:07 -04:00
|
|
|
}
|
2015-10-08 09:41:51 -04:00
|
|
|
|
|
|
|
int file_writef(struct file *file, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list argp;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
va_start(argp, fmt);
|
|
|
|
ret = g_vfprintf(file->f_file, fmt, argp);
|
|
|
|
va_end(argp);
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
REPORT_ERROR();
|
|
|
|
return ret;
|
|
|
|
}
|