From f24da08d85432032b33c81cc76446fd918ba7f53 Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Thu, 8 Oct 2015 09:41:51 -0400 Subject: [PATCH] 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 --- core/audio.cpp | 2 +- core/deck.cpp | 4 ++-- core/file.cpp | 47 +++++++++++++++++++++++++++++++-------- core/index.cpp | 4 ++-- core/library.cpp | 6 ++--- core/queue.cpp | 4 ++-- core/tags/album.cpp | 2 +- core/tags/generic.cpp | 2 +- core/tags/library.cpp | 2 +- core/tags/track.cpp | 9 ++++---- include/core/database.hpp | 8 +++---- include/core/file.h | 11 ++++++++- tests/core/database.cpp | 2 +- tests/core/file.cpp | 14 +++++++----- 14 files changed, 79 insertions(+), 38 deletions(-) diff --git a/core/audio.cpp b/core/audio.cpp index 116b51de..01cd214b 100644 --- a/core/audio.cpp +++ b/core/audio.cpp @@ -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); } diff --git a/core/deck.cpp b/core/deck.cpp index e359b83f..4be3a789 100644 --- a/core/deck.cpp +++ b/core/deck.cpp @@ -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); diff --git a/core/file.cpp b/core/file.cpp index 95869fb4..2c28d384 100644 --- a/core/file.cpp +++ b/core/file.cpp @@ -2,7 +2,8 @@ * Copyright 2013 (c) Anna Schumaker. */ #include -#include +#include +#include #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(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; +} diff --git a/core/index.cpp b/core/index.cpp index 8d3401a8..21088ce7 100644 --- a/core/index.cpp +++ b/core/index.cpp @@ -47,9 +47,9 @@ typename IndexEntry::iterator IndexEntry :: end() void IndexEntry :: write(file &file) { std::set::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) diff --git a/core/library.cpp b/core/library.cpp index cc4f7233..44ad3281 100644 --- a/core/library.cpp +++ b/core/library.cpp @@ -29,10 +29,10 @@ public: std::vector::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); } diff --git a/core/queue.cpp b/core/queue.cpp index db178c6a..a24b28e6 100644 --- a/core/queue.cpp +++ b/core/queue.cpp @@ -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) diff --git a/core/tags/album.cpp b/core/tags/album.cpp index c7509c25..5cf9872c 100644 --- a/core/tags/album.cpp +++ b/core/tags/album.cpp @@ -38,7 +38,7 @@ void Album :: read(file &file) void Album :: write(file &file) { - file << _year << " "; + file_writef(&file, "%u ", _year); GenericTag :: write(file); } diff --git a/core/tags/generic.cpp b/core/tags/generic.cpp index 564fa243..d9365cc2 100644 --- a/core/tags/generic.cpp +++ b/core/tags/generic.cpp @@ -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 diff --git a/core/tags/library.cpp b/core/tags/library.cpp index 5b7f8a44..fce7766d 100644 --- a/core/tags/library.cpp +++ b/core/tags/library.cpp @@ -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() diff --git a/core/tags/track.cpp b/core/tags/track.cpp index 5f215e88..b182d15d 100644 --- a/core/tags/track.cpp +++ b/core/tags/track.cpp @@ -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()); } diff --git a/include/core/database.hpp b/include/core/database.hpp index f4ad3116..61cf5948 100644 --- a/include/core/database.hpp +++ b/include/core/database.hpp @@ -28,15 +28,15 @@ void Database :: 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); diff --git a/include/core/file.h b/include/core/file.h index ea57f6ff..072bc1b9 100644 --- a/include/core/file.h +++ b/include/core/file.h @@ -4,6 +4,9 @@ #ifndef OCARINA_CORE_FILE_H #define OCARINA_CORE_FILE_H +#include +#include + #include #include @@ -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 */ diff --git a/tests/core/database.cpp b/tests/core/database.cpp index 16495b05..360025c5 100644 --- a/tests/core/database.cpp +++ b/tests/core/database.cpp @@ -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; } }; diff --git a/tests/core/file.cpp b/tests/core/file.cpp index 7d3e1876..4f9c0996 100644 --- a/tests/core/file.cpp +++ b/tests/core/file.cpp @@ -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");