mirror of https://github.com/JAJames/Jupiter.git
Jessica James
8 years ago
9 changed files with 804 additions and 3 deletions
@ -0,0 +1,145 @@ |
|||
/**
|
|||
* Copyright (C) 2016 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#include "Config.h" |
|||
|
|||
const Jupiter::Config o_null_section; |
|||
|
|||
const Jupiter::ReadableString &Jupiter::Config::get(const Jupiter::ReadableString &in_key, const Jupiter::ReadableString &in_default_value) const |
|||
{ |
|||
const Jupiter::ReadableString *result = m_table.get(in_key); |
|||
|
|||
if (result == nullptr) |
|||
return in_default_value; |
|||
|
|||
return *result; |
|||
} |
|||
|
|||
const Jupiter::ReadableString *Jupiter::Config::getValue(const Jupiter::ReadableString &in_key) const |
|||
{ |
|||
return m_table.get(in_key); |
|||
} |
|||
|
|||
Jupiter::Config *Jupiter::Config::getSection(const Jupiter::ReadableString &in_key) const |
|||
{ |
|||
return m_sections.get(in_key); |
|||
} |
|||
|
|||
Jupiter::Config &Jupiter::Config::getSectionReference(const Jupiter::ReadableString &in_key) |
|||
{ |
|||
Config *section = m_sections.get(in_key); |
|||
|
|||
if (section == nullptr) |
|||
{ |
|||
m_sections.set(in_key); |
|||
section = m_sections.get(in_key); |
|||
section->m_name = in_key; |
|||
return *section; |
|||
} |
|||
|
|||
return *section; |
|||
} |
|||
|
|||
bool Jupiter::Config::set(const Jupiter::ReadableString &in_key, const Jupiter::ReadableString &in_value) |
|||
{ |
|||
return m_table.set(in_key, in_value); |
|||
} |
|||
|
|||
bool Jupiter::Config::remove(const Jupiter::ReadableString &in_key) |
|||
{ |
|||
return m_table.remove(in_key); |
|||
} |
|||
|
|||
const Jupiter::ReadableString &Jupiter::Config::getName() const |
|||
{ |
|||
return m_name; |
|||
} |
|||
|
|||
void Jupiter::Config::erase() |
|||
{ |
|||
m_table.erase(); |
|||
m_sections.erase(); |
|||
} |
|||
|
|||
bool Jupiter::Config::read(const char *in_filename) |
|||
{ |
|||
m_name = in_filename; |
|||
return this->read_internal(in_filename); |
|||
} |
|||
|
|||
bool Jupiter::Config::read(const Jupiter::ReadableString &in_filename) |
|||
{ |
|||
m_name = in_filename; |
|||
return this->read_internal(m_name.c_str()); |
|||
} |
|||
|
|||
bool Jupiter::Config::write() |
|||
{ |
|||
return this->write(m_name.c_str()); |
|||
} |
|||
|
|||
bool Jupiter::Config::write(const char *) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
bool Jupiter::Config::write(const Jupiter::ReadableString &in_filename) |
|||
{ |
|||
return this->write(Jupiter::CStringS(in_filename).c_str()); |
|||
} |
|||
|
|||
bool Jupiter::Config::reload() |
|||
{ |
|||
this->erase(); |
|||
return this->read_internal(m_name.c_str()); |
|||
} |
|||
|
|||
bool Jupiter::Config::reload(const char *in_filename) |
|||
{ |
|||
this->erase(); |
|||
return this->read(in_filename); |
|||
} |
|||
|
|||
bool Jupiter::Config::reload(const Jupiter::ReadableString &in_filename) |
|||
{ |
|||
this->erase(); |
|||
return this->read(in_filename); |
|||
} |
|||
|
|||
/** Operators */ |
|||
Jupiter::Config &Jupiter::Config::operator[](const Jupiter::ReadableString &in_key) |
|||
{ |
|||
return this->getSectionReference(in_key); |
|||
} |
|||
|
|||
/** Private functions */ |
|||
|
|||
bool Jupiter::Config::read_internal(const char *) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
void Jupiter::Config::Buffer::set_length(size_t in_length) |
|||
{ |
|||
this->length = in_length; |
|||
} |
|||
|
|||
char *Jupiter::Config::Buffer::get_str() const |
|||
{ |
|||
return this->str; |
|||
} |
@ -0,0 +1,253 @@ |
|||
/**
|
|||
* Copyright (C) 2016 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#if !defined JUPITER_CONFIG_H_HEADER |
|||
#define JUPITER_CONFIG_H_HEADER |
|||
|
|||
/**
|
|||
* @file Config.h |
|||
* @brief Defines the Config class, which provides common functionality for Config files in differing formats. |
|||
*/ |
|||
|
|||
#include "Jupiter.h" |
|||
#include "Hash_Table.h" |
|||
#include "Reference_String.h" |
|||
#include "CString.h" |
|||
|
|||
/** DLL Linkage Nagging */ |
|||
#if defined _MSC_VER |
|||
#pragma warning(push) |
|||
#pragma warning(disable: 4251) |
|||
#endif |
|||
|
|||
namespace Jupiter |
|||
{ |
|||
/**
|
|||
* @brief Base class for all Config type files |
|||
*/ |
|||
class JUPITER_API Config |
|||
{ |
|||
public: |
|||
/** Hash_Table type for sections */ |
|||
typedef Hash_Table<StringS, Config, ReadableString> SectionHashTable; |
|||
|
|||
/**
|
|||
* @brief Fetches the value of an entry. |
|||
* |
|||
* @param in_key Key of the entry to fetch |
|||
* @param in_default_value Value to return if no such entry exists |
|||
* @return Value of the entry if it exists, an empty string otherwise. |
|||
*/ |
|||
const Jupiter::ReadableString &get(const Jupiter::ReadableString &in_key, const Jupiter::ReadableString &in_default_value = Jupiter::ReferenceString::empty) const; |
|||
|
|||
/**
|
|||
* @brief Fetches the value of an entry |
|||
* |
|||
* @param in_key Key of the entry to fetch |
|||
* @return Pointer to the value of the entry on success, nullptr otherwise |
|||
*/ |
|||
const Jupiter::ReadableString *getValue(const Jupiter::ReadableString &in_key) const; |
|||
|
|||
/**
|
|||
* @brief Fetches the value of an entry and interprets it as another type. |
|||
* |
|||
* @param T Type to interpret the value as |
|||
* |
|||
* @param in_key Key of the entry to fetch |
|||
* @param in_default_value Value to return if no such entry exists |
|||
* @return Value of the entry if it exists, 0 otherwise. |
|||
*/ |
|||
template<typename T> T get(const Jupiter::ReadableString &in_key, T in_default_value = 0); |
|||
|
|||
/**
|
|||
* @brief Fetches a section based on its name |
|||
* |
|||
* @param in_key Name of the section to fetch |
|||
* @return Pointer to a section if it exists, nullptr otherwise |
|||
*/ |
|||
Config *getSection(const Jupiter::ReadableString &in_key) const; |
|||
|
|||
/**
|
|||
* @brief Fetches a section based on its name |
|||
* Note: This will create new sections as necessary if they do not exist |
|||
* |
|||
* @param in_key Name of the section to fetch |
|||
* @return Reference to the section |
|||
*/ |
|||
Config &getSectionReference(const Jupiter::ReadableString &in_key); |
|||
|
|||
/**
|
|||
* @brief Sets an entry's value in the table |
|||
* |
|||
* @param in_key Key of the entry to write to |
|||
* @param in_value Value to write to the entry |
|||
* @return True if a new entry was added, false if an entry was overwritten |
|||
*/ |
|||
bool set(const Jupiter::ReadableString &in_key, const Jupiter::ReadableString &in_value); |
|||
|
|||
/**
|
|||
* @brief Removes an entry from the table |
|||
* |
|||
* @param in_key Key of the entry to remove |
|||
* @return True if an entry was removed, false otherwise |
|||
*/ |
|||
bool remove(const Jupiter::ReadableString &in_key); |
|||
|
|||
/**
|
|||
* @brief Fetches the name of this config section |
|||
* Note: This is the filename on the root node |
|||
* |
|||
* @return Name of this section |
|||
*/ |
|||
const Jupiter::ReadableString &getName() const; |
|||
|
|||
/**
|
|||
* @brief Erases all data from this section |
|||
*/ |
|||
void erase(); |
|||
|
|||
/**
|
|||
* @brief Reads config data from a file and stores it in this config |
|||
* |
|||
* @param in_filename Name of the file to read from |
|||
* @return True on success, false otherwise |
|||
*/ |
|||
bool read(const char *in_filename); |
|||
|
|||
/**
|
|||
* @brief Reads config data from a file and stores it in this config |
|||
* |
|||
* @param in_filename Name of the file to read from |
|||
* @return True on success, false otherwise |
|||
*/ |
|||
bool read(const Jupiter::ReadableString &in_filename); |
|||
|
|||
/**
|
|||
* @brief Writes config data to the last read file |
|||
* |
|||
* @return True on success, false otherwise |
|||
*/ |
|||
bool write(); |
|||
|
|||
/**
|
|||
* @brief Writes config data to a file |
|||
* |
|||
* @param in_filename Name of the file to write to |
|||
* @return True on success, false otherwise |
|||
*/ |
|||
virtual bool write(const char *in_filename); |
|||
|
|||
/**
|
|||
* @brief Writes config data to a file |
|||
* |
|||
* @param in_filename Name of the file to write to |
|||
* @return True on success, false otherwise |
|||
*/ |
|||
bool write(const Jupiter::ReadableString &in_filename); |
|||
|
|||
/**
|
|||
* @brief Empties config data from memory and reads from the last read file |
|||
* |
|||
* @return True on success, false otherwise |
|||
*/ |
|||
bool reload(); |
|||
|
|||
/**
|
|||
* @brief Empties config data from memory and reads from a file |
|||
* |
|||
* @param in_filename Name of the file to read from |
|||
* @return True on success, false otherwise |
|||
*/ |
|||
bool reload(const char *in_filename); |
|||
|
|||
/**
|
|||
* @brief Empties config data from memory and reads from a file |
|||
* |
|||
* @param in_filename Name of the file to read from |
|||
* @return True on success, false otherwise |
|||
*/ |
|||
bool reload(const Jupiter::ReadableString &in_filename); |
|||
|
|||
/**
|
|||
* @brief Fetches a reference to this config's entry table |
|||
* |
|||
* @return Reference to m_table |
|||
*/ |
|||
inline const HashTable &getTable() const { return m_table; } |
|||
|
|||
/**
|
|||
* @brief Fetches a reference to this config's subsections |
|||
* |
|||
* @return Reference to m_sections |
|||
*/ |
|||
inline const SectionHashTable getSections() const { return m_sections; } |
|||
|
|||
/** Subscript operator */ |
|||
Config &operator[](const Jupiter::ReadableString &in_key); |
|||
|
|||
/** Used for low-level string operations */ |
|||
class Buffer : public Jupiter::StringL |
|||
{ |
|||
public: |
|||
/**
|
|||
* @brief Sets the length of the string |
|||
* |
|||
* @param in_length Length of the string |
|||
*/ |
|||
void set_length(size_t in_length); |
|||
|
|||
/**
|
|||
* @brief Returns a pointer to the underlying string |
|||
* |
|||
* @return Pointer to an array of characters |
|||
*/ |
|||
char *get_str() const; |
|||
}; |
|||
|
|||
protected: |
|||
virtual bool read_internal(const char *in_filename); |
|||
|
|||
/** Name of this Config section. This is empty or the filename at the root level. */ |
|||
Jupiter::CStringS m_name; |
|||
|
|||
/** Table of entries within this section */ |
|||
HashTable m_table; |
|||
|
|||
/** Table of sections within this section */ |
|||
SectionHashTable m_sections; |
|||
}; |
|||
} |
|||
|
|||
/** Template function implementations */ |
|||
|
|||
template<typename T> inline T Jupiter::Config::get(const Jupiter::ReadableString &in_key, T in_default_value) |
|||
{ |
|||
const Jupiter::ReadableString *result = m_table.get(in_key); |
|||
|
|||
if (result == nullptr) |
|||
return in_default_value; |
|||
|
|||
return static_cast<T>(*result); |
|||
} |
|||
|
|||
/** Re-enable warnings */ |
|||
#if defined _MSC_VER |
|||
#pragma warning(pop) |
|||
#endif |
|||
|
|||
#endif // JUPITER_CONFIG_H_HEADER
|
@ -0,0 +1,285 @@ |
|||
/**
|
|||
* Copyright (C) 2016 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#include <stack> |
|||
#include <functional> |
|||
#include "INIConfig.h" |
|||
#include "Socket.h" |
|||
|
|||
void Jupiter::INIConfig::write_helper(FILE *in_file, const Jupiter::Config *in_section, size_t in_depth) |
|||
{ |
|||
size_t index; |
|||
|
|||
if (in_depth != 0) |
|||
{ |
|||
// Write header
|
|||
|
|||
fputs("\r\n", in_file); |
|||
|
|||
// Tabs
|
|||
for (index = 1; index < in_depth; ++index) |
|||
fputc('\t', in_file); |
|||
|
|||
for (index = 0; index != in_depth; ++index) |
|||
fputc('[', in_file); |
|||
|
|||
in_section->getName().print(in_file); |
|||
|
|||
for (index = 0; index != in_depth; ++index) |
|||
fputc(']', in_file); |
|||
|
|||
fputs("\r\n", in_file); |
|||
} |
|||
|
|||
// Write table entries
|
|||
{ |
|||
auto bucket_itr = in_section->getTable().begin(); |
|||
auto bucket_end = in_section->getTable().end(); |
|||
Jupiter::SLList<HashTable::Bucket::Entry>::Node *entry_itr; |
|||
|
|||
while (bucket_itr != bucket_end) |
|||
{ |
|||
for (entry_itr = bucket_itr->m_entries.getHead(); entry_itr != nullptr; entry_itr = entry_itr->next) |
|||
{ |
|||
// Tabs
|
|||
for (index = 1; index < in_depth; ++index) |
|||
fputc('\t', in_file); |
|||
|
|||
// Write entry
|
|||
entry_itr->data->key.print(in_file); |
|||
fputs(" = ", in_file); |
|||
entry_itr->data->value.println(in_file); |
|||
} |
|||
|
|||
++bucket_itr; |
|||
} |
|||
} |
|||
|
|||
// Write subsections
|
|||
{ |
|||
auto bucket_itr = in_section->getSections().begin(); |
|||
auto bucket_end = in_section->getSections().end(); |
|||
Jupiter::SLList<SectionHashTable::Bucket::Entry>::Node *entry_itr; |
|||
|
|||
while (bucket_itr != bucket_end) |
|||
{ |
|||
for (entry_itr = bucket_itr->m_entries.getHead(); entry_itr != nullptr; entry_itr = entry_itr->next) |
|||
write_helper(in_file, &entry_itr->data->value, in_depth + 1); |
|||
|
|||
++bucket_itr; |
|||
} |
|||
} |
|||
} |
|||
|
|||
bool Jupiter::INIConfig::write(const char *in_filename) |
|||
{ |
|||
// Open file
|
|||
FILE *file = fopen(in_filename, "wb"); |
|||
|
|||
if (file == nullptr) |
|||
return false; |
|||
|
|||
// Iterate through table and sections
|
|||
write_helper(file, this, 0); |
|||
|
|||
// File writing completed; close and return
|
|||
fclose(file); |
|||
return true; |
|||
} |
|||
|
|||
bool Jupiter::INIConfig::read_internal(const char *in_filename) |
|||
{ |
|||
Jupiter::ReferenceString line; |
|||
std::stack<Jupiter::Config *> section_stack; |
|||
|
|||
section_stack.push(this); |
|||
|
|||
auto process_line = [&line, §ion_stack]() |
|||
{ |
|||
const char *itr = line.ptr(); |
|||
const char *end = itr + line.size(); // guaranteed to be greater than itr
|
|||
|
|||
// Shift to right of spaces
|
|||
|
|||
while (isspace(*itr)) |
|||
if (++itr == end) |
|||
return; // Line is purely whitespace
|
|||
|
|||
line.shiftRight(itr - line.ptr()); |
|||
|
|||
if (*itr == ';') |
|||
return; // Comment
|
|||
|
|||
if (*itr == '[') |
|||
{ |
|||
// Parse header
|
|||
|
|||
size_t depth = 1; |
|||
|
|||
for (++itr; itr != end && *itr == '['; ++itr) |
|||
++depth; |
|||
|
|||
line.shiftRight(itr - line.ptr()); |
|||
|
|||
while (end != itr) |
|||
{ |
|||
--end; |
|||
if (*end != ']' && isspace(*end) == 0) |
|||
{ |
|||
++end; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
line.set(itr, end - itr); |
|||
|
|||
// Add section to stack; pop sections or push blanks as necessary
|
|||
|
|||
while (depth < section_stack.size()) |
|||
section_stack.pop(); |
|||
|
|||
while (depth > section_stack.size()) |
|||
section_stack.push(std::addressof(section_stack.top()->getSectionReference(Jupiter::ReferenceString::empty))); |
|||
|
|||
section_stack.push(§ion_stack.top()->getSectionReference(line)); |
|||
} |
|||
else |
|||
{ |
|||
// Truncate spaces
|
|||
--end; |
|||
|
|||
while (isspace(*end)) |
|||
--end; // don't need a safety check since we know there is at least 1 non-space character
|
|||
// end now points to a non-space character within the bounds
|
|||
|
|||
++end; |
|||
line.truncate(itr + line.size() - end); |
|||
|
|||
// Parse key (can be empty)
|
|||
|
|||
while (*itr != '=') |
|||
if (++itr == end) |
|||
return; // Error: no assignment exists; ignore line
|
|||
|
|||
Jupiter::ReferenceString key; |
|||
|
|||
if (itr != line.ptr()) |
|||
{ |
|||
// Truncate spaces from key; a non-space character is guaranteed
|
|||
end = itr - 1; |
|||
|
|||
while (isspace(*end)) |
|||
--end; |
|||
|
|||
key = line.substring(size_t{ 0 }, end + 1 - line.ptr()); |
|||
|
|||
end = line.ptr() + line.size(); |
|||
} |
|||
|
|||
// Parse value (can be empty)
|
|||
|
|||
if (++itr != end) |
|||
{ |
|||
// Shift to right of spaces; a non-space character is guaranteed
|
|||
while (isspace(*itr)) |
|||
++itr; |
|||
|
|||
line.shiftRight(itr - line.ptr()); |
|||
} |
|||
else |
|||
line = Jupiter::ReferenceString::empty; |
|||
|
|||
// Add entry to current table on stack
|
|||
section_stack.top()->set(key, line); |
|||
} |
|||
}; |
|||
|
|||
constexpr size_t READ_CHUNK_SIZE = 1024; |
|||
size_t read_count = READ_CHUNK_SIZE; |
|||
Buffer buffer; |
|||
char *itr; |
|||
char *end; |
|||
|
|||
// Open file
|
|||
FILE *file = fopen(in_filename, "rb"); |
|||
|
|||
if (file == nullptr) |
|||
return false; |
|||
|
|||
buffer.setBufferSize(READ_CHUNK_SIZE * 2); |
|||
|
|||
// Parse file contents
|
|||
while (read_count == READ_CHUNK_SIZE) |
|||
{ |
|||
// Ensure the buffer has at least READ_CHUNK_SIZE space remaining
|
|||
buffer.setBufferSize(buffer.size() + READ_CHUNK_SIZE); |
|||
|
|||
// Read data from file to end of buffer
|
|||
itr = buffer.get_str(); |
|||
read_count = fread(itr + buffer.size(), sizeof(char), READ_CHUNK_SIZE, file); |
|||
buffer.set_length(buffer.size() + read_count); |
|||
end = itr + buffer.size(); |
|||
|
|||
// Reset line
|
|||
line.set(buffer.ptr(), 0); |
|||
|
|||
// Parse buffer for lines
|
|||
while (itr != end) |
|||
{ |
|||
// Check if the line is over
|
|||
if (*itr == '\n' || *itr == '\r') |
|||
{ |
|||
// Process line
|
|||
line.set(buffer.ptr(), itr - buffer.ptr()); |
|||
if (line.isNotEmpty()) |
|||
process_line(); |
|||
|
|||
// Keep iterating until next non-newline character
|
|||
while (true) |
|||
{ |
|||
++itr; |
|||
|
|||
if (itr == end) |
|||
{ |
|||
// No data remains to be parsed in buffer; erase buffer and break
|
|||
buffer.erase(); |
|||
break; |
|||
} |
|||
|
|||
if (*itr != '\n' && *itr != '\r') |
|||
{ |
|||
// Shift buffer and break
|
|||
buffer.shiftRight(itr - buffer.ptr()); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
else |
|||
++itr; |
|||
} |
|||
} |
|||
|
|||
// Process data remaining in buffer as a line
|
|||
line.set(buffer.ptr(), buffer.size()); |
|||
if (line.isNotEmpty()) |
|||
process_line(); |
|||
|
|||
// File has been successfully read, or an error occurred.
|
|||
fclose(file); |
|||
return true; |
|||
} |
@ -0,0 +1,62 @@ |
|||
/**
|
|||
* Copyright (C) 2016 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#if !defined JUPITER_INICONFIG_H_HEADER |
|||
#define JUPITER_INICONFIG_H_HEADER |
|||
|
|||
/**
|
|||
* @file INIConfig.h |
|||
* @brief Provides an INI config implementation for the Config interface. |
|||
*/ |
|||
|
|||
#include "Config.h" |
|||
|
|||
/** DLL Linkage Nagging */ |
|||
#if defined _MSC_VER |
|||
#pragma warning(push) |
|||
#pragma warning(disable: 4251) |
|||
#endif |
|||
|
|||
namespace Jupiter |
|||
{ |
|||
/**
|
|||
* @brief INI-based Config class |
|||
*/ |
|||
class JUPITER_API INIConfig : public Jupiter::Config |
|||
{ |
|||
public: |
|||
/**
|
|||
* @brief Writes config data to a file |
|||
* |
|||
* @param in_filename Name of the file to write to |
|||
* @return True on success, false otherwise |
|||
*/ |
|||
bool write(const char *in_filename); |
|||
|
|||
private: |
|||
bool read_internal(const char *in_filename); |
|||
void write_helper(FILE *in_file, const Jupiter::Config *in_section, size_t in_depth); |
|||
}; |
|||
} |
|||
|
|||
/** Re-enable warnings */ |
|||
#if defined _MSC_VER |
|||
#pragma warning(pop) |
|||
#endif |
|||
|
|||
#endif // JUPITER_INICONFIG_H_HEADER
|
Loading…
Reference in new issue