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() static void save_state()
{ {
file_open(&f_cur_track, OPEN_WRITE); 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); file_close(&f_cur_track);
} }

View File

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

View File

@ -2,7 +2,8 @@
* Copyright 2013 (c) Anna Schumaker. * Copyright 2013 (c) Anna Schumaker.
*/ */
#include <core/file.h> #include <core/file.h>
#include <glib.h> #include <core/string.h>
#include <errno.h>
#ifdef CONFIG_TESTING #ifdef CONFIG_TESTING
const std::string OCARINA_DIR = "ocarina-test"; const std::string OCARINA_DIR = "ocarina-test";
@ -12,6 +13,10 @@ const std::string OCARINA_DIR = "ocarina-debug";
const std::string OCARINA_DIR = "ocarina"; const std::string OCARINA_DIR = "ocarina";
#endif #endif
#define REPORT_ERROR() \
printf("%s (%s:%d): %s\n", __func__, __FILE__, __LINE__, strerror(errno))
static const std::string find_ocarina_dir() static const std::string find_ocarina_dir()
{ {
std::string res(g_get_user_data_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_mode = NOT_OPEN;
file->f_version = version; file->f_version = version;
file->f_prev = 0; file->f_prev = 0;
file->f_file = NULL;
file->f_name = name; file->f_name = name;
} }
@ -58,10 +64,17 @@ bool file_exists(struct file *file)
static bool __file_open_common(struct file *file, OpenMode mode) static bool __file_open_common(struct file *file, OpenMode mode)
{ {
((std::fstream *)file)->open(file_path(file).c_str(), if (mode == OPEN_READ) {
(mode == OPEN_READ) ? std::fstream::in : std::fstream::out); ((std::fstream *)file)->open(file_path(file).c_str(), std::fstream::in);
if (file->fail()) if (file->fail())
return false; 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; file->f_mode = mode;
return true; return true;
@ -85,9 +98,7 @@ static bool __file_open_write(struct file *file)
return false; return false;
if (!__file_open_common(file, OPEN_WRITE)) if (!__file_open_common(file, OPEN_WRITE))
return false; return false;
return file_writef(file, "%d\n", file->f_version) > 0;
*file << file->f_version << std::endl;
return true;
} }
bool file_open(struct file *file, OpenMode mode) 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) void file_close(struct file *file)
{ {
if (file->f_mode != NOT_OPEN) if (file->f_mode != NOT_OPEN) {
file->close(); file->close();
if (file->f_file)
fclose(file->f_file);
file->f_file = NULL;
}
file->f_mode = NOT_OPEN; file->f_mode = NOT_OPEN;
} }
@ -120,3 +135,17 @@ std::string file_readl(struct file *file)
std::getline(*static_cast<std::fstream *>(file), res); std::getline(*static_cast<std::fstream *>(file), res);
return 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) void IndexEntry :: write(file &file)
{ {
std::set<unsigned int>::iterator it; 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++) for (it = _values.begin(); it != _values.end(); it++)
file << *it << " "; file_writef(&file, "%u ", *it);
} }
void IndexEntry :: read(file &file) void IndexEntry :: read(file &file)

View File

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

View File

@ -33,9 +33,9 @@ Queue :: ~Queue()
void Queue :: write(file &file) 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++) 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) void Queue :: read(file &file)

View File

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

View File

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

View File

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

View File

