diff --git a/DESIGN b/DESIGN index 3c73e11c..f35f855b 100644 --- a/DESIGN +++ b/DESIGN @@ -44,104 +44,6 @@ Callbacks: -On-disk files: - Data will be stored in the user's home directory according to the - XDG / freedesktop.org specification. This means data will be stored - in a subdirectory of $XDG_DATA_HOME. - - The filse class will support reading and writing files in the users - $XDG_CONFIG_HOME/ocarina{-debug|test}. - - Items should be written to a file with either a space or new line - separating multiple values. - -- Notation: - "File << aaaaa << bbbbb << endl" is translated into "aaaaa bbbbb\n" - -- Open mode: - enum OpenMode { - OPEN_READ, - OPEN_WRITE, - NOT_OPEN, - } - -- File: - class File : public std::fstream { - private: - unsigned int version; - unsigned int prev_version; - OpenMode mode; - string filename; - - public: - File(const std::string &, unsigned int); - ~File(); - const std::string get_filepath(); - const unsigned int get_version(); - bool exists(); - void open(OpenMode); - void close(); - string getline(); - } - -- File format: - File << FILE_VERSION << endl; - File << ; - -- API: - File :: File(const std::string &filename, unsigned int version); - Store the name of the file and the file version. - - File :: ~File(); - Close the file stream if it is open. - - const std::string File :: get_filepath(); - If filename == "": - return "" - - Otherwise, resolve filepath to one of: - XDG_DATA_HOME/ocarina/filepath - XDG_DATA_HOME/ocarina-debug/filepath - XDG_DATA_HOME/ocarina-test/filepath - - and return the result. - - const unsigned int File :: get_version(); - if mode == OPEN_READ: - return prev_version - return version - - bool File :: exists(); - Return true if the file exists in the filesystem. - Return false otherwise. - - bool File :: open(OpenMode mode); - Return false if: - - filename == "" - - mode == NOT_OPEN - - The file is already open - - When opening a file for reading (mode == OPEN_READ), - - Return false if the file does not exist - - Open the file - - Read in prev_version from the start of the file - - When opening a file for writing (mode == OPEN_WRITE), - - Create missing directories as needed - - Write version information to the start of the file - - Return true on success. - - void File :: close(); - Close a file after IO. - - string File :: getline(); - Read an entire line from the file and return it to the caller. - In theory a return value optimization will occur so returning - a string by value won't be a problem. - - - Database Entry: The database entry class is a base class used for storing data inside a database (below). The valid flag and id counter will be managed by diff --git a/Doxyfile b/Doxyfile index 069b6f8f..2122b5c2 100644 --- a/Doxyfile +++ b/Doxyfile @@ -216,7 +216,7 @@ SEPARATE_MEMBER_PAGES = NO # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. -TAB_SIZE = 4 +TAB_SIZE = 8 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: @@ -415,7 +415,7 @@ EXTRACT_ALL = NO # be included in the documentation. # The default value is: NO. -EXTRACT_PRIVATE = NO +EXTRACT_PRIVATE = Yes # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. @@ -460,7 +460,7 @@ EXTRACT_ANON_NSPACES = NO # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. -HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_MEMBERS = YES # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set diff --git a/core/file.cpp b/core/file.cpp index a68e854c..648607d8 100644 --- a/core/file.cpp +++ b/core/file.cpp @@ -13,8 +13,16 @@ const std::string OCARINA_DIR = "ocarina-debug"; const std::string OCARINA_DIR = "ocarina"; #endif -File :: File(const std::string &name, unsigned int vers) - : mode(NOT_OPEN), filename(name), version(vers), prev_version(0) +static const std::string find_ocarina_dir() +{ + std::string res(g_get_user_data_dir()); + res += "/" + OCARINA_DIR; + return res; +} + + +File :: File(const std::string &name, unsigned int version) + : _mode(NOT_OPEN), _filename(name), _version(version), _prev_version(0) { } @@ -23,29 +31,22 @@ File :: ~File() close(); } -const std::string File :: find_dir() -{ - std::string res(g_get_user_data_dir()); - res += "/" + OCARINA_DIR; - return res; -} - const std::string File :: get_filepath() { std::string res = ""; - if (filename != "") { - res = find_dir(); - res += "/" + filename; + if (_filename != "") { + res = find_ocarina_dir(); + res += "/" + _filename; } return res; } const unsigned int File :: get_version() { - if (mode == OPEN_READ) - return prev_version; - return version; + if (_mode == OPEN_READ) + return _prev_version; + return _version; } bool File :: exists() @@ -53,7 +54,7 @@ bool File :: exists() return g_file_test(get_filepath().c_str(), G_FILE_TEST_EXISTS); } -bool File :: open_read() +bool File :: _open_read() { if (!exists()) return false; @@ -62,42 +63,42 @@ bool File :: open_read() if (std::fstream::fail()) return false; - mode = OPEN_READ; - std::fstream::operator>>(prev_version); + _mode = OPEN_READ; + std::fstream::operator>>(_prev_version); getline(); return true; } -bool File :: open_write() +bool File :: _open_write() { - if (g_mkdir_with_parents(find_dir().c_str(), 0755) != 0) + if (g_mkdir_with_parents(find_ocarina_dir().c_str(), 0755) != 0) return false; std::fstream::open(get_filepath().c_str(), std::fstream::out); if (std::fstream::fail()) return false; - mode = OPEN_WRITE; - std::fstream::operator<<(version) << std::endl; + _mode = OPEN_WRITE; + std::fstream::operator<<(_version) << std::endl; return true; } -bool File :: open(OpenMode m) +bool File :: open(OpenMode mode) { - if ((filename == "") || (m == NOT_OPEN) || (mode != NOT_OPEN)) + if ((_filename == "") || (mode == NOT_OPEN) || (_mode != NOT_OPEN)) return false; - else if (m == OPEN_READ) - return open_read(); - else /* m == OPEN_WRITE */ - return open_write(); + else if (mode == OPEN_READ) + return _open_read(); + else /* mode == OPEN_WRITE */ + return _open_write(); } void File :: close() { - if (mode != NOT_OPEN) + if (_mode != NOT_OPEN) std::fstream::close(); - mode = NOT_OPEN; + _mode = NOT_OPEN; } std::string File :: getline() diff --git a/include/core/file.h b/include/core/file.h index c30f99f0..b9a0c9cf 100644 --- a/include/core/file.h +++ b/include/core/file.h @@ -10,33 +10,48 @@ /** - * Enum for how files could be open. + * Constants defining how files can be opened. */ enum OpenMode { - /** File is open for reading. */ - OPEN_READ, - - /** File is open for writing. */ - OPEN_WRITE, - - /** File is not open. */ - NOT_OPEN, + OPEN_READ, /**< File is open for reading. */ + OPEN_WRITE, /**< File is open for writing. */ + NOT_OPEN, /**< File is not open. */ }; /** - * Class for modifying files in the Ocarina directory. + * File data is store in the user's home directory according to the + * XDG / freedesktop.org specification, meaning all of our data will + * be stored in a subdirectory of $XDG_DATA_HOME. The actual subdirectory + * changes based on what configuration values the user has set when Ocarina + * is compiled. + * + * Config Value | Ocarina Directory + * -------------|-------------------- + * default | $XDG_DATA_HOME/ocarina/ + * CONFIG_DEBUG | $XDG_DATA_HOME/ocarina-debug/ + * CONFIG_TEST | $XDG_DATA_HOME/ocarina-test/ + * + * Data should be written to files using either a space or newline as a + * delimiter. The beginning of every file is the current file version + * followed by a newline. For example: + * + * 42 + * + * + * + * Data should be written to files using either a space or newline as + * a delimiter. */ class File : public std::fstream { private: - OpenMode mode; - std::string filename; - unsigned int version; - unsigned int prev_version; + OpenMode _mode; /**< The file's current open mode. */ + std::string _filename; /**< The file's basename. */ + unsigned int _version; /**< The file's current data version. */ + unsigned int _prev_version; /**< The file's on-disk data version. */ - const std::string find_dir(); - bool open_read(); - bool open_write(); + bool _open_read(); + bool _open_write(); public: @@ -49,17 +64,20 @@ public: File(const std::string &, unsigned int); /** - * File class destructor. + * Closes the file stream if it is still open. */ ~File(); /** - * @return The full filepath of the file. + * @return The full filepath of the file or an empty string if + * the filename is not set. */ const std::string get_filepath(); /** - * @return The version number of the file. + * @return The version number of the file. If File::_mode is + * ::OPEN_READ then File::_prev_version is returned. + * File::_version is returned in all other cases. */ const unsigned int get_version(); @@ -69,19 +87,37 @@ public: bool exists(); /** - * Open a file. + * Call to open a file for either reading or writing. + * + * When opening a file for reading: + * -# Check if the file exists. + * -# Open the file stream. + * -# Read in File::_prev_version from the start of the file. + * + * When opening a file for writing: + * -# Create missing directories as needed. + * -# Write File::_version to the start of the file. * * @param mode How the file should be opened. - * @return True if the open succeeded, False otherwise. + * @return True if the open was successful. + * @return False under the following conditions: + * - File::_filename is unset + * - mode is ::NOT_OPEN + * - The file is already open (File::_mode != NOT_OPEN) + * - The file does not exist (mode == ::OPEN_READ) */ bool open(OpenMode); /** - * Close an open file. + * Close an open file and set File::mode to ::NOT_OPEN. */ void close(); /** + * Read an entire line from the file and return it to the caller. + * In theory a return value optimization will occur so returning + * a string by value won't be a performance problem. + * * @return A string containing the rest of the line. */ std::string getline();