core/file: Use a C-style file stream for writing to files

I also introduced a file_writef() function to make it easier to write a
formatted string to the file.

Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2015-10-08 09:41:51 -04:00
parent 3b220d3f3a
commit f24da08d85
14 changed files with 79 additions and 38 deletions

View File

@ -18,7 +18,7 @@ static AudioDriver *cur_driver = NULL;
static void save_state()
{
file_open(&f_cur_track, OPEN_WRITE);
f_cur_track << cur_track->index() << std::endl;
file_writef(&f_cur_track, "%u\n", cur_track->index());
file_close(&f_cur_track);
}

View File

@ -118,10 +118,10 @@ void deck :: write()
if (!file_open(&deck_file, OPEN_WRITE))
return;
deck_file << queue_deck.size() << std :: endl;
file_writef(&deck_file, "%zu\n", queue_deck.size());
for (it = queue_deck.begin(); it != queue_deck.end(); it++) {
it->write(deck_file);
deck_file << std::endl;
file_writef(&deck_file, "\n");
}
file_close(&deck_file);

View File

@ -2,7 +2,8 @@
* Copyright 2013 (c) Anna Schumaker.
*/
#include <core/file.h>
#include <glib.h>
#include <core/string.h>
#include <errno.h>
#ifdef CONFIG_TESTING
const std::string OCARINA_DIR = "ocarina-test";
@ -12,6 +13,10 @@ const std::string OCARINA_DIR = "ocarina-debug";
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());
@ -30,6 +35,7 @@ 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;
}
@ -58,10 +64,17 @@ bool file_exists(struct file *file)
static bool __file_open_common(struct file *file, OpenMode mode)
{
((std::fstream *)file)->open(file_path(file).c_str(),
(mode == OPEN_READ) ? std::fstream::in : std::fstream::out);
if (file->fail())
return false;
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;
@ -85,9 +98,7 @@ static bool __file_open_write(struct file *file)
return false;
if (!__file_open_common(file, OPEN_WRITE))
return false;
*file << file->f_version << std::endl;
return true;
return file_writef(file, "%d\n", file->f_version) > 0;
}
bool file_open(struct file *file, OpenMode mode)
@ -103,8 +114,12 @@ bool file_open(struct file *file, OpenMode mode)
void file_close(struct file *file)
{
if (file->f_mode != NOT_OPEN)
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;
}
@ -120,3 +135,17 @@ std::string file_readl(struct file *file)
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;
}

View File

@ -47,9 +47,9 @@ typename IndexEntry::iterator IndexEntry :: end()
void IndexEntry :: write(file &file)
{
std::set<unsigned int>::iterator it;
file << _key << std::endl << _values.size() << " ";
file_writef(&file, "%s\n%zu ", _key.c_str(), _values.size());
for (it = _values.begin(); it != _values.end(); it++)
file << *it << " ";
file_writef(&file, "%u ", *it);
}
void IndexEntry :: read(file &file)

View File

@ -29,10 +29,10 @@ public:
std::vector<struct sort_info>::iterator it;
file_open(&f, OPEN_WRITE);
f << _flags << " " << _sort_order.size();
file_writef(&f, "%u %u", _flags, _sort_order.size());
for (it = _sort_order.begin(); it != _sort_order.end(); it++)
f << " " << it->field << " " << it->ascending;
f << std::endl;
file_writef(&f, " %u %d", it->field, it->ascending);
file_writef(&f, "\n");
file_close(&f);
}

View File

@ -33,9 +33,9 @@ Queue :: ~Queue()
void Queue :: write(file &file)
{
file << _flags << " " << _tracks.size();
file_writef(&file, "%u %zu", _flags, _tracks.size());
for (unsigned int i = 0; i < _tracks.size(); i++)
file << " " << _tracks[i]->index();
file_writef(&file, " %u", _tracks[i]->index());
}
void Queue :: read(file &file)

View File

@ -38,7 +38,7 @@ void Album :: read(file &file)
void Album :: write(file &file)
{
file << _year << " ";
file_writef(&file, "%u ", _year);
GenericTag :: write(file);
}

View File

@ -38,7 +38,7 @@ void GenericTag :: read(file &file)
void GenericTag :: write(file &file)
{
file << _name;
file_writef(&file, "%s", _name.c_str());
}
const std::string &GenericTag :: name() const

View File

@ -30,7 +30,7 @@ void Library :: read(file &file)
void Library :: write(file &file)
{
file << _enabled << " " << _path;
file_writef(&file, "%d %s", _enabled, _path.c_str());
}
const bool Library :: enabled()

View File