@ -140,12 +140,11 @@ void Track :: read(file &file)
void Track :: write(file &file) void Track :: write(file &file)
{ {
file << _library->index() << " " << _artist->index() << " "; file_writef(&file, "%u %u %u %u %u %u %u %u %u %u", _library->index(),
file << _album->index() << " " << _genre->index() << " " << _track << " "; _artist->index(), _album->index(), _genre->index(), _track,
file << _date.year << " " << _date.month << " " << _date.day << " "; _date.year, _date.month, _date.day, _count, _length);
file << _count << " " << _length << " ";
GenericTag :: write(file); 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) if (file_open(&_file, OPEN_WRITE) == false)
return; return;
_file << actual_size() << std::endl; file_writef(&_file, "%u\n", actual_size());
for (unsigned int i = 0; i < _db.size(); i++) { for (unsigned int i = 0; i < _db.size(); i++) {
if (_db[i] == NULL) if (_db[i] == NULL)
_file << false; file_writef(&_file, "%d\n", false);
else { else {
_file << true << " "; file_writef(&_file, "%d ", true);
_db[i]->write(_file); _db[i]->write(_file);
file_writef(&_file, "\n");
} }
_file << std::endl;
} }
file_close(&_file); file_close(&_file);

View File

@ -4,6 +4,9 @@
#ifndef OCARINA_CORE_FILE_H #ifndef OCARINA_CORE_FILE_H
#define OCARINA_CORE_FILE_H #define OCARINA_CORE_FILE_H
#include <glib.h>
#include <glib/gstdio.h>
#include <fstream> #include <fstream>
#include <string> #include <string>
@ -46,6 +49,7 @@ struct file : public std::fstream {
OpenMode f_mode; /* The file's current open mode. */ OpenMode f_mode; /* The file's current open mode. */
unsigned int f_version; /* The file's current data version. */ unsigned int f_version; /* The file's current data version. */
unsigned int f_prev; /* The file's on-disk 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. */ std::string f_name; /* The file's basename. */
}; };
@ -78,11 +82,16 @@ bool file_exists(struct file *);
*/ */
bool file_open(struct file *, OpenMode); bool file_open(struct file *, OpenMode);
/* Close an open file, setting file->mode to NOT_OPEN. */ /* Close an open file, setting file->mode to NOT_OPEN. */
void file_close(struct file *); void file_close(struct file *);
/* Read an entire line from the file and return it to the caller. */ /* Read an entire line from the file and return it to the caller. */
std::string file_readl(struct file *); 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 */ #endif /* OCARINA_CORE_FILE_H */

View File

@ -27,7 +27,7 @@ public:
return res; return res;
} }
void write(file &f) { f << val; } void write(file &f) { file_writef(&f, "%d", val); }
void read(file &f) { f >> 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) 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_version(file), 0);
test_equal(file->f_mode, NOT_OPEN); test_equal(file->f_mode, NOT_OPEN);
test_equal(file_path(file), fpath); 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, NOT_OPEN), (bool)false);
test_equal(file_open(&fempty, OPEN_READ), (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(fempty.f_mode, NOT_OPEN);
test_equal(file_open(&fempty, OPEN_WRITE), (bool)false); 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(fempty.f_mode, NOT_OPEN);
test_equal(file_exists(&fempty), (bool)false); 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, NOT_OPEN), (bool)false);
test_equal(file_open(&file, OPEN_READ), (bool)false); test_equal(file_open(&file, OPEN_READ), (bool)false);
test_equal(file_open(&file, OPEN_WRITE), (bool)true); 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.f_mode, OPEN_WRITE);
test_equal(file_open(&file, OPEN_WRITE), (bool)false); test_equal(file_open(&file, OPEN_WRITE), (bool)false);
file_close(&file); file_close(&file);
test_equal((void *)file.f_file, NULL);
test_equal(file.f_mode, NOT_OPEN); test_equal(file.f_mode, NOT_OPEN);
test_equal(file_exists(&file), (bool)true); test_equal(file_exists(&file), (bool)true);
@ -71,14 +76,13 @@ static void test_io()
std::string res; std::string res;
file_init(&a, "file.txt", 1); file_init(&a, "file.txt", 1);
test_equal(file_open(&a, OPEN_WRITE), true); test_equal(file_open(&a, OPEN_WRITE), (bool)true);
a << "ABCDE FGHIJ KLMNO PQRST UVWXYZ" << std::endl; file_writef(&a, "ABCDE FGHIJ KLMNO PQRST UVWXYZ\n");
file_close(&a); file_close(&a);
test_equal(file_exists(&a), true); test_equal(file_exists(&a), (bool)true);
file_init(&b, "file.txt", 0); 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); test_equal(file_version(&b), (unsigned)1);
b >> res; b >> res;
test_equal(res, (std::string)"ABCDE"); test_equal(res, (std::string)"ABCDE");