@ -0,0 +1,2 @@ | |||
build/* | |||
src/version.h |
@ -0,0 +1,119 @@ | |||
#################### | |||
#Configure PROJECT | |||
#################### | |||
# set the PROJECT version number | |||
set (VERSION_MAJOR 0) | |||
set (VERSION_MINOR 0) | |||
set (VERSION_PATCH 0) | |||
set (VERSION_NUMBER "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") | |||
# Set required cmake version and project details | |||
cmake_minimum_required (VERSION 3.0) | |||
project ("ModdingFramework" VERSION "${VERSION_NUMBER}" LANGUAGES CXX) | |||
set (LIBRARY_TYPE SHARED) #Options: SHARED, STATIC, MODULAR | |||
# Set some project path variables | |||
set( PROJECT_CODE_DIR ${PROJECT_SOURCE_DIR}/src ) | |||
set( PROJECT_HEADER_DIR ${PROJECT_SOURCE_DIR}/src ) | |||
set( PROJECT_DEP_DIR ${PROJECT_SOURCE_DIR}/dependencies) | |||
set( PROJECT_TEST_DIR ${PROJECT_SOURCE_DIR}/test ) | |||
# Find required libraries | |||
#> For Lua mod support | |||
#find_package(Lua 5.3 REQUIRED) | |||
#Include header directories | |||
#>For ini file parsing | |||
include_directories( "${PROJECT_DEP_DIR}/cpp-feather-ini-parser" ) | |||
#>For LUA mod support | |||
#include_directories( "${PROJECT_DEP_DIR}/sol2/single/sol/" ) | |||
#include_directories( "${LUA_INCLUDE_DIR}" ) | |||
# Pull together all package libraries to link with the main executable | |||
set( LINK_LIBRARIES "" ) | |||
#TODO add lines like this: list( APPEND LINK_LIBRARIES ${CURSES_LIBRARIES} ) | |||
# Set compiler flags for different release types | |||
#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++14 -g -Wall -Weffc++") #TODO Tweak for the project | |||
#set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++14 -Wall -Weffc++") #TODO Tweak for the project | |||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -g -Wall -Weffc++") #TODO Tweak for the project | |||
#set paths for the source file that hold all the version info | |||
set (VERSION_SOURCE_CONFIG_FILE_PATH "${CMAKE_SOURCE_DIR}/src/version.h.in") | |||
set (VERSION_SOURCE_TARGET_FILE_PATH "${CMAKE_SOURCE_DIR}/src/version.h") | |||
#Use this in C++ to pull in the version string | |||
# * create file at VERSION_SOURCE_CONFIG_FILE_PATH (i.e. ${CMAKE_SOURCE_DIR}/src/version.h.in) | |||
# * write it like a normal header but instead of data use | |||
# @PROJECT_NAME@, @VERSION_MAJOR@, @VERSION_MINOR@, @VERSION_PATCH@, @VERSION_GIT@, and @VERSION_STRING@ | |||
############################### | |||
#Finished Configuring Project | |||
############################### | |||
#everything else is automatic | |||
#setup version file | |||
#>handle git version string | |||
if ( EXISTS "${CMAKE_SOURCE_DIR}/.git" ) | |||
execute_process( COMMAND git rev-parse HEAD | |||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | |||
OUTPUT_VARIABLE VERSION_GIT ) | |||
string(REGEX REPLACE "\n$" "" VERSION_GIT "${VERSION_GIT}") | |||
endif() | |||
#> add on git repo sha to version number if avalible. | |||
if (VERSION_GIT) | |||
set(VERSION_NUMBER "${VERSION_NUMBER}.${VERSION_GIT}") | |||
endif() | |||
#> Set version string that will be used in the version config file | |||
set( VERSION_STRING "${PROJECT_NAME} Version: ${VERSION_NUMBER}" ) | |||
#> Create the version source file if config file is avalible | |||
if ( EXISTS ${VERSION_SOURCE_CONFIG_FILE_PATH} ) | |||
configure_file(${VERSION_SOURCE_CONFIG_FILE_PATH} ${VERSION_SOURCE_TARGET_FILE_PATH} @ONLY) | |||
else() | |||
message(WARNING "Could not find version config source file at ${VERSION_SOURCE_CONFIG_FILE_PATH}. Look at CMakeLists.txt VERSION_SOURCE_CONFIG_FILE_PATH variable for more info.") | |||
endif() | |||
#Platform detection | |||
#TODO handle cpu type i.e. 32bit | |||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") | |||
add_definitions( -Dlinux ) | |||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") | |||
add_definitions( -Dwindows ) | |||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") | |||
add_definitions( -Dmac ) | |||
#else | |||
#TODO handle extra platforms/errors | |||
endif() | |||
# Collect source file paths into a var for later building | |||
file(GLOB_RECURSE PROJECT_SOURCES "${PROJECT_CODE_DIR}/*.cpp") | |||
file(GLOB_RECURSE PROJECT_HEADERS "${PROJECT_HEADER_DIR}/*.h") | |||
set (PROJECT_INCLUDE_DIRS "${PROJECT_HEADER_DIR}") | |||
# Build project and link it | |||
add_library(${PROJECT_NAME} ${LIBRARY_TYPE} ${PROJECT_SOURCES} ) | |||
target_include_directories( ${PROJECT_NAME} PRIVATE ${PROJECT_INCLUDE_DIRS} ) | |||
target_link_libraries( ${PROJECT_NAME} ${LINK_LIBRARIES} ) | |||
#Build example bianries | |||
add_subdirectory(examples/1_minimal) | |||
@ -0,0 +1,81 @@ | |||
Modding Framework library provides a drop in solution to allow user extension of a program. Mod can stand for module or modification and is a package of code that adds onto the original codebase. | |||
The library aims to do the following: | |||
* Support Linux, Windows, and MacOS. | |||
* Functional out of the box. | |||
* Mod configuration via simple [ini files](https://github.com/jtilly/inih). | |||
* Mod types of: configuration files (no code), pre-compiled library (dll, so, etc), and Lua. | |||
* Mod dependency handling. Automatically builds a dependency tree that loads mods in a certain order allowing mod inter-dependency. | |||
* Custom configuration file type. Add additional configuration file loaders and/or override the default. | |||
* Custom Mod handlers to add additional modding languages. | |||
* Possibly single header. | |||
# Usage | |||
# High-level Design and Extending Functionality | |||
Library is broken into 6 parts: | |||
* Configuration: Focused on loading configuration formats. | |||
* Dependency: Builds a loading order based on required and optional dependencies. | |||
* Implementation: Handles loading different mod types (lua/configuration/etc). | |||
* API: Holds API objects from each mod and the core program. | |||
* WebMediator: Handles http post and get requests to online mod repositories. | |||
* ModFrameworkCore: Core class that organizes everything. | |||
## Configuration | |||
The Configuration sub-system is based around recursive key/value objects and file parsers. These two aspects are, respectively, handled by the ConfigStore and ConfigLoader classes. | |||
### ConfigLoader | |||
The ConfigLoader base class forces derivatives to implement the validate, parse, and serialize functions. By default we include a INIConfigLoader class that loads [.ini style](https://github.com/jtilly/inih) config files. | |||
* Validate checks a given file is the right format. | |||
* Parse takes a file path and populates a ConfigStore object with the data therein. | |||
* Serialize converts a ConfigStore into the configuration file format and saves it to the given path. | |||
In the ModFrameworkCore, you can set the default ConfigLoader. There is also a function to register new formates and associate them with a ConfigLoader child class. | |||
### ConfigStore | |||
The ConfigCore class allows storing values in key/value pairs. By default supported values are string, int, floating point, and another ConfigStore instance. However additional value objects can be defined by sub-classing the ConfigValue class. ConfigCore has the get and set functions that return and take a const ConfigValue derived class. | |||
## Dependency | |||
The Dependency sub-system makes sure that mods will be loaded in the correct order. This is a self-contained sub-system and doesn't need any user extensions. | |||
## Implementation | |||
The Implementation sub-system deals with actually loading the meat of the Mod. By default there are 3 implementation mod types: | |||
* config: Mods just used to load up configuration files. | |||
* pre-compiled: Mods that load pre-compiled libraries. | |||
* Lua: Mods in the Lua language. | |||
New mod types are defined by creating a new derivative of the ModHandler. ModHandler derivatives need to implement the load function. | |||
The load function is given the directory path and is supposed to do everything needed to get a mod working. | |||
## API | |||
## WebMediator | |||
## ModFrameworkCore | |||
@ -0,0 +1,32 @@ | |||
# Compiled Object files | |||
*.slo | |||
*.lo | |||
*.o | |||
*.obj | |||
# Precompiled Headers | |||
*.gch | |||
*.pch | |||
# Compiled Dynamic libraries | |||
*.so | |||
*.dylib | |||
*.dll | |||
# Fortran module files | |||
*.mod | |||
# Compiled Static libraries | |||
*.lai | |||
*.la | |||
*.a | |||
*.lib | |||
# Executables | |||
*.exe | |||
*.out | |||
*.app | |||
# Other | |||
*.depend | |||
*.layout |
@ -0,0 +1,665 @@ | |||
/* | |||
Feather INI Parser - 1.41 | |||
You are free to use this however you wish. | |||
If you find a bug, please attept to debug the cause. | |||
Post your environment details and the cause or fix in the issues section of GitHub. | |||
Written by Turbine. | |||
Website: | |||
https://github.com/Turbine1991/feather-ini-parser | |||
http://code.google.com/p/feather-ini-parser/downloads | |||
Help: | |||
Bundled example & readme. | |||
http://code.google.com/p/feather-ini-parser/wiki/Tutorials | |||
*/ | |||
#pragma once | |||
#include <string> | |||
#include <fstream> | |||
#include <sstream> | |||
#include <stdint.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <ostream> | |||
#define FINI_SAFE | |||
#define FINI_BUFFER_SIZE 256 | |||
#if __cplusplus >= 201103L | |||
#include <unordered_map> | |||
#define FINI_CPP11 | |||
#define ALLOCATE_SECTIONS 100 | |||
#define ALLOCATE_KEYS 5 | |||
#else | |||
#include <map> | |||
#endif | |||
#ifdef FINI_WIDE_SUPPORT | |||
#include <wchar.h> | |||
typedef std::wstringstream fini_sstream_t; | |||
typedef std::wstring fini_string_t; | |||
typedef wchar_t fini_char_t; | |||
typedef std::wifstream fini_ifstream_t; | |||
typedef std::wofstream fini_ofstream_t; | |||
#define fini_strlen(a) wcslen(a) | |||
#define fini_strncpy(a, b) wcscpy(a, b) | |||
#define fini_strncpy(a, b, c) wcsncpy(a, b, c) | |||
#define fini_strtok(a, b) wcstok(a, b) | |||
#define _T(x) L ##x | |||
#else | |||
#include <cstring> | |||
typedef std::stringstream fini_sstream_t; | |||
typedef std::string fini_string_t; | |||
typedef char fini_char_t; | |||
typedef std::ifstream fini_ifstream_t; | |||
typedef std::ofstream fini_ofstream_t; | |||
#define fini_strlen(a) strlen(a) | |||
#define fini_strcpy(a, b) strcpy(a, b) | |||
#define fini_strncpy(a, b, c) strncpy(a, b, c) | |||
#define fini_strtok(a, b) strtok(a, b) | |||
#define _T(x) x | |||
#endif | |||
#define CHAR_SIZE sizeof(fini_char_t) | |||
///Simple converter using templates and streams to effectively required for the flexibility of handling native types | |||
class Converters | |||
{ | |||
public: | |||
template <typename T, typename U> | |||
static T Convert(U value); | |||
template <typename T> | |||
static void GetLine(fini_sstream_t& out, T& value); | |||
static void GetLine(fini_sstream_t& out, fini_string_t& value); | |||
template <typename T> | |||
static size_t GetDataSize(T& value); | |||
static size_t GetDataSize(fini_string_t value); | |||
}; | |||
/// | |||
template <typename T = fini_string_t, typename U = fini_string_t, typename V = fini_string_t> | |||
class INI | |||
{ | |||
public: | |||
typedef T section_t; | |||
typedef U key_t; | |||
typedef V value_t; | |||
typedef INI<section_t, key_t, value_t> ini_t; | |||
///Type definition declarations | |||
#ifdef FINI_CPP11 | |||
typedef typename std::unordered_map<key_t, value_t> keys_t; | |||
typedef typename std::unordered_map<section_t, keys_t*> sections_t; | |||
#else | |||
typedef typename std::map<key_t, value_t> keys_t; | |||
typedef typename std::map<section_t, keys_t*> sections_t; | |||
#endif | |||
typedef typename keys_t::iterator keysit_t; | |||
typedef typename sections_t::iterator sectionsit_t; | |||
typedef typename std::pair<key_t, value_t> keyspair_t; | |||
typedef typename std::pair<section_t, keys_t*> sectionspair_t; | |||
typedef char data_t; | |||
enum source_e {SOURCE_FILE, SOURCE_MEMORY}; | |||
///Data members | |||
std::string filename; | |||
data_t* data; | |||
size_t dataSize; | |||
keys_t* current; | |||
sections_t sections; | |||
source_e source; | |||
///Constuctor/Destructor | |||
//Specify the filename to associate and whether to parse immediately | |||
INI(const std::string filename, bool doParse): filename(filename) | |||
{ | |||
init(SOURCE_FILE, doParse); | |||
} | |||
//Used for loading INI from memory | |||
INI(void* data, size_t dataSize, bool doParse): data((data_t*)data), dataSize(dataSize) | |||
{ | |||
init(SOURCE_MEMORY, doParse); | |||
} | |||
~INI() | |||
{ | |||
clear(); | |||
} | |||
///Access Content | |||
//Provide bracket access to section contents | |||
keys_t& operator[](section_t section) | |||
{ | |||
#ifdef FINI_SAFE | |||
if (!sections[section]) | |||
sections[section] = new keys_t; | |||
#endif | |||
return *sections[section]; | |||
} | |||
//Create a new section and select it | |||
bool create(const section_t section) | |||
{ | |||
if (select(section)) | |||
return false; | |||
current = new keys_t; | |||
sections[section] = current; | |||
reserveKeys(current); | |||
return true; | |||
} | |||
//Select a section for performing operations | |||
bool select(const section_t section) | |||
{ | |||
sectionsit_t sectionsit = sections.find(section); | |||
if (sectionsit == sections.end()) | |||
return false; | |||
current = sectionsit->second; | |||
return true; | |||
} | |||
///Debug | |||
friend std::ostream& operator<<(std::ostream& os, const ini_t& ini) | |||
{ | |||
#ifdef FINI_CPP11 | |||
for(auto i = ini.sections.begin(); i != ini.sections.end(); i++) //typename ini_t::sectionsit_t | |||
{ | |||
//Section name as ini_t::section_t | |||
os << '[' << i->first << ']' << std::endl; | |||
if (i->second->size() == 0) //No keys/values in section, skip to next | |||
continue; | |||
for(typename ini_t::keysit_t j = i->second->begin(); j != i->second->end(); j++) | |||
{ | |||
//Name as ini_t::key_t & Value as ini_t::key_t | |||
os << " " << j->first << "=" << j->second << std::endl; | |||
} | |||
} | |||
#else | |||
std::cout << "Error: FINI requires CPP11 when outputting to stream." << std::endl; | |||
#endif | |||
return os; | |||
} | |||
///Set | |||
//Assign a value for key under the selected section | |||
bool set(const key_t key, const value_t value) | |||
{ | |||
if (current == NULL) | |||
return false; | |||
(*current)[key] = value; | |||
return true; | |||
} | |||
template <typename W, typename X> | |||
bool set(const W key, const X value) | |||
{ return set(Converters::Convert<key_t>(key), Converters::Convert<value_t>(value)); } | |||
///Get | |||
value_t get(const key_t key, value_t def = value_t()) | |||
{ | |||
keysit_t it = current->find(key); | |||
if (current == NULL || it == current->end()) | |||
return def; | |||
return it->second; | |||
} | |||
value_t get(const section_t section, const key_t key, value_t def) | |||
{ | |||
if (!select(section)) | |||
return def; | |||
return get(key, def); | |||
} | |||
template <typename W, typename X> | |||
X get(const W key, const X def = value_t()) | |||
{ return Converters::Convert<X>(get(Converters::Convert<key_t>(key), Converters::Convert<value_t>(def))); } | |||
template <typename W> | |||
fini_string_t get(const W key, const fini_char_t* def = _T("")) //Handle C string default value without casting | |||
{ return Converters::Convert<fini_string_t>(get(Converters::Convert<key_t>(key), Converters::Convert<value_t>(def))); } | |||
template <typename W, typename X, typename Y> | |||
Y get(const W section, const X key, const Y def) | |||
{ return Converters::Convert<Y>(get(Converters::Convert<section_t>(section), Converters::Convert<key_t>(key), Converters::Convert<value_t>(def))); } | |||
template <typename W, typename X> | |||
fini_string_t get(const W section, const X key, const fini_char_t* def) //Handle C string default value without casting | |||
{ return Converters::Convert<fini_string_t>(get(Converters::Convert<section_t>(section), Converters::Convert<key_t>(key), Converters::Convert<value_t>(def))); } | |||
///Functions | |||
void parse(std::istream& file) | |||
{ | |||
fini_char_t line[FINI_BUFFER_SIZE]; | |||
bool first = true; | |||
fini_sstream_t out; | |||
while(!file.eof()) | |||
{ | |||
file.getline(line, FINI_BUFFER_SIZE); | |||
if (first) | |||
{ | |||
first = false; | |||
if (line[0] == 0xEF) //Allows handling of UTF-16/32 documents | |||
{ | |||
memmove(line, line + (CHAR_SIZE * 3), CHAR_SIZE * (FINI_BUFFER_SIZE - 3)); | |||
return; | |||
} | |||
} | |||
nake(line); | |||
if (line[0]) | |||
{ | |||
size_t len = fini_strlen(line); | |||
if (len > 0 && !((len >= 2 && (line[0] == '/' && line[1] == '/')) || (len >= 1 && line[0] == '#'))) //Ignore comment and empty lines | |||
{ | |||
if (line[0] == '[') //Section | |||
{ | |||
section_t section; | |||
size_t length = fini_strlen(line) - 2; //Without section brackets | |||
while(isspace(line[length + 1])) //Leave out any additional new line characters, not "spaces" as the name suggests | |||
--length; | |||
fini_char_t* ssection = (fini_char_t*)calloc(CHAR_SIZE, length + 1); | |||
fini_strncpy(ssection, line + 1, length); //Count after first bracket | |||
current = new keys_t; | |||
out << ssection; | |||
free(ssection); | |||
Converters::GetLine(out, section); | |||
sections[section] = current; | |||
} | |||
else //Key | |||
{ | |||
key_t key; | |||
value_t value; | |||
fini_char_t* skey; | |||
fini_char_t* svalue; | |||
skey = fini_strtok(line, _T("=")); | |||
svalue = fini_strtok(NULL, _T("\n")); | |||
if (skey && svalue) | |||
{ | |||
size_t index = 0; //Without section brackets | |||
while(isspace(skey[index])) //Leave out any additional new line characters, not "spaces" as the name suggests | |||
index++; | |||
if (index != 0) //Has preceeding white space | |||
fini_strcpy(skey, skey + index); | |||
out << skey; | |||
Converters::GetLine(out, key); | |||
out.clear(); | |||
out.str(fini_string_t()); | |||
out << svalue; | |||
Converters::GetLine(out, value); | |||
if (value != value_t()) | |||
(*current)[key] = value; | |||
} | |||
} | |||
out.clear(); | |||
out.str(fini_string_t()); //Clear existing stream; | |||
} | |||
} | |||
} | |||
} | |||
//Parse an INI's contents into memory from the filename given during construction | |||
bool parse() | |||
{ | |||
switch(source) | |||
{ | |||
case SOURCE_FILE: { | |||
fini_ifstream_t file(filename.c_str()); | |||
if (!file.is_open()) | |||
return false; | |||
parse(file); | |||
file.close(); | |||
} | |||
break; | |||
case SOURCE_MEMORY: { | |||
std::stringstream sstream; | |||
sstream.rdbuf()->pubsetbuf(data, dataSize); | |||
parse(sstream); | |||
} | |||
break; | |||
} | |||
return true; | |||
} | |||
bool parseBinary() | |||
{ | |||
fini_ifstream_t file(filename.c_str(), std::ios::binary); | |||
if (!file.is_open()) | |||
return false; | |||
size_t sectionCount; | |||
size_t keyCount; | |||
key_t key; | |||
value_t value; | |||
section_t section; | |||
//file.read((fini_char_t*)§ionCount, sizeof(sectionCount)); | |||
file >> sectionCount; | |||
for(size_t i = 0; i < sectionCount; i++) | |||
{ | |||
if (i > 0) | |||
file.seekg(1 + file.tellg()); | |||
file.read((fini_char_t*)&keyCount, sizeof(keyCount)); | |||
file >> section; | |||
create(section); | |||
for(size_t j = 0; j < keyCount; j++) | |||
{ | |||
file >> key; | |||
file >> value; | |||
set(key, value); | |||
} | |||
} | |||
file.close(); | |||
return true; | |||
} | |||
//Clear the contents from memory | |||
void clear() | |||
{ | |||
clean(); | |||
sections.clear(); | |||
} | |||
///Output | |||
//Save from memory into file | |||
bool save(const std::string filename = "") | |||
{ | |||
if (!hasFileAssociation(filename)) | |||
return false; | |||
fini_ofstream_t file(((filename == "")? this->filename: filename).c_str(), std::ios::trunc); | |||
if (!file.is_open()) | |||
return false; | |||
//Loop through sections | |||
for(typename INI::sectionsit_t i = sections.begin(); i != sections.end(); i++) | |||
{ | |||
if (i->second->size() == 0) //No keys/values in section, skip to next | |||
continue; | |||
//Write section | |||
const fini_string_t temp = makeSection(i->first); | |||
const fini_char_t* line = temp.c_str(); | |||
file.write(line, fini_strlen(line)); | |||
for(typename INI::keysit_t j = i->second->begin(); j != i->second->end(); j++) | |||
{ | |||
//Write key and value | |||
const fini_string_t temp = makeKeyValue(j->first, j->second); | |||
const fini_char_t* line = temp.c_str(); | |||
file.write(line, fini_strlen(line)); | |||
} | |||
} | |||
file.close(); | |||
return true; | |||
} | |||
//Saves it without any conventional INI formatting characters, however it only uses string streams | |||
bool saveBinary(const std::string filename = "") | |||
{ | |||
if (!hasFileAssociation(filename)) | |||
return false; | |||
fini_ofstream_t file(((filename == "")? this->filename: filename).c_str(), std::ios::trunc | std::ios::binary); | |||
if (!file.is_open()) | |||
return false; | |||
size_t sectionCount = sections.size(); | |||
size_t keyCount; | |||
file.write((fini_char_t*)§ionCount, sizeof(sectionCount)); | |||
//Loop through sections | |||
for(typename INI::sectionsit_t i = sections.begin(); i != sections.end(); i++) | |||
{ | |||
keyCount = i->second->size(); | |||
file.write((fini_char_t*)&keyCount, sizeof(keyCount)); | |||
file << i->first << std::endl; | |||
for(typename INI::keysit_t j = i->second->begin(); j != i->second->end(); j++) | |||
{ | |||
file << j->first << std::endl; | |||
file << j->second << std::endl; | |||
} | |||
} | |||
file.close(); | |||
return true; | |||
} | |||
//Saves it as a true binary file, intended to replace the existing one. Don't bother using it with all strings. | |||
bool saveBinaryExperimental(std::string filename = "") | |||
{ | |||
if (!hasFileAssociation(filename)) | |||
return false; | |||
fini_ofstream_t file(((filename == "")? this->filename: filename).c_str(), std::ios::trunc | std::ios::binary); | |||
if (!file.is_open()) | |||
return false; | |||
size_t sectionCount = sections.size(); | |||
size_t keyCount; | |||
file.write((fini_char_t*)§ionCount, sizeof(sectionCount)); | |||
//Loop through sections | |||
for(typename INI::sectionsit_t i = sections.begin(); i != sections.end(); i++) | |||
{ | |||
keyCount = i->second->size(); | |||
file.write((fini_char_t*)&keyCount, sizeof(keyCount)); | |||
file.write((fini_char_t*)&i->first, Converters::GetDataSize(i->first)); | |||
for(typename INI::keysit_t j = i->second->begin(); j != i->second->end(); j++) | |||
{ | |||
file.write((fini_char_t*)&j->first, Converters::GetDataSize(j->first)); | |||
file.write((fini_char_t*)&j->second, Converters::GetDataSize(j->second)); | |||
} | |||
} | |||
file.close(); | |||
return true; | |||
} | |||
//Alows another INI's contents to be insert into another, with the ability to retain the original values | |||
void merge(ini_t& other, bool retainValues = true) | |||
{ | |||
for(typename INI::sectionsit_t i = other.sections.begin(); i != other.sections.end(); i++) | |||
{ | |||
if (!select(i->first)) //Create and insert all key values into a missing section | |||
{ | |||
keys_t* keys = new keys_t(*i->second); | |||
sections.insert(std::make_pair(i->first, keys)); | |||
} | |||
else | |||
{ | |||
for(typename INI::keysit_t j = i->second->begin(); j != i->second->end(); j++) | |||
{ | |||
keysit_t it = current->find(j->first); | |||
if (it == current->end()) | |||
current->insert(std::make_pair(j->first, j->second)); | |||
else if (!retainValues) | |||
it->second = j->second; | |||
} | |||
} | |||
} | |||
} | |||
private: | |||
///Functions | |||
//Init the INI in with values set by constructor | |||
void init(source_e source, bool doParse) | |||
{ | |||
this->source = source; | |||
reserveSections(); | |||
if (doParse) | |||
parse(); | |||
} | |||
//Clean the contents for descruction | |||
void clean() | |||
{ | |||
for(sectionsit_t i = sections.begin(); i != sections.end(); i++) | |||
delete i->second; | |||
current = NULL; | |||
} | |||
//Make any alterations to the raw line | |||
void nake(const fini_char_t*) //Strip the line of any non-interpretable characters | |||
{ | |||
} | |||
void reserveSections() | |||
{ | |||
#ifdef FINI_CPP11 | |||
sections.reserve(ALLOCATE_SECTIONS); | |||
#endif | |||
} | |||
void reserveKeys(keys_t* current) | |||
{ | |||
#ifdef FINI_CPP11 | |||
current->reserve(ALLOCATE_KEYS); | |||
#endif | |||
} | |||
bool hasFileAssociation(std::string filename) | |||
{ | |||
if (source == SOURCE_MEMORY && filename == "") //No association to a file | |||
return false; | |||
return true; | |||
} | |||
///Output | |||
//Creates a section as a string | |||
fini_string_t makeSection(const section_t& section) | |||
{ | |||
fini_sstream_t line; | |||
line << '[' << section << ']' << std::endl; | |||
return line.str(); | |||
} | |||
//Creates a key and a value as a string | |||
fini_string_t makeKeyValue(const key_t& key, const value_t& value) | |||
{ | |||
fini_sstream_t line; | |||
line << key << '=' << value << std::endl; | |||
return line.str(); | |||
} | |||
}; | |||
///Definitions | |||
template <typename T, typename U> | |||
inline T Converters::Convert(U value) | |||
{ | |||
fini_sstream_t sout; | |||
T result; | |||
sout << value; | |||
sout >> result; | |||
sout.str(fini_string_t()); | |||
return result; | |||
} | |||
template <> | |||
inline fini_string_t Converters::Convert<fini_string_t, fini_string_t>(fini_string_t value) | |||
{ | |||
return value; | |||
} | |||
template <> | |||
inline fini_string_t Converters::Convert<fini_string_t>(const fini_char_t* value) | |||
{ | |||
return value; | |||
} | |||
template <typename T> | |||
inline void Converters::GetLine(fini_sstream_t& out, T& value) | |||
{ | |||
out >> value; | |||
} | |||
inline void Converters::GetLine(fini_sstream_t& out, fini_string_t& value) | |||
{ | |||
std::getline(out, value); | |||
} | |||
template <typename T> | |||
inline size_t Converters::GetDataSize(T& value) | |||
{ | |||
return sizeof(value); | |||
} | |||
inline size_t Converters::GetDataSize(fini_string_t value) | |||
{ | |||
return value.size() + 1; | |||
} |
@ -0,0 +1,21 @@ | |||
The MIT License (MIT) | |||
Copyright (c) 2014 Turbine1991 | |||
Permission is hereby granted, free of charge, to any person obtaining a copy | |||
of this software and associated documentation files (the "Software"), to deal | |||
in the Software without restriction, including without limitation the rights | |||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
copies of the Software, and to permit persons to whom the Software is | |||
furnished to do so, subject to the following conditions: | |||
The above copyright notice and this permission notice shall be included in all | |||
copies or substantial portions of the Software. | |||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
SOFTWARE. |
@ -0,0 +1,80 @@ | |||
feather-ini-parser | |||
================== | |||
Intuitive, fast, lightweight, header, portable INI parser for ANSI C++. | |||
``` | |||
INI<> ini("filename.ini", true); // Open and parse | |||
ini.get("section", "key", "value", "default"); // Get section -> key -> value, return "default" if not found | |||
ini.set("section", "key", "value"); // Set section -> key -> value | |||
ini.save(); // Save over initial file | |||
for(auto i: ini.sections) // Loop through all sections | |||
{ | |||
String section = i.first; | |||
for(auto j: *i.second) // Loop through all key/values | |||
String key = j.first, value = j.second; | |||
} | |||
``` | |||
## Methods | |||
Statement | Return Type | |||
------------- | ------------- | |||
ini(filename, doParse)|constructor | |||
ini(data, dataSize, doParse)|constructor | |||
ini.parse()|bool | |||
ini.merge(other INI, retainValues)|void | |||
ini.create(section)|bool | |||
ini.select(section)|bool | |||
ini.set(key, value)|bool | |||
ini.get(key, dvalue = value_t())|dvalue_t | |||
ini.save(filename = "")|bool | |||
ini.clear()|bool | |||
ini[section][key]|value_t& | |||
ini[section]|keys_t& | |||
## Example | |||
``` | |||
// Please view the complete list of examplex in 'example/example.cpp' | |||
#include <iostream> | |||
#include <String> | |||
#include "INI.h" | |||
using namespace std; | |||
``` | |||
... | |||
``` | |||
INI<> ini("filename.ini", true); // Load file and parse | |||
ini.create("section1"); //Create a section and select it (into the active context) | |||
ini.set("key", "value"); | |||
// Set equivelant | |||
ini.set("section1", "key", "value"); | |||
// Set equivelant (non-safe, performance) | |||
ini["section1"]["key"] = "value"; | |||
cout << ini.get("keynumeric", "default") << endl; | |||
// Get equivelant | |||
cout << ini.get("section1", "keynumeric", "default") << endl; | |||
ini.save(); | |||
// Loop through all sections and keys (CPP11) | |||
for(auto i: ini.sections) | |||
{ | |||
String section = i.first; | |||
cout << "[" << section << "]" << endl; | |||
for(auto j: *i.second) | |||
{ | |||
String key = j.first, value = j.second; | |||
cout << " " << key << "=" << value << endl; | |||
} | |||
} | |||
``` | |||
## More | |||
Please see the example .cpp file and Code::Blocks .cbp project for a compilable GCC and VSC++ example. Further examples include enabling wide char support. |
@ -0,0 +1,130 @@ | |||
#include <iostream> | |||
#include <cstring> | |||
#include <stdint.h> | |||
#include "../INI.h" | |||
using namespace std; | |||
void centerString(string str); //Printing to console | |||
std::string getStringFromFile(const std::string& path); //Source for data loading from memory. | |||
int main() | |||
{ | |||
///Declare | |||
typedef INI<> ini_t; //Makes things shorter/easier to write <Section, Key, Value> | |||
//or | |||
//typedef INI<string, string, string> ini_t; //Equivelant to previous line when wide characters are disabled | |||
ini_t ini("file.ini", true); //File to open/default save filename. The constuctor is set to parse by default, unless specified as false | |||
///Manipulate and access contents | |||
centerString("########## Access & Manipulate Contents ##########"); | |||
//Common usage | |||
ini.create("Section 1"); | |||
ini.create("Section 2"); | |||
ini.get("Key1", "DefaultValue"); | |||
ini.select("Section 1"); | |||
ini.set("Key2", "Value"); | |||
ini.save(); //Save contents to file, optional filename parameter available | |||
ini.clear(); //Clear INI contents from memory | |||
//Extended usage | |||
ini["Section Name"]["Key"] = "Value"; //You are not required to create a section first | |||
ini.create("Section1"); //Also selects as current section | |||
ini.create("Section2"); //Current | |||
ini.set("Key1", "Value1"); //Added pair under section "Section2" | |||
ini.select("Section1"); //Current | |||
cout << ini.get("Key1", "-1") << endl; //Returns "-1" as no key exists, no default will return NULL for data type, eg int() is 0 | |||
ini.select("Section2"); | |||
ini.set("Key1", "1.123"); | |||
cout << ini.get("Key1", -1.0) << endl; //Return value as double | |||
ini.set(123, 123); //Will convert to provided INI data type for key/value, in this case string for both | |||
ini.save(); | |||
ini.clear(); | |||
ini.parse(); //Parses file into objects in memory | |||
cout << ini["Section2"]["Key1"] << endl; //Returns "Value1", slightly more overhead involved seeking section, avoid using excessively | |||
///Iterate through sections and keys for both C++11 and C++98 | |||
centerString("########## Iterate Contents ##########"); | |||
#ifdef FINI_CPP11 | |||
for(auto i: ini.sections) | |||
{ | |||
cout << "[" << i.first << "]" << endl; | |||
//for(auto j = i.second->begin(); j != i.second->end(); j++) | |||
for(auto j: *i.second) | |||
{ | |||
cout << " " << j.first << "=" << j.second << endl; | |||
} | |||
} | |||
#else | |||
for(ini_t::sectionsit_t i = ini.sections.begin(); i != ini.sections.end(); i++) | |||
{ | |||
//Section name as ini_t::section_t | |||
cout << i->first << endl; | |||
if (i->second->size() == 0) //No keys/values in section, skip to next | |||
continue; | |||
for(ini_t::keysit_t j = i->second->begin(); j != i->second->end(); j++) | |||
{ | |||
//Name as ini_t::key_t & Value as ini_t::key_t | |||
cout << " " << j->first << "=" << j->second << endl; | |||
} | |||
} | |||
#endif | |||
///Example with different data types | |||
typedef INI <unsigned char, string, float> ini_int_t; //Makes things shorter/easier to write <Section, Key, Value> | |||
ini_int_t ini_int("file_ints.ini", false); //File to open/default save filename. The constuctor is set to parse by default, unless specified as false | |||
for(int i = 1; i <= 200; i++) | |||
{ | |||
ini_int.create(i); //Section | |||
ini_int.set("Key", i / 2.f); | |||
} | |||
ini_int.save(); | |||
///Wide char support example (please define FINI_WIDE_SUPPORT in project) | |||
/* | |||
ini_t ini_w("file.ini", true); | |||
wcout << ini_w[L"Section2"][L"Key1"] << endl; | |||
*/ | |||
///Load from memory | |||
std::string str = getStringFromFile("config/test.ini"); //Allows us to tap into a source for the purpose of this example | |||
ini_t ini_mem((void*)str.c_str(), str.size(), true); //This is the line which parses data from memory | |||
///Merge contents and keep values | |||
ini_t inid("file.ini", true); | |||
ini_t inis("merge.ini", true); | |||
inid.merge(inis, true); | |||
inid.save("merged.ini"); | |||
return EXIT_SUCCESS; | |||
} | |||
void centerString(string str) | |||
{ | |||
const char* s = str.c_str(); | |||
int l = strlen(s); | |||
int pos = (int)((80 - l) / 2); | |||
for(int i = 0; i < pos; i++) | |||
cout << " "; | |||
cout << s << endl; | |||
} | |||
std::string getStringFromFile(const std::string& path) { | |||
std::ostringstream buf; | |||
std::ifstream input (path.c_str()); | |||
buf << input.rdbuf(); | |||
return buf.str(); | |||
} |
@ -0,0 +1,5 @@ | |||
[Section2] | |||
123=123 | |||
Key1=1.123 | |||
[Section Name] | |||
Key=Value |
@ -0,0 +1,400 @@ | |||
[200] | |||
Key=100 | |||
[199] | |||
Key=99.5 | |||
[198] | |||
Key=99 | |||
[197] | |||
Key=98.5 | |||
[196] | |||
Key=98 | |||
[195] | |||
Key=97.5 | |||
[194] | |||
Key=97 | |||
[193] | |||
Key=96.5 | |||
[192] | |||
Key=96 | |||
[191] | |||
Key=95.5 | |||
[190] | |||
Key=95 | |||
[189] | |||
Key=94.5 | |||
[188] | |||
Key=94 | |||
[187] | |||
Key=93.5 | |||
[186] | |||
Key=93 | |||
[185] | |||
Key=92.5 | |||
[184] | |||
Key=92 | |||
[183] | |||
Key=91.5 | |||
[182] | |||
Key=91 | |||
[181] | |||
Key=90.5 | |||
[180] | |||
Key=90 | |||
[179] | |||
Key=89.5 | |||
[178] | |||
Key=89 | |||
[177] | |||
Key=88.5 | |||
[176] | |||
Key=88 | |||
[175] | |||
Key=87.5 | |||
[174] | |||
Key=87 | |||
[173] | |||
Key=86.5 | |||
[172] | |||
Key=86 | |||
[171] | |||
Key=85.5 | |||
[170] | |||
Key=85 | |||
[169] | |||
Key=84.5 | |||
[168] | |||
Key=84 | |||
[167] | |||
Key=83.5 | |||
[166] | |||
Key=83 | |||
[165] | |||
Key=82.5 | |||
[164] | |||
Key=82 | |||
[163] | |||
Key=81.5 | |||
[162] | |||
Key=81 | |||
[161] | |||
Key=80.5 | |||
[160] | |||
Key=80 | |||
[159] | |||
Key=79.5 | |||
[158] | |||
Key=79 | |||
[157] | |||
Key=78.5 | |||
[156] | |||
Key=78 | |||
[155] | |||
Key=77.5 | |||
[154] | |||
Key=77 | |||
[153] | |||
Key=76.5 | |||
[152] | |||
Key=76 | |||
[151] | |||
Key=75.5 | |||
[150] | |||
Key=75 | |||
[149] | |||
Key=74.5 | |||
[148] | |||
Key=74 | |||
[147] | |||
Key=73.5 | |||
[146] | |||
Key=73 | |||
[145] | |||
Key=72.5 | |||
[144] | |||
Key=72 | |||
[143] | |||
Key=71.5 | |||
[142] | |||
Key=71 | |||
[141] | |||
Key=70.5 | |||
[140] | |||
Key=70 | |||
[139] | |||
Key=69.5 | |||
[138] | |||
Key=69 | |||
[137] | |||
Key=68.5 | |||
[136] | |||
Key=68 | |||
[135] | |||
Key=67.5 | |||
[134] | |||
Key=67 | |||
[133] | |||
Key=66.5 | |||
[132] | |||
Key=66 | |||
[131] | |||
Key=65.5 | |||
[130] | |||
Key=65 | |||
[129] | |||
Key=64.5 | |||
[128] | |||
Key=64 | |||
[127] | |||
Key=63.5 | |||
[126] | |||
Key=63 | |||
[125] | |||
Key=62.5 | |||
[124] | |||
Key=62 | |||
[123] | |||
Key=61.5 | |||
[122] | |||
Key=61 | |||
[121] | |||
Key=60.5 | |||
[120] | |||
Key=60 | |||
[119] | |||
Key=59.5 | |||
[118] | |||
Key=59 | |||
[117] | |||
Key=58.5 | |||
[116] | |||
Key=58 | |||
[115] | |||
Key=57.5 | |||
[114] | |||
Key=57 | |||
[113] | |||
Key=56.5 | |||
[112] | |||
Key=56 | |||
[111] | |||
Key=55.5 | |||
[110] | |||
Key=55 | |||
[109] | |||
Key=54.5 | |||
[108] | |||
Key=54 | |||
[107] | |||
Key=53.5 | |||
[106] | |||
Key=53 | |||
[105] | |||
Key=52.5 | |||
[104] | |||
Key=52 | |||
[103] | |||
Key=51.5 | |||
[1] | |||
Key=0.5 | |||
[2] | |||
Key=1 | |||
[3] | |||
Key=1.5 | |||
[4] | |||
Key=2 | |||
[5] | |||
Key=2.5 | |||
[6] | |||
Key=3 | |||
[7] | |||
Key=3.5 | |||
[8] | |||
Key=4 | |||
[9] | |||
Key=4.5 | |||
[10] | |||
Key=5 | |||
[11] | |||
Key=5.5 | |||
[12] | |||
Key=6 | |||
[13] | |||
Key=6.5 | |||
[14] | |||
Key=7 | |||
[15] | |||
Key=7.5 | |||
[16] | |||
Key=8 | |||
[17] | |||
Key=8.5 | |||
[18] | |||
Key=9 | |||
[19] | |||
Key=9.5 | |||
[20] | |||
Key=10 | |||
[21] | |||
Key=10.5 | |||
[22] | |||
Key=11 | |||
[23] | |||
Key=11.5 | |||
[24] | |||
Key=12 | |||
[25] | |||
Key=12.5 | |||
[26] | |||
Key=13 | |||
[27] | |||
Key=13.5 | |||
[28] | |||
Key=14 | |||
[29] | |||
Key=14.5 | |||
[30] | |||
Key=15 | |||
[31] | |||
Key=15.5 | |||
[32] | |||
Key=16 | |||
[33] | |||
Key=16.5 | |||
[34] | |||
Key=17 | |||
[35] | |||
Key=17.5 | |||
[36] | |||
Key=18 | |||
[37] | |||
Key=18.5 | |||
[38] | |||
Key=19 | |||
[39] | |||
Key=19.5 | |||
[40] | |||
Key=20 | |||
[41] | |||
Key=20.5 | |||
[42] | |||
Key=21 | |||
[43] | |||
Key=21.5 | |||
[44] | |||
Key=22 | |||
[45] | |||
Key=22.5 | |||
[46] | |||
Key=23 | |||
[47] | |||
Key=23.5 | |||
[48] | |||
Key=24 | |||
[49] | |||
Key=24.5 | |||
[50] | |||
Key=25 | |||
[51] | |||
Key=25.5 | |||
[52] | |||
Key=26 | |||
[53] | |||
Key=26.5 | |||
[54] | |||
Key=27 | |||
[55] | |||
Key=27.5 | |||
[56] | |||
Key=28 | |||
[57] | |||
Key=28.5 | |||
[58] | |||
Key=29 | |||
[59] | |||
Key=29.5 | |||
[60] | |||
Key=30 | |||
[61] | |||
Key=30.5 | |||
[62] | |||
Key=31 | |||
[63] | |||
Key=31.5 | |||
[64] | |||
Key=32 | |||
[65] | |||
Key=32.5 | |||
[66] | |||
Key=33 | |||
[67] | |||
Key=33.5 | |||
[68] | |||
Key=34 | |||
[69] | |||
Key=34.5 | |||
[70] | |||
Key=35 | |||
[71] | |||
Key=35.5 | |||
[72] | |||
Key=36 | |||
[73] | |||
Key=36.5 | |||
[74] | |||
Key=37 | |||
[75] | |||
Key=37.5 | |||
[76] | |||
Key=38 | |||
[77] | |||
Key=38.5 | |||
[78] | |||
Key=39 | |||
[79] | |||
Key=39.5 | |||
[80] | |||
Key=40 | |||
[81] | |||
Key=40.5 | |||
[82] | |||
Key=41 | |||
[83] | |||
Key=41.5 | |||
[84] | |||
Key=42 | |||
[85] | |||
Key=42.5 | |||
[86] | |||
Key=43 | |||
[87] | |||
Key=43.5 | |||
[88] | |||
Key=44 | |||
[89] | |||
Key=44.5 | |||
[90] | |||
Key=45 | |||
[91] | |||
Key=45.5 | |||
[92] | |||
Key=46 | |||
[93] | |||
Key=46.5 | |||
[94] | |||
Key=47 | |||
[95] | |||
Key=47.5 | |||
[96] | |||
Key=48 | |||
[97] | |||
Key=48.5 | |||
[98] | |||
Key=49 | |||
[99] | |||
Key=49.5 | |||
[100] | |||
Key=50 | |||
[101] | |||
Key=50.5 | |||
[102] | |||
Key=51 |
@ -0,0 +1,5 @@ | |||
[NewSection] | |||
Key=Value | |||
[Section2] | |||
NewKey=Value | |||
123=456 |
@ -0,0 +1,57 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | |||
<CodeBlocks_project_file> | |||
<FileVersion major="1" minor="6" /> | |||
<Project> | |||
<Option title="project" /> | |||
<Option pch_mode="2" /> | |||
<Option compiler="gcc" /> | |||
<Build> | |||
<Target title="gcc_mingw"> | |||
<Option output="bin/gcc_mingw/example" prefix_auto="1" extension_auto="1" /> | |||
<Option object_output="obj/gcc_mingw/" /> | |||
<Option type="1" /> | |||
<Option compiler="gcc" /> | |||
<Compiler> | |||
<Add option="-O2" /> | |||
<Add option="-Wall" /> | |||
<Add option="-std=c++0x" /> | |||
</Compiler> | |||
</Target> | |||
<Target title="vs_2013"> | |||
<Option output="bin/vs/example" prefix_auto="1" extension_auto="1" /> | |||
<Option object_output="obj/vs_2013/" /> | |||
<Option type="1" /> | |||
<Option compiler="microsoft_visual_c_2013" /> | |||
<Compiler> | |||
<Add option="/EHa" /> | |||
<Add option="/W2" /> | |||
<Add directory="C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/include" /> | |||
</Compiler> | |||
<Linker> | |||
<Add directory="C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/lib" /> | |||
<Add directory="C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Lib" /> | |||
</Linker> | |||
</Target> | |||
<Target title="vs_2010"> | |||
<Option output="bin/vs/example" prefix_auto="1" extension_auto="1" /> | |||
<Option object_output="obj/vs_2010/" /> | |||
<Option type="1" /> | |||
<Option compiler="msvc10" /> | |||
<Compiler> | |||
<Add option="/EHa" /> | |||
<Add option="/W2" /> | |||
</Compiler> | |||
<Linker> | |||
<Add directory="C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Lib" /> | |||
</Linker> | |||
</Target> | |||
</Build> | |||
<Unit filename="../INI.h" /> | |||
<Unit filename="example.cpp" /> | |||
<Extensions> | |||
<code_completion /> | |||
<envvars /> | |||
<debugger /> | |||
</Extensions> | |||
</Project> | |||
</CodeBlocks_project_file> |
@ -0,0 +1,12 @@ | |||
# Collect source file paths into a var for later building | |||
file(GLOB_RECURSE SUB_PROJECT_SOURCES "src/*.cpp") | |||
file(GLOB_RECURSE SUB_PROJECT_HEADERS "src/*.h") | |||
#pull in the project's headers | |||
include_directories( ${PROJECT_HEADER_DIR} ) | |||
# Build project and link it | |||
add_executable( 1_Minimal_Example ${SUB_PROJECT_SOURCES} ) | |||
target_include_directories( 1_Minimal_Example PRIVATE ${SUB_PROJECT_INCLUDE_DIRS} ) | |||
target_link_libraries( 1_Minimal_Example ModdingFramework) |
@ -0,0 +1,2 @@ | |||
name=mod 1 | |||
id=2dk53l89mn3n7JdY801264Kds0H |
@ -0,0 +1,20 @@ | |||
//Author: | |||
//Description: | |||
#include <ModdingFrameworkCore.h> | |||
#include <Configuration/ConfigStore.h> | |||
#include <Configuration/FileOperations.h> | |||
#include <memory> | |||
#include <iostream> | |||
int main (int argc, char* argv[]) { | |||
std::unique_ptr<ModdingFrameworkCore> mod_framework; | |||
mod_framework = std::make_unique<ModdingFrameworkCore>("mods"); | |||
std::shared_ptr<ConfigStore> data = mod_framework->mod_config[0]; | |||
std::cout << data->getStr("name") << "; " << data->getStr("id") << std::endl; | |||
return 0; | |||
} |
@ -0,0 +1,27 @@ | |||
#ifndef ConfigLoaderBase_H | |||
#define ConfigLoaderBase_H | |||
#include "ConfigStore.h" | |||
#include <string> | |||
//base class for config loaders mostly abstract though it includes some type identification functions | |||
class ConfigLoaderBase { | |||
public: | |||
std::string extension; | |||
ConfigLoaderBase(std::string ext) : extension(ext) {}; | |||
virtual ~ConfigLoaderBase() {}; | |||
virtual bool validate(std::string filepath) = 0; | |||
virtual std::shared_ptr<ConfigStore> parse(std::string filepath) = 0; | |||
virtual bool serialize(std::shared_ptr<ConfigStore> data, std::string filepath) = 0; | |||
}; | |||
#endif |
@ -0,0 +1,72 @@ | |||
#include "ConfigLoaderINI.h" | |||
#include "ConfigStore.h" | |||
//The following lets us include a 3rd party lib without throwing compile warnings | |||
#ifdef linux | |||