ocarina/core/file.cpp

152 lines
2.9 KiB
C++
Raw Normal View History

/**
* Copyright 2013 (c) Anna Schumaker.
*/
#include <core/file.h>
#include <core/string.h>
#include <errno.h>
#ifdef CONFIG_TESTING
const std::string OCARINA_DIR = "ocarina-test";
#elif CONFIG_DEBUG
const std::string OCARINA_DIR = "ocarina-debug";
#else
const std::string OCARINA_DIR = "ocarina";
#endif
#define REPORT_ERROR() \
printf("%s (%s:%d): %s\n", __func__, __FILE__, __LINE__, strerror(errno))
static const std::string find_ocarina_dir()
{
std::string res(g_get_user_data_dir());
res += "/" + OCARINA_DIR;
return res;
}
static bool __file_mkdir()
{
return g_mkdir_with_parents(find_ocarina_dir().c_str(), 0755) == 0;
}
void file_init(struct file *file, const std::string &name, unsigned int version)
{
file->f_mode = NOT_OPEN;
file->f_version = version;
file->f_prev = 0;
file->f_file = NULL;
file->f_name = name;
}
const std::string file_path(struct file *file)
{
std::string res = "";
if (file->f_name != "") {
res = find_ocarina_dir();
res += "/" + file->f_name;
}
return res;
}
const unsigned int file_version(struct file *file)
{
if (file->f_mode == OPEN_READ)
return file->f_prev;
return file->f_version;
}
bool file_exists(struct file *file)
{
return g_file_test(file_path(file).c_str(), G_FILE_TEST_EXISTS);
}
static bool __file_open_common(struct file *file, OpenMode mode)
{
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;
}
}
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))
return false;
*file >> file->f_prev;
file_readl(file);
return true;
}
static bool __file_open_write(struct file *file)
{
if (!__file_mkdir())
return false;
if (!__file_open_common(file, OPEN_WRITE))
return false;
return file_writef(file, "%d\n", file->f_version) > 0;
}
bool file_open(struct file *file, OpenMode mode)
{
if ((file->f_name == "") || (mode == NOT_OPEN) ||
(file->f_mode != NOT_OPEN))
return false;
if (mode == OPEN_READ)
return __file_open_read(file);
return __file_open_write(file);
}
void file_close(struct file *file)
{
if (file->f_mode != NOT_OPEN) {
file->close();
if (file->f_file)
fclose(file->f_file);
file->f_file = NULL;
}
file->f_mode = NOT_OPEN;
}
std::string file_readl(struct file *file)
{
char c;
std::string res;
/* Ignore leading whitespace */
while (file->peek() == ' ')
file->read(&c, 1);
std::getline(*static_cast<std::fstream *>(file), res);
return res;
}
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;
}