file: Update documentation and various cleanups

I add more detailed documentation matching what was in my DESIGN file.
In addition, I also prefix private File members with an underscore like
I do in other Ocarina classes.

Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2014-11-01 21:30:06 -04:00
parent 23cc27c3ef
commit 47f6684923
4 changed files with 93 additions and 154 deletions

98
DESIGN
View File

@ -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 << <OTHER_DATA>;
- 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

View File

@ -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

View File

@ -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()

View File

@ -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> <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;
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();