@ -140,12 +140,11 @@ void Track :: read(file &file)
void Track :: write(file &file)
{
file << _library->index() << " " << _artist->index() << " ";
file << _album->index() << " " << _genre->index() << " " << _track << " ";
file << _date.year << " " << _date.month << " " << _date.day << " ";
file << _count << " " << _length << " ";
file_writef(&file, "%u %u %u %u %u %u %u %u %u %u", _library->index(),
_artist->index(), _album->index(), _genre->index(), _track,
_date.year, _date.month, _date.day, _count, _length);
GenericTag :: write(file);
file << std::endl << _path << std::endl;
file_writef(&file, "\n%s\n", _path.c_str());
}

View File

@ -28,15 +28,15 @@ void Database<T> :: save()
if (file_open(&_file, OPEN_WRITE) == false)
return;
_file << actual_size() << std::endl;
file_writef(&_file, "%u\n", actual_size());
for (unsigned int i = 0; i < _db.size(); i++) {
if (_db[i] == NULL)
_file << false;
file_writef(&_file, "%d\n", false);
else {
_file << true << " ";
file_writef(&_file, "%d ", true);
_db[i]->write(_file);
file_writef(&_file, "\n");
}
_file << std::endl;
}
file_close(&_file);

View File

@ -4,6 +4,9 @@
#ifndef OCARINA_CORE_FILE_H
#define OCARINA_CORE_FILE_H
#include <glib.h>
#include <glib/gstdio.h>
#include <fstream>
#include <string>
@ -46,6 +49,7 @@ struct file : public std::fstream {
OpenMode f_mode; /* The file's current open mode. */
unsigned int f_version; /* The file's current data version. */
unsigned int f_prev; /* The file's on-disk data version. */
FILE *f_file; /* The file's IO stream. */
std::string f_name; /* The file's basename. */
};
@ -78,11 +82,16 @@ bool file_exists(struct file *);
*/
bool file_open(struct file *, OpenMode);
/* Close an open file, setting file->mode to NOT_OPEN. */
void file_close(struct file *);
/* Read an entire line from the file and return it to the caller. */
std::string file_readl(struct file *);
/*
* Write to a file with an fprintf(3) style format string.
* Returns the number of bytes successfully written.
*/
int file_writef(struct file *, const char *, ...);
#endif /* OCARINA_CORE_FILE_H */

View File

@ -27,7 +27,7 @@ public:
return res;
}
void write(file &f) { f << val; }
void write(file &f) { file_writef(&f, "%d", val); }
void read(file &f) { f >> val; }
};

View File

@ -7,6 +7,7 @@
static void test_verify_constructor(struct file *file, const std::string &fpath)
{
test_equal((void *)file->f_file, NULL);
test_equal(file_version(file), 0);
test_equal(file->f_mode, NOT_OPEN);
test_equal(file_path(file), fpath);
@ -21,8 +22,10 @@ static void test_empty()
test_equal(file_open(&fempty, NOT_OPEN), (bool)false);
test_equal(file_open(&fempty, OPEN_READ), (bool)false);
test_equal((void *)fempty.f_file, NULL);
test_equal(fempty.f_mode, NOT_OPEN);
test_equal(file_open(&fempty, OPEN_WRITE), (bool)false);
test_equal((void *)fempty.f_file, NULL);
test_equal(fempty.f_mode, NOT_OPEN);
test_equal(file_exists(&fempty), (bool)false);
@ -42,10 +45,12 @@ static void test_file()
test_equal(file_open(&file, NOT_OPEN), (bool)false);
test_equal(file_open(&file, OPEN_READ), (bool)false);
test_equal(file_open(&file, OPEN_WRITE), (bool)true);
test_not_equal((void *)file.f_file, NULL);
test_equal(file.f_mode, OPEN_WRITE);
test_equal(file_open(&file, OPEN_WRITE), (bool)false);
file_close(&file);
test_equal((void *)file.f_file, NULL);
test_equal(file.f_mode, NOT_OPEN);
test_equal(file_exists(&file), (bool)true);
@ -71,14 +76,13 @@ static void test_io()
std::string res;
file_init(&a, "file.txt", 1);
test_equal(file_open(&a, OPEN_WRITE), true);
a << "ABCDE FGHIJ KLMNO PQRST UVWXYZ" << std::endl;
test_equal(file_open(&a, OPEN_WRITE), (bool)true);
file_writef(&a, "ABCDE FGHIJ KLMNO PQRST UVWXYZ\n");
file_close(&a);
test_equal(file_exists(&a), true);
test_equal(file_exists(&a), (bool)true);
file_init(&b, "file.txt", 0);
test_equal(file_open(&b, OPEN_READ), true);
test_equal(file_open(&b, OPEN_READ), (bool)true);
test_equal(file_version(&b), (unsigned)1);
b >> res;
test_equal(res, (std::string)"ABCDE");