What I'm trying to do should be pretty self-explanatory from the code. Unfortunately, the code is extensive. Thanks in advance to anyone who's willing to give it a look.
jake.settings.cpp
jake.settings.hCode:/******************************************************************************/ /* The Settings Class, by Jake Meiergerd /* ~ C++ Implementation /* AUTHOR: Jake Meiergerd /* VERSION: 1.0.0.1 /* /* FILE: jake.settings.h /* ~ Settings Class Implementation File /* ~ A Member of the jake library. /* /* A useful class that encapsulates storing data (settings) between executions /* of a program. The class stores the data in a file within the same /* directory as the program (by default), and provides intermediate /* functions for reading from and writing to the file. /* The format is fairly simple, from the coder's perspective. Each setting /* stored has a name which only need by worried about by the coder, /* specified by a string, and a block of straight, raw data, whose size /* needs to be specificly argued by the coder. Once the setting block is in /* place within the file, the coder can tell the Settings Object to go to /* the beginning of a particular setting and can then begin reading and /* writing upon the file. /******************************************************************************/ #ifdef __cplusplus // Module Header File #include "jake.settings.h" Settings::Settings(string filename) { cout << "CHECKPOINT: Constructing Settings object...\n"; // We first open the file in output mode only, to ensure that it exists. Also, // Append mode needs ot be specified, otherwise the old contents of the file // will be erased. cout << "CHECKPOINT: Testing open of settings file...\n"; settings_file.open(filename.c_str(), ios_base::out | ios_base::app); if(settings_file.is_open()) { cout << "CHECKPOINT: Success.\n"; settings_file.close(); } else cout << "CHECKPOINT: Failure.\n"; // Open the file for real, in IN/OUT binary mode cout << "CHECKPOINT: Opening settings file...\n"; settings_file.open(filename.c_str(), ios_base::in | ios_base::out | ios_base::binary); if(settings_file.is_open()) cout << "CHECKPOINT: Success.\n"; else cout << "CHECKPOINT: Failure.\n"; } Settings::Settings(char* filename) { cout << "CHECKPOINT: Constructing Settings object...\n"; // We first open the file in output mode only, to ensure that it exists. Also, // Append mode needs ot be specified, otherwise the old contents of the file // will be erased. cout << "CHECKPOINT: Testing open of settings file...\n"; settings_file.open(filename, ios_base::out | ios_base::app); if(settings_file.is_open()) { cout << "CHECKPOINT: Success.\n"; settings_file.close(); } else cout << "CHECKPOINT: Failure.\n"; // Open the file for real, in IN/OUT binary mode cout << "CHECKPOINT: Opening settings file...\n"; settings_file.open(filename, ios_base::in | ios_base::out | ios_base::binary); if(settings_file.is_open()) cout << "CHECKPOINT: Success.\n"; else cout << "CHECKPOINT: Failure.\n"; } Settings::~Settings(void) { cout << "CHECKPOINT: Destroying Settings object...\n"; // Make sure the file is open, then close it. cout << "CHECKPOINT: Closing settings file...\n"; if(settings_file.is_open()) settings_file.close(); if(!settings_file.is_open()) cout << "CHECKPOINT: Success.\n"; else cout << "CHECKPOINT: Failure.\n"; } bool Settings::GotoSetting(string setting_name) { cout << "CHECKPOINT: Executing GotoSetting()...\n"; // Make sure the file is open... if(!settings_file.is_open()) { cout << "CHECKPOINT: ERROR: File not open. Exiting.\n"; return false; } // Go to the beginning of the file. cout << "CHECKPOINT: Moving to beginning of file...\n"; settings_file.seekg(0); if(!settings_file.fail()) cout << "CHECKPOINT: Success.\n"; else cout << "CHECKPOINT: Failure.\n"; // Start at the beginning of setting_name uint name_index = 0; // For logic progression purposes... bool matched_name = false; uint null_count = 0; cout << "CHECKPOINT: Entering Search loop...\n"; while(1) { // As long as we don't reach the end of the file... settings_file.peek(); if(settings_file.eof()) { cout << "CHECKPOINT: End of file.\n"; break; } // If we've already matched the entire name if(matched_name) { cout << "CHECKPOINT: Setting Name Matched.\n"; // Record another Null-Terminator, if the next character is one. if(settings_file.get() == 0) { ++null_count; cout << "CHECKPOINT: Null-Terminator #" << null_count << ".\n"; } // If we didn't get a Null-Terminator, we need to start over else { cout << "CHECKPOINT: No Null-Terminator. Resetting loop.\n"; matched_name = false; null_count = 0; } // If we found two Null-Terminators after the name, we found it if(null_count == 2) { cout << "CHECKPOINT: Second Null-Terminator.\n"; cout << "CHECKPOINT: Setting found!\n"; // Synchronize the input position to the output position, which is the // beginning of the setting's data settings_file.seekp(settings_file.tellg()); // Return Success return true; } } else { // If we matched a character within the name if(settings_file.get() == setting_name[name_index]) { cout << "CHECKPOINT: setting_name[" << name_index << "] Matched.\n"; // If it was the final character of the name, indicate that we've // matched the entire name if(name_index == (setting_name.size() - 1)) { cout << "CHECKPOINT: Full Name Matched.\n"; matched_name = true; } // If we haven't matched the entire name yet, go to the next character // of the name else ++name_index; } // If the current character didn't match, start over at the beginning of // setting_name. else { cout << "CHECKPOINT: No character match. Resetting loop.\n"; name_index = 0; } } } // If we made it this far, that means the loop ran through the entire file, // and didn't find what we were looking for. So, return false cout << "CHECKPOINT: Failure to find Setting.\n"; return false; } bool Settings::GotoSetting(char* setting_name) { // Make a C++ style-string out of the setting's name string string_setting_name = setting_name; // Pass the work off to the other version of GotoSetting() return GotoSetting(string_setting_name); } bool Settings::AddSetting(string setting_name, uint size) { cout << "CHECKPOINT: Executing AddSetting()...\n"; // If the file isn't open, we can't do anything if(!settings_file.is_open()) { cout << "CHECKPOINT: ERROR: File not open. Exiting.\n"; return false; } // Make sure there isn't already a setting with the given name if(GotoSetting(setting_name)) { cout << "CHECKPOINT: Setting " << setting_name << " already exists.\n"; return false; } // Go to the end of the file cout << "CHECKPOINT: Going to end of file...\n"; settings_file.seekp(0, ios_base::end); if(!settings_file.fail()) cout << "CHECKPOINT: Success.\n"; else cout << "CHECKPOINT: Failure.\n"; cout << "CHECKPOINT: Checking file positions...\n"; cout << "CHECKPOINT: Put pointer = " << settings_file.tellp() << "\n"; cout << "CHECKPOINT: Get pointer = " << settings_file.tellg() << "\n"; if(!settings_file.fail()) cout << "CHECKPOINT: Success.\n"; else cout << "CHECKPOINT: Failure.\n"; // Add the prefixer, which is the setting's name, followed by two // Null-Terminators. cout << "CHECKPOINT: Adding prefixer for setting " << setting_name << "...\n"; settings_file << setting_name << (byte)0 << (byte)0; if(!settings_file.fail()) cout << "CHECKPOINT: Success.\n"; else cout << "CHECKPOINT: Failure.\n"; // Remember this position, because the coder expects this function to leave // the file at the beginning of the setting's data block cout << "CHECKPOINT: Retrieving file position...\n"; uint position = settings_file.tellp(); if(!settings_file.fail()) cout << "CHECKPOINT: Success.\n"; else cout << "CHECKPOINT: Failure.\n"; // Add [size] number of bytes to the file, making space for the setting's // data. cout << "CHECKPOINT: Adding empty filespace...\n"; for(uint i = 0; i < size; ++i) settings_file << (byte)0; if(!settings_file.fail()) cout << "CHECKPOINT: Success.\n"; else cout << "CHECKPOINT: Failure.\n"; // Set the file's position to the one we stored, the beginning of the // setting's data. cout << "CHECKPOINT: Setting File positions...\n"; settings_file.seekp(position); settings_file.seekg(position); if(!settings_file.fail()) cout << "CHECKPOINT: Success.\n"; else cout << "CHECKPOINT: Failure.\n"; // We made it here, so the setting was added. return true; } bool Settings::AddSetting(char* setting_name, uint size) { // Make a C++ style-string out of the setting's name string string_setting_name = setting_name; // Pass the work off to the other version of AddSetting() return AddSetting(string_setting_name, size); } #endif
test.cppCode:/******************************************************************************/ /* The Settings Class, by Jake Meiergerd /* ~ C++ Implementation /* AUTHOR: Jake Meiergerd /* VERSION: 1.0.0.1 /* /* FILE: jake.settings.h /* ~ Settings Class Header File /* ~ A Member of the jake library. /* /* A useful class that encapsulates storing data (settings) between executions /* of a program. The class stores the data in a file within the same /* directory as the program (by default), and provides intermediate /* functions for reading from and writing to the file. /* The format is fairly simple, from the coder's perspective. Each setting /* stored has a name which only need by worried about by the coder, /* specified by a string, and a block of straight, raw data, whose size /* needs to be specificly argued by the coder. Once the setting block is in /* place within the file, the coder can tell the Settings Object to go to /* the beginning of a particular setting and can then begin reading and /* writing upon the file. /******************************************************************************/ #ifndef JAKE_SETTINGS_H #define JAKE_SETTINGS_H #ifdef __cplusplus // Global header for the library #include "jake.lib.h" /**************************************/ /********* Class Declaration **********/ /**************************************/ class Settings { public: // FUNCTION: Settings() - Class Constructor // ARGUMENTS: filename: The name of the file in which the settings data // will be stored. // PRE: None // POST: The class is initialized for the given filename, and the // file is created, if it didn't already exist. // BRIEF: Initializes the Settings module for a given filename. Settings(string filename); Settings(char* filename); // FUNCTION: ~Settings() - Class Destructor // PRE: None // POST: The class object is ready to be deleted. // BRIEF: Basically, it just closes the fstream object. ~Settings(void); // FUNCTION: GotoSetting() // ARGUMENTS: setting_name: The name of the setting to search for // RETURN: true: The function was successful. // false: The setting could not be found: i.e. there is no // setting named setting_name in the file, or the file // wasn't open. // PRE: None // POST: The current position of the settings file is the beginning // of the data block of the specified setting // BRIEF: This function searches the settings file for a setting named // setting_name and sets the current position of the file, for both // reading and writing, to the beginning of the data block for that // setting. bool GotoSetting(string setting_name); bool GotoSetting(char* setting_name); // FUNCTION: AddSetting() // ARGUMENTS: setting_name: The name of the setting you wish to add // size: The number of bytes required for the setting's // data // RETURN: true: The function was successful // false: The function failed: i.e. the settings file was not // opened, or it already contains a setting with the // given name. // PRE: None // POST: The settings file now contains a block of space for the new // setting, and the current position within the file, for // both reading and writing, is the beginning of the new // setting's data block. // BRIEF: This function will add a block of space to the settings file to // store data for the setting with the given name. This new block will // be prefixed with the setting's name and a double Null-Terminator // so it can be found by GotoSetting. bool AddSetting(string setting_name, uint size); bool AddSetting(char* setting_name, uint size); private: // VAR: settings_file // BRIEF: file in which the setting data is stored. fstream settings_file; }; #endif #endif
All necessary #includes and namespace stuff are taken care of in "jake.lib.h". Program compiles and runs, and gives the following output, whether the file "test_file.set" exists previously or not.Code:#include "jake.lib.h" int main(void) { cout << " ~ Testing the jake library, main Modules ~\n\n"; // Test the Settings Module class Settings ProgramSettings("test_file.set"); ProgramSettings.AddSetting("TEST_SETTING", 16); // ProgramSettings.AddSetting("TEST_SETTING_2", 32); // End of Tests cout << "\n\n"; cout << "Program Complete\n\n"; return 0; }
Code:-bash-3.2$ test.exe ~ Testing the jake library, main Modules ~ CHECKPOINT: Constructing Settings object... CHECKPOINT: Testing open of settings file... CHECKPOINT: Success. CHECKPOINT: Opening settings file... CHECKPOINT: Success. CHECKPOINT: Executing AddSetting()... CHECKPOINT: Executing GotoSetting()... CHECKPOINT: Moving to beginning of file... CHECKPOINT: Success. CHECKPOINT: Entering Search loop... CHECKPOINT: End of file. CHECKPOINT: Failure to find Setting. CHECKPOINT: Going to end of file... CHECKPOINT: Success. CHECKPOINT: Checking file positions... CHECKPOINT: Put pointer = 0 CHECKPOINT: Get pointer = 0 CHECKPOINT: Success. CHECKPOINT: Adding prefixer for setting TEST_SETTING... CHECKPOINT: Failure. CHECKPOINT: Retrieving file position... CHECKPOINT: Failure. CHECKPOINT: Adding empty filespace... CHECKPOINT: Failure. CHECKPOINT: Setting File positions... CHECKPOINT: Failure. Program Complete CHECKPOINT: Destroying Settings object... CHECKPOINT: Closing settings file... CHECKPOINT: Success.



LinkBack URL
About LinkBacks


