mirror of https://github.com/JAJames/Jupiter.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
577 lines
16 KiB
577 lines
16 KiB
/**
|
|
* Copyright (C) Justin James - All Rights Reserved.
|
|
* Unauthorized use or copying of this file via any medium is strictly prohibited.
|
|
* This document is proprietary and confidential.
|
|
* This document should be immediately destroyed unless given explicit permission by Justin James.
|
|
* Written by Justin James <justin.aj@hotmail.com>
|
|
*/
|
|
|
|
#include <cstring>
|
|
#include <cstdlib>
|
|
#include <cstdio>
|
|
#include "Functions.h"
|
|
#include "INIFile.h"
|
|
#include "CString.h"
|
|
#include "ArrayList.h"
|
|
#include "InvalidIndex.h"
|
|
|
|
/**
|
|
* TODO:
|
|
* Rewrite using String, and ArrayList. Consider using File when reading data.
|
|
* Add support for unspecified section.
|
|
* Consider sort/search optimization.
|
|
*/
|
|
|
|
/** KeyValuePair implementation */
|
|
|
|
struct Jupiter::INIFile::Section::KeyValuePair::Data
|
|
{
|
|
Jupiter::CStringS key;
|
|
Jupiter::CStringS value;
|
|
};
|
|
|
|
Jupiter::INIFile::Section::KeyValuePair::KeyValuePair()
|
|
{
|
|
Jupiter::INIFile::Section::KeyValuePair::data_ = new Jupiter::INIFile::Section::KeyValuePair::Data();
|
|
}
|
|
|
|
Jupiter::INIFile::Section::KeyValuePair::KeyValuePair(const KeyValuePair &source)
|
|
{
|
|
Jupiter::INIFile::Section::KeyValuePair::data_ = new Jupiter::INIFile::Section::KeyValuePair::Data();
|
|
Jupiter::INIFile::Section::KeyValuePair::data_->key = source.data_->key;
|
|
Jupiter::INIFile::Section::KeyValuePair::data_->value = source.data_->value;
|
|
}
|
|
|
|
Jupiter::INIFile::Section::KeyValuePair::~KeyValuePair()
|
|
{
|
|
delete Jupiter::INIFile::Section::KeyValuePair::data_;
|
|
}
|
|
|
|
const Jupiter::StringType &Jupiter::INIFile::Section::KeyValuePair::getKey() const
|
|
{
|
|
return Jupiter::INIFile::Section::KeyValuePair::data_->key;
|
|
}
|
|
|
|
const Jupiter::StringType &Jupiter::INIFile::Section::KeyValuePair::getValue() const
|
|
{
|
|
return Jupiter::INIFile::Section::KeyValuePair::data_->value;
|
|
}
|
|
|
|
void Jupiter::INIFile::Section::KeyValuePair::setValue(const Jupiter::StringType &value)
|
|
{
|
|
Jupiter::INIFile::Section::KeyValuePair::data_->value = value;
|
|
}
|
|
|
|
void Jupiter::INIFile::Section::KeyValuePair::setValue(const char *value)
|
|
{
|
|
Jupiter::INIFile::Section::KeyValuePair::data_->value = value;
|
|
}
|
|
|
|
/** Section implementation */
|
|
|
|
struct Jupiter::INIFile::Section::Data
|
|
{
|
|
Jupiter::CStringS name;
|
|
Jupiter::ArrayList<Jupiter::INIFile::Section::KeyValuePair> data;
|
|
~Data();
|
|
};
|
|
|
|
Jupiter::INIFile::Section::Data::~Data()
|
|
{
|
|
Jupiter::INIFile::Section::Data::data.emptyAndDelete();
|
|
}
|
|
|
|
Jupiter::INIFile::Section::Section()
|
|
{
|
|
Jupiter::INIFile::Section::data_ = new Jupiter::INIFile::Section::Data();
|
|
}
|
|
|
|
Jupiter::INIFile::Section::Section(const Jupiter::StringType &name)
|
|
{
|
|
Jupiter::INIFile::Section::data_ = new Jupiter::INIFile::Section::Data();
|
|
Jupiter::INIFile::Section::data_->name = name;
|
|
}
|
|
|
|
Jupiter::INIFile::Section::Section(const char *name)
|
|
{
|
|
Jupiter::INIFile::Section::data_ = new Jupiter::INIFile::Section::Data();
|
|
Jupiter::INIFile::Section::data_->name = name;
|
|
}
|
|
|
|
Jupiter::INIFile::Section::Section(const Jupiter::INIFile::Section &source)
|
|
{
|
|
Jupiter::INIFile::Section::data_ = new Jupiter::INIFile::Section::Data();
|
|
Jupiter::INIFile::Section::data_->name = source.data_->name;
|
|
unsigned int size = Jupiter::INIFile::Section::data_->data.size();
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
Jupiter::INIFile::Section::data_->data.add(new Jupiter::INIFile::Section::KeyValuePair(*source.data_->data.get(i)));
|
|
}
|
|
}
|
|
|
|
Jupiter::INIFile::Section::~Section()
|
|
{
|
|
delete Jupiter::INIFile::Section::data_;
|
|
}
|
|
|
|
const Jupiter::StringType &Jupiter::INIFile::Section::getName() const
|
|
{
|
|
return Jupiter::INIFile::Section::data_->name;
|
|
}
|
|
|
|
const Jupiter::StringType &Jupiter::INIFile::Section::getValue(unsigned int index) const
|
|
{
|
|
return Jupiter::INIFile::Section::data_->data.get(index)->data_->value;
|
|
}
|
|
|
|
const Jupiter::StringType &Jupiter::INIFile::Section::getValue(const Jupiter::StringType &key) const
|
|
{
|
|
unsigned int size = Jupiter::INIFile::Section::data_->data.size();
|
|
Jupiter::INIFile::Section::KeyValuePair *pair;
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
pair = Jupiter::INIFile::Section::data_->data.get(i);
|
|
if (pair->getKey().equalsi(key)) return pair->getValue();
|
|
}
|
|
return Jupiter::emptyString;
|
|
}
|
|
|
|
const Jupiter::StringType &Jupiter::INIFile::Section::getValue(const char *key) const
|
|
{
|
|
unsigned int size = Jupiter::INIFile::Section::data_->data.size();
|
|
Jupiter::INIFile::Section::KeyValuePair *pair;
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
pair = Jupiter::INIFile::Section::data_->data.get(i);
|
|
if (pair->getKey().equalsi(key)) return pair->getValue();
|
|
}
|
|
return Jupiter::emptyString;
|
|
}
|
|
|
|
Jupiter::INIFile::Section::KeyValuePair *Jupiter::INIFile::Section::getPair(unsigned int index) const
|
|
{
|
|
return Jupiter::INIFile::Section::data_->data.get(index);
|
|
}
|
|
|
|
Jupiter::INIFile::Section::KeyValuePair *Jupiter::INIFile::Section::getPair(const Jupiter::StringType &key) const
|
|
{
|
|
unsigned int size = Jupiter::INIFile::Section::data_->data.size();
|
|
Jupiter::INIFile::Section::KeyValuePair *pair;
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
pair = Jupiter::INIFile::Section::data_->data.get(i);
|
|
if (pair->getKey().equalsi(key)) return pair;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Jupiter::INIFile::Section::KeyValuePair *Jupiter::INIFile::Section::getPair(const char *key) const
|
|
{
|
|
unsigned int size = Jupiter::INIFile::Section::data_->data.size();
|
|
Jupiter::INIFile::Section::KeyValuePair *pair;
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
pair = Jupiter::INIFile::Section::data_->data.get(i);
|
|
if (pair->getKey().equalsi(key)) return pair;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
unsigned int Jupiter::INIFile::Section::size() const
|
|
{
|
|
return Jupiter::INIFile::Section::data_->data.size();
|
|
}
|
|
|
|
bool Jupiter::INIFile::Section::hasKey(const Jupiter::StringType &key) const
|
|
{
|
|
unsigned int size = Jupiter::INIFile::Section::data_->data.size();
|
|
Jupiter::INIFile::Section::KeyValuePair *pair;
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
pair = Jupiter::INIFile::Section::data_->data.get(i);
|
|
if (pair->getKey().equalsi(key)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Jupiter::INIFile::Section::hasKey(const char *key) const
|
|
{
|
|
unsigned int size = Jupiter::INIFile::Section::data_->data.size();
|
|
Jupiter::INIFile::Section::KeyValuePair *pair;
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
pair = Jupiter::INIFile::Section::data_->data.get(i);
|
|
if (pair->getKey().equalsi(key)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Jupiter::INIFile::Section::set(Jupiter::StringType &key, Jupiter::StringType &value)
|
|
{
|
|
unsigned int size = Jupiter::INIFile::Section::data_->data.size();
|
|
Jupiter::INIFile::Section::KeyValuePair *pair;
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
pair = Jupiter::INIFile::Section::data_->data.get(i);
|
|
if (pair->getKey().equalsi(key))
|
|
{
|
|
pair->data_->value = value;
|
|
return false;
|
|
}
|
|
}
|
|
pair = new Jupiter::INIFile::Section::KeyValuePair();
|
|
pair->data_->key = key;
|
|
pair->data_->value = value;
|
|
Jupiter::INIFile::Section::data_->data.add(pair);
|
|
return true;
|
|
}
|
|
|
|
bool Jupiter::INIFile::Section::set(const char *key, const char *value)
|
|
{
|
|
unsigned int size = Jupiter::INIFile::Section::data_->data.size();
|
|
Jupiter::INIFile::Section::KeyValuePair *pair;
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
pair = Jupiter::INIFile::Section::data_->data.get(i);
|
|
if (pair->getKey().equalsi(key))
|
|
{
|
|
pair->data_->value = value;
|
|
return false;
|
|
}
|
|
}
|
|
pair = new Jupiter::INIFile::Section::KeyValuePair();
|
|
pair->data_->key = key;
|
|
pair->data_->value = value;
|
|
Jupiter::INIFile::Section::data_->data.add(pair);
|
|
return true;
|
|
}
|
|
|
|
void Jupiter::INIFile::Section::setName(const Jupiter::StringType &name)
|
|
{
|
|
Jupiter::INIFile::Section::data_->name = name;
|
|
}
|
|
|
|
void Jupiter::INIFile::Section::setName(const char *name)
|
|
{
|
|
Jupiter::INIFile::Section::data_->name = name;
|
|
}
|
|
|
|
bool Jupiter::INIFile::Section::remove(Jupiter::StringType &key)
|
|
{
|
|
unsigned int size = Jupiter::INIFile::Section::data_->data.size();
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
if (Jupiter::INIFile::Section::data_->data.get(i)->getKey().equalsi(key))
|
|
{
|
|
delete Jupiter::INIFile::Section::data_->data.remove(i);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Jupiter::INIFile::Section::remove(const char *key)
|
|
{
|
|
unsigned int size = Jupiter::INIFile::Section::data_->data.size();
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
if (Jupiter::INIFile::Section::data_->data.get(i)->getKey().equalsi(key))
|
|
{
|
|
delete Jupiter::INIFile::Section::data_->data.remove(i);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/** INIFile implementation */
|
|
|
|
struct Jupiter::INIFile::Data
|
|
{
|
|
Jupiter::ArrayList<Section> data;
|
|
Jupiter::CStringS fName;
|
|
~Data();
|
|
};
|
|
|
|
Jupiter::INIFile::Data::~Data()
|
|
{
|
|
Jupiter::INIFile::Data::data.emptyAndDelete();
|
|
}
|
|
|
|
Jupiter::INIFile::INIFile()
|
|
{
|
|
Jupiter::INIFile::data_ = new Jupiter::INIFile::Data;
|
|
}
|
|
|
|
Jupiter::INIFile::INIFile(const INIFile &source)
|
|
{
|
|
Jupiter::INIFile::data_ = new Jupiter::INIFile::Data;
|
|
Jupiter::INIFile::data_->fName = source.data_->fName;
|
|
unsigned int size = Jupiter::INIFile::data_->data.size();
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
Jupiter::INIFile::data_->data.add(new Jupiter::INIFile::Section(*source.data_->data.get(i)));
|
|
}
|
|
}
|
|
|
|
Jupiter::INIFile::~INIFile()
|
|
{
|
|
delete Jupiter::INIFile::data_;
|
|
}
|
|
|
|
void Jupiter::INIFile::flushData()
|
|
{
|
|
delete Jupiter::INIFile::data_;
|
|
Jupiter::INIFile::data_ = new Jupiter::INIFile::Data();
|
|
}
|
|
|
|
// TODO: Rewrite this.
|
|
unsigned int Jupiter::INIFile::readFile(const char *fileName)
|
|
{
|
|
unsigned int count = 0;
|
|
Jupiter::INIFile::data_->fName = fileName;
|
|
FILE *file = fopen(Jupiter::INIFile::data_->fName.c_str(), "rb");
|
|
if (file == nullptr) return Jupiter::ERROR_INDICATOR;
|
|
char fileBuffer[8192];
|
|
char *section;
|
|
//int nSection = 0;
|
|
while (!feof(file))
|
|
{
|
|
if (fgets(fileBuffer, sizeof(fileBuffer), file))
|
|
{
|
|
do1:
|
|
if (fileBuffer[strspn(fileBuffer, WHITESPACE)] != ';' && fileBuffer[strspn(fileBuffer, WHITESPACE)] == '[')
|
|
{
|
|
section = charToChar(fileBuffer, strspn(fileBuffer, WHITESPACE) + 1, strcspn(fileBuffer, "]"));
|
|
do2:
|
|
if (fgets(fileBuffer, sizeof(fileBuffer), file))
|
|
{
|
|
size_t eqlpos = strcspn(fileBuffer, "=");
|
|
if (fileBuffer[strspn(fileBuffer, WHITESPACE)] != ';' && eqlpos != strlen(fileBuffer))
|
|
{
|
|
size_t a = strspn(fileBuffer, WHITESPACE);
|
|
char *tkey = charToChar(fileBuffer, a, a + strcspn(fileBuffer + a, WHITESPACE "="));
|
|
char *tval = charToChar(fileBuffer, eqlpos + 1 + strspn(fileBuffer + eqlpos + 1, WHITESPACE), strcspn(fileBuffer, ENDL));
|
|
if (Jupiter::INIFile::set(section, tkey, tval)) count++;
|
|
delete[] tval;
|
|
delete[] tkey;
|
|
}
|
|
}
|
|
if (!feof(file))
|
|
{
|
|
if (fileBuffer[strspn(fileBuffer, WHITESPACE)] != '[') goto do2;
|
|
else goto do1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fclose(file);
|
|
return count;
|
|
}
|
|
|
|
unsigned int Jupiter::INIFile::reload()
|
|
{
|
|
Jupiter::CStringS fileName = Jupiter::INIFile::data_->fName;
|
|
Jupiter::INIFile::flushData();
|
|
return Jupiter::INIFile::readFile(fileName.c_str());
|
|
}
|
|
|
|
bool Jupiter::INIFile::sync(const char *fileName)
|
|
{
|
|
unsigned int size = Jupiter::INIFile::data_->data.size();
|
|
unsigned int sectionSize;
|
|
Jupiter::INIFile::Section *section;
|
|
Jupiter::INIFile::Section::KeyValuePair *pair;
|
|
|
|
FILE *file = fopen(fileName, "wb");
|
|
if (file == nullptr) return false;
|
|
fputs("; This file was automatically generated by Agent's INI parser." ENDL "; The currently used data values are as follows." ENDL ENDL, file);
|
|
for (unsigned int a = 0; a < size; a++)
|
|
{
|
|
section = Jupiter::INIFile::data_->data.get(a);
|
|
fputc('[', file);
|
|
section->getName().print(file);
|
|
fputs("]" ENDL, file);
|
|
|
|
sectionSize = section->size();
|
|
for (unsigned int b = 0; b < sectionSize; b++)
|
|
{
|
|
pair = section->getPair(b);
|
|
pair->getKey().print(file);
|
|
fputc('=', file);
|
|
pair->getValue().print(file);
|
|
fputs(ENDL, file);
|
|
}
|
|
fputs(ENDL, file);
|
|
}
|
|
fputs("; EOF", file);
|
|
fclose(file);
|
|
return true;
|
|
}
|
|
|
|
bool Jupiter::INIFile::sync()
|
|
{
|
|
if (Jupiter::INIFile::data_->fName.size() == 0) return false;
|
|
return Jupiter::INIFile::sync(Jupiter::INIFile::data_->fName.c_str());
|
|
}
|
|
|
|
bool Jupiter::INIFile::set(const char *section, const char *key, const char *value)
|
|
{
|
|
unsigned int i = 0;
|
|
unsigned int size = Jupiter::INIFile::data_->data.size();
|
|
Jupiter::INIFile::Section *sec;
|
|
while (i < size)
|
|
{
|
|
sec = Jupiter::INIFile::data_->data.get(i);
|
|
if (sec->getName().equalsi(section))
|
|
{
|
|
sec->set(key, value);
|
|
return false;
|
|
}
|
|
i++;
|
|
}
|
|
sec = new Jupiter::INIFile::Section(section);
|
|
sec->set(key, value);
|
|
Jupiter::INIFile::data_->data.add(sec);
|
|
return true;
|
|
}
|
|
|
|
bool Jupiter::INIFile::remove(const char *section, const char *key)
|
|
{
|
|
unsigned int size = Jupiter::INIFile::data_->data.size();
|
|
Jupiter::INIFile::Section *sec;
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
sec = Jupiter::INIFile::data_->data.get(i);
|
|
if (sec->getName().equalsi(section)) return sec->remove(key);
|
|
i++;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
unsigned int Jupiter::INIFile::getSections() const
|
|
{
|
|
return Jupiter::INIFile::data_->data.size();
|
|
}
|
|
|
|
Jupiter::INIFile::Section *Jupiter::INIFile::getSection(unsigned int index) const
|
|
{
|
|
return Jupiter::INIFile::data_->data.get(index);
|
|
}
|
|
|
|
unsigned int Jupiter::INIFile::getSectionIndex(const char *section) const
|
|
{
|
|
unsigned int size = Jupiter::INIFile::data_->data.size();
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
if (Jupiter::INIFile::data_->data.get(i)->getName().equalsi(section)) return i;
|
|
}
|
|
return Jupiter::INVALID_INDEX;
|
|
}
|
|
|
|
unsigned int Jupiter::INIFile::getSectionLength(unsigned int index) const
|
|
{
|
|
return Jupiter::INIFile::data_->data.get(index)->size();
|
|
}
|
|
|
|
const char *Jupiter::INIFile::getKey(const char *section, unsigned int index) const
|
|
{
|
|
unsigned int sectionIndex = Jupiter::INIFile::getSectionIndex(section);
|
|
if (sectionIndex == Jupiter::INVALID_INDEX) return nullptr;
|
|
return Jupiter::INIFile::data_->data.get(sectionIndex)->getPair(index)->getKey().c_str();
|
|
}
|
|
|
|
unsigned int Jupiter::INIFile::getKeyIndex(const char *section, const char *key) const
|
|
{
|
|
unsigned int sectionIndex = Jupiter::INIFile::getSectionIndex(section);
|
|
if (sectionIndex == Jupiter::INVALID_INDEX) return Jupiter::INVALID_INDEX;
|
|
Jupiter::INIFile::Section *sect = Jupiter::INIFile::data_->data.get(sectionIndex);
|
|
unsigned int sectionSize = sect->size();
|
|
for (unsigned int i = 0; i < sectionSize; i++) if (sect->getPair(i)->getKey().equalsi(key)) return i;
|
|
return Jupiter::INVALID_INDEX;
|
|
}
|
|
|
|
const char *Jupiter::INIFile::get(const char *section, const char *key, const char *defaultValue) const
|
|
{
|
|
unsigned int size = Jupiter::INIFile::data_->data.size();
|
|
Jupiter::INIFile::Section *sect;
|
|
|
|
for (unsigned int i = 0; i < size; i++)
|
|
{
|
|
sect = Jupiter::INIFile::data_->data.get(i);
|
|
if (sect->getName().equalsi(section))
|
|
{
|
|
Jupiter::INIFile::Section::KeyValuePair *pair = sect->getPair(key);
|
|
if (pair == nullptr) return defaultValue;
|
|
return pair->getValue().c_str();
|
|
}
|
|
}
|
|
return defaultValue;
|
|
}
|
|
|
|
bool Jupiter::INIFile::getBool(const char *section, const char *key, bool defaultValue) const
|
|
{
|
|
const char *val = Jupiter::INIFile::get(section, key);
|
|
if (val != nullptr)
|
|
{
|
|
if (streqli(val, "FALSE")) return false;
|
|
if (streql(val, "0")) return false;
|
|
if (streqli(val, "OFF")) return false;
|
|
return true;
|
|
}
|
|
return defaultValue;
|
|
}
|
|
|
|
/*char Jupiter::INIFile::getChar(const char *section, const char *key) const
|
|
{
|
|
const char *val = Jupiter::INIFile::get(section,key);
|
|
if (val != nullptr) return val[0];
|
|
return 0;
|
|
}*/
|
|
|
|
short Jupiter::INIFile::getShort(const char *section, const char *key, short defaultValue) const
|
|
{
|
|
return (short)Jupiter::INIFile::getInt(section, key, defaultValue);
|
|
}
|
|
|
|
int Jupiter::INIFile::getInt(const char *section, const char *key, int defaultValue) const
|
|
{
|
|
const char *val = Jupiter::INIFile::get(section, key);
|
|
if (val != nullptr) return atoi(val);
|
|
return defaultValue;
|
|
}
|
|
|
|
long Jupiter::INIFile::getLong(const char *section, const char *key, long defaultValue) const
|
|
{
|
|
const char *val = Jupiter::INIFile::get(section, key);
|
|
if (val != nullptr) return strtol(val, nullptr, 0);
|
|
return defaultValue;
|
|
}
|
|
|
|
long long Jupiter::INIFile::getLongLong(const char *section, const char *key, long long defaultValue) const
|
|
{
|
|
const char *val = Jupiter::INIFile::get(section, key);
|
|
if (val != nullptr) return strtoll(val, nullptr, 0);
|
|
return defaultValue;
|
|
}
|
|
|
|
float Jupiter::INIFile::getFloat(const char *section, const char *key, float defaultValue) const
|
|
{
|
|
const char *val = Jupiter::INIFile::get(section, key);
|
|
if (val != nullptr) return strtof(val, nullptr);
|
|
return defaultValue;
|
|
}
|
|
|
|
double Jupiter::INIFile::getDouble(const char *section, const char *key, double defaultValue) const
|
|
{
|
|
const char *val = Jupiter::INIFile::get(section, key);
|
|
if (val != nullptr) return strtod(val, nullptr);
|
|
return defaultValue;
|
|
}
|
|
|
|
long double Jupiter::INIFile::getLongDouble(const char *section, const char *key, long double defaultValue) const
|
|
{
|
|
const char *val = Jupiter::INIFile::get(section, key);
|
|
if (val != nullptr) return strtold(val, nullptr);
|
|
return defaultValue;
|
|
}
|
|
|