126 lines
3.3 KiB
C++
126 lines
3.3 KiB
C++
/**
|
|
* Copyright 2013 (c) Anna Schumaker.
|
|
*/
|
|
#ifndef OCARINA_CORE_FILE_H
|
|
#define OCARINA_CORE_FILE_H
|
|
|
|
#include <fstream>
|
|
#include <string>
|
|
|
|
|
|
/**
|
|
* Constants defining how files can be opened.
|
|
*/
|
|
enum OpenMode {
|
|
OPEN_READ, /**< File is open for reading. */
|
|
OPEN_WRITE, /**< File is open for writing. */
|
|
NOT_OPEN, /**< File is not open. */
|
|
};
|
|
|
|
|
|
/**
|
|
* 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> <more data>
|
|
* <even more data>
|
|
*
|
|
* Data should be written to files using either a space or newline as
|
|
* a delimiter.
|
|
*/
|
|
class File : public std::fstream {
|
|
private:
|
|
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. */
|
|
|
|
bool _open_read();
|
|
bool _open_write();
|
|
|
|
public:
|
|
|
|
/**
|
|
* Set up a new file object.
|
|
*
|
|
* @param name The name of the file.
|
|
* @param version The file version of the new file.
|
|
*/
|
|
File(const std::string &, unsigned int);
|
|
|
|
/**
|
|
* Closes the file stream if it is still open.
|
|
*/
|
|
~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. 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();
|
|
|
|
/**
|
|
* @return True if the file exists on disk, False otherwise.
|
|
*/
|
|
bool exists();
|
|
|
|
/**
|
|
* 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 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 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();
|
|
};
|
|
|
|
#endif /* OCARINA_CORE_FILE_H */
|