diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3f925daa97dabfd7bbc0990665014856e677864f..4b632f04cebdae375592bdf19a2f72dd74f82564 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -8,7 +8,7 @@ include(FindThreads)
 
 #----------------------------------------------------------------------------
 # Sources and headers
-file(GLOB src "*.cxx")
+file(GLOB src "*.cxx" "*.cpp")
 file(GLOB allheaders RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h")
 list(REMOVE_ITEM allheaders
   "${CMAKE_CURRENT_SOURCE_DIR}/${LIBNAME}_LinkDef.h"
diff --git a/src/ConfigObject.cpp b/src/ConfigObject.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ee18cd36afcc2b782b33a642e35618379256f7c6
--- /dev/null
+++ b/src/ConfigObject.cpp
@@ -0,0 +1,332 @@
+//============================================================================//
+// A class based on the support from ConfigParser and ConfigValue             //
+// It provides a simple way to read text file as configuration file, and read //
+// or modify a parameter in the inherited class                               //
+// The Configure() function should be overloaded according to specialized     //
+// requirements, and be called after the parameters being configured          //
+//                                                                            //
+// Chao Peng                                                                  //
+// 10/31/2016                                                                 //
+//============================================================================//
+
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <algorithm>
+#include "ConfigObject.h"
+
+
+
+//============================================================================//
+// Constructor, Destructor                                                    //
+//============================================================================//
+
+// constructor
+ConfigObject::ConfigObject(const std::string &splitter, const std::string &ignore, bool case_ins)
+: split_chars(splitter), ignore_chars(ignore), case_insensitive(case_ins), __empty_value("")
+{
+    // set default replace bracket
+    replace_pair = std::make_pair("{", "}");
+}
+
+// destructor
+ConfigObject::~ConfigObject()
+{
+    // place holder
+}
+
+
+//============================================================================//
+// Public Member Function                                                     //
+//============================================================================//
+
+// configure the cluster method
+void ConfigObject::Configure(const std::string &path)
+{
+    // save the path
+    config_path = path;
+
+    // clear the map
+    config_map.clear();
+
+    // read configuration file in
+    ReadConfigFile(path);
+}
+
+// clear all the loaded configuration values
+void ConfigObject::ClearConfig()
+{
+    config_path = "";
+    config_map.clear();
+}
+
+// read configuration file and build the configuration map
+bool ConfigObject::ReadConfigFile(const std::string &path)
+{
+    ConfigParser c_parser;
+    c_parser.SetSplitters(split_chars); // self-defined splitters
+
+    if (c_parser.ReadFile(path)) {
+        // current directory
+        parserProcess(c_parser, path);
+        return true;
+    } else {
+        std::cerr << "Cannot open configuration file "
+                  << "\"" << path << "\""
+                  << std::endl;
+        return false;
+    }
+}
+
+// read the configuration string directly
+void ConfigObject::ReadConfigString(const std::string &content)
+{
+    ConfigParser c_parser;
+    c_parser.SetSplitters(split_chars);
+
+    c_parser.ReadBuffer(content.c_str());
+
+    parserProcess(c_parser, "buffer_string");
+}
+
+// continue parse the terms
+void ConfigObject::parserProcess(ConfigParser &c_parser, const std::string &source)
+{
+    std::string cur_dir = ConfigParser::decompose_path(source).dir;
+
+    while (c_parser.ParseLine()) {
+        // possible control words
+        if (c_parser.NbofElements() == 1) {
+            std::string control = c_parser.TakeFirst();
+            size_t pos = control.find("{THIS_DIR}");
+            if(pos != std::string::npos)
+                control.replace(pos, 10, cur_dir);
+            parseControl(control);
+        // var_name and var_value
+        } else if (c_parser.NbofElements() == 2) {
+            std::string var_name, key, var_value;
+            c_parser >> var_name >> var_value;
+            size_t pos = var_value.find("{THIS_DIR}");
+            if(pos != std::string::npos)
+                var_value.replace(pos, 10, cur_dir);
+            parseTerm(std::move(var_name), std::move(var_value));
+        // unsupported format
+        } else {
+            std::cout << "Warning: Unsupported format at line "
+                      << c_parser.LineNumber() << " from " << source << "\n"
+                      << "\"" << c_parser.CurrentLine() << "\""
+                      << std::endl;
+        }
+    }
+}
+
+// check if a certain term is configured
+bool ConfigObject::HasKey(const std::string &var_name)
+const
+{
+    auto key = formKey(var_name);
+
+    if (config_map.find(key) != config_map.end())
+        return true;
+    return false;
+}
+
+// list all the existing configuration keys
+void ConfigObject::ListKeys()
+const
+{
+    for (auto &it : config_map) {
+        std::cout << it.first << std::endl;
+    }
+}
+
+// get all the existing configuration keys
+std::vector<std::string> ConfigObject::GetKeyList()
+const
+{
+    std::vector<std::string> res;
+
+    for (auto &it : config_map) {
+        res.push_back(it.first);
+    }
+
+    return res;
+}
+
+// save current configuration into a file
+void ConfigObject::SaveConfig(const std::string &path)
+const
+{
+    std::string save_path;
+
+    if (path.empty()) 
+        save_path = config_path;
+    if(save_path.empty())
+        save_path = "latest.conf";
+
+    std::ofstream save(save_path);
+    for (auto &it : config_map) {
+        save << it.first
+             << " " << split_chars.front() << " "
+             << it.second
+             << std::endl;
+    }
+}
+
+// get configuration value by its name/key
+ConfigValue ConfigObject::GetConfigValue(const std::string &var_name)
+const
+{
+    // convert to lower case and remove uninterested characters
+    auto key = formKey(var_name);
+
+    auto it = config_map.find(key);
+    if (it == config_map.end()) {
+        return __empty_value;
+    } else {
+        ConfigValue result(it->second);
+        reform(result._value, replace_pair.first, replace_pair.second);
+        return result;
+    }
+}
+
+// set configuration value by its name/key
+void ConfigObject::SetConfigValue(const std::string &var_name, const ConfigValue &c_value)
+{
+    // convert to lower case and remove uninterested characters
+    auto key = formKey(var_name);
+
+    config_map[key] = c_value;
+}
+
+
+// get configuration value from the map
+// if no such config value exists, it will fill the default value in
+ConfigValue ConfigObject::GetConfigValue(const std::string &var_name, const ConfigValue &def_value, bool verbose)
+{
+    auto key = formKey(var_name);
+
+    auto it = config_map.find(key);
+    if (it == config_map.end()) {
+        if (def_value.IsEmpty())
+            return __empty_value;
+
+        if (verbose) {
+            std::cout << var_name << " (key: " << key << ")"
+                      << " not defined in configuration file, set to default value "
+                      << def_value
+                      << std::endl;
+        }
+        config_map[key] = def_value;
+        return def_value;
+    }
+
+    ConfigValue result(it->second);
+    reform(result._value, replace_pair.first, replace_pair.second);
+    return result;
+}
+
+
+
+//============================================================================//
+// Protected Member Function                                                  //
+//============================================================================//
+
+// build the key
+std::string ConfigObject::formKey(const std::string &rawKey)
+const
+{
+    std::string key = ConfigParser::str_remove(rawKey, ignore_chars);
+    if (case_insensitive) {
+        key = ConfigParser::str_lower(key);
+    }
+    return key;
+}
+
+// replace the contents inside replace_pair with the configuration value
+void ConfigObject::reform(std::string &input, const std::string &op, const std::string &cl)
+const
+{
+    // loop until no pair found
+    while (true) {
+        auto rpair = ConfigParser::find_pair(input, op, cl);
+        if (rpair.first != std::string::npos && rpair.second != std::string::npos) {
+            // get content inside the bracket
+            std::string var = input.substr(rpair.first + op.size(),
+                                           rpair.second - op.size() - rpair.first);
+            // deal with nested structure
+            reform(var, op, cl);
+
+            // replace content
+            std::string val;
+
+            // environment variable
+            if (rpair.first > 0 && input.at(rpair.first - 1) == '$') {
+                val = std::getenv(var.c_str());
+                // replace $ mark also
+                rpair.first--;
+            // ConfigObject variable
+            } else {
+                val = GetConfigValue(var)._value;
+            }
+
+            // replace variable with configuration value
+            input.replace(rpair.first, rpair.second - rpair.first + cl.size(), val);
+        } else {
+            // no pair found any more
+            return;
+        }
+    }
+}
+
+
+
+
+//============================================================================//
+// Private Member Function                                                    //
+//============================================================================//
+
+// parse the control word and respond
+void ConfigObject::parseControl(const std::string &word)
+{
+    if (ConfigParser::str_upper(word.substr(0, 7)) == "INCLUDE") {
+        // need the most outer pair
+        auto p = ConfigParser::find_pair(word, "(", ")");
+        // not find pair
+        if (p.first == std::string::npos || p.second == std::string::npos) {
+            std::cout << "Unsupported control word format: " << word << "."
+                      << "Expected: INCLUDE(path)"
+                      << std::endl;
+            return;
+        }
+
+        int begin = p.first + 1;
+        int length = p.second - begin;
+
+        std::string new_path = word.substr(begin, length);
+        reform(new_path, replace_pair.first, replace_pair.second);
+
+        ReadConfigFile(new_path);
+    }
+    else {
+        std::cout << "Unsupported control word: " << word << std::endl;
+    }
+}
+
+// parse the configuration term
+void ConfigObject::parseTerm(std::string &&var_name, std::string &&var_value)
+{
+    // convert to lower case and remove uninterested characters
+    auto key = formKey(var_name);
+
+    if (key.back() == '+') {
+        key.pop_back();
+        auto it = config_map.find(key);
+        if (it != config_map.end())
+            it->second += var_value;
+        else
+            config_map[key] = var_value;
+    } else {
+        config_map[key] = var_value;
+    }
+}
diff --git a/src/ConfigObject.h b/src/ConfigObject.h
new file mode 100644
index 0000000000000000000000000000000000000000..aa3bd1c82e8582cd994dca214d910b6edaf9076c
--- /dev/null
+++ b/src/ConfigObject.h
@@ -0,0 +1,89 @@
+#ifndef CONFIG_OBJECT_H
+#define CONFIG_OBJECT_H
+
+#include <string>
+#include <utility>
+#include <vector>
+#include <unordered_map>
+#include "ConfigParser.h"
+
+
+#define CONF_CONN(val, str, def, warn) val=GetConfigValue<decltype(val)>(str, def, warn)
+#define CONF_CONN2(val, def, warn) val=GetConfiValue<decltype(val)>(str, def, warn)
+#define GET_CONF(obj, val, str, def, warn) val=obj.GetConfiValue<decltype(val)>(str, def, warn)
+#define GET_CONF2(obj, val, def, warn) val=GetConfiValue<decltype(val)>(#val, def, warn)
+
+
+class ConfigObject
+{
+public:
+    // constructor, desctructor
+    ConfigObject(const std::string &spliiter = ":=", const std::string &ignore = " _\t", bool case_ins = true);
+
+    virtual ~ConfigObject();
+
+    // public member functions
+    void ClearConfig();
+    void SaveConfig(const std::string &path = "") const;
+    void ListKeys() const;
+    bool HasKey(const std::string &name) const;
+
+    bool ReadConfigFile(const std::string &path);
+    void ReadConfigString(const std::string &content);
+    void SetConfigValue(const std::string &var_name, const ConfigValue &c_value);
+    void SetIgnoreChars(const std::string &ignore) {ignore_chars = ignore;}
+    void SetSplitChars(const std::string &splitter) {split_chars = splitter;}
+    void SetReplacePair(const std::string &open, const std::string &close)
+    {
+        replace_pair = std::make_pair(open, close);
+    }
+
+    // get members
+    ConfigValue GetConfigValue(const std::string &var_name) const;
+    template<typename T>
+    T GetConfigValue(const std::string &var_name)
+    const
+    {
+        return GetConfigValue(var_name).Convert<T>();
+    }
+
+    ConfigValue GetConfigValue(const std::string &var_name, const ConfigValue &def_value, bool verbose = true);
+    template<typename T>
+    T GetConfigValue(const std::string &var_name, const T &val, bool verbose = true)
+    {
+        return GetConfigValue(var_name, ConfigValue(val), verbose).Convert<T>();
+    }
+
+    const std::string &GetConfigPath() const {return config_path;}
+    const std::string &GetSplitChars() const {return split_chars;}
+    const std::string &GetSpaceChars() const {return ignore_chars;}
+    const std::pair<std::string, std::string> &GetReplacePair() const {return replace_pair;}
+    std::vector<std::string> GetKeyList() const;
+
+
+    // functions that to be overloaded
+    virtual void Configure(const std::string &path = "");
+
+protected:
+    // protected member functions
+    void reform(std::string &input, const std::string &open, const std::string &close) const;
+    std::string formKey(const std::string &raw_key) const;
+
+private:
+    void parserProcess(ConfigParser &p, const std::string &source);
+    void parseControl(const std::string &control_word);
+    void parseTerm(std::string &&var_name, std::string &&var_value);
+
+protected:
+    std::string split_chars;
+    std::string ignore_chars;
+    bool case_insensitive;
+    std::pair<std::string, std::string> replace_pair;
+    std::string config_path;
+    std::unordered_map<std::string, std::string> config_map;
+
+    // return this reference when there is no value found in the map
+    ConfigValue __empty_value;
+};
+
+#endif
diff --git a/src/ConfigOption.cpp b/src/ConfigOption.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a9b6744d82738bf93020b6c3d1c1cc8d91a02cb8
--- /dev/null
+++ b/src/ConfigOption.cpp
@@ -0,0 +1,218 @@
+//============================================================================//
+// A class to simplify the argument parsing procedure                         //
+//                                                                            //
+// Chao Peng                                                                  //
+// 07/26/2017                                                                 //
+//============================================================================//
+
+#include "ConfigOption.h"
+#include "ConfigParser.h"
+#include <iostream>
+#include <cstring>
+
+
+
+ConfigOption::ConfigOption()
+{
+    // place holder
+}
+
+ConfigOption::~ConfigOption()
+{
+    // place holder
+}
+
+void ConfigOption::AddOpt(OptType type, char s_term)
+{
+    AddOpt(type, s_term, s_term);
+}
+
+void ConfigOption::AddLongOpt(OptType type, const char *l_term)
+{
+    AddLongOpt(type, l_term, *l_term);
+}
+
+void ConfigOption::AddOpts(OptType type, char s_term, const char *l_term)
+{
+    AddOpts(type, s_term, l_term, s_term);
+}
+
+void ConfigOption::AddOpt(OptType type, char s_term, char mark)
+{
+    if(s_opt_map.find(s_term) != s_opt_map.end()) {
+        std::cerr << "ConfigOption: Short option " << s_term
+                  << " has already been added, abort AddOpt."
+                  << std::endl;
+        return;
+    }
+
+    s_opt_map[s_term] = Opt(mark, type);
+}
+
+void ConfigOption::AddLongOpt(OptType type, const char *l_term, char mark)
+{
+    if(l_opt_map.find(l_term) != l_opt_map.end()) {
+        std::cerr << "ConfigOption: Long option " << l_term
+                  << " has already been added, abort AddOpt."
+                  << std::endl;
+        return;
+    }
+
+    l_opt_map[l_term] = Opt(mark, type);
+}
+
+void ConfigOption::AddOpts(OptType type, char s_term, const char *l_term, char mark)
+{
+    AddOpt(type, s_term, mark);
+    AddLongOpt(type, l_term, mark);
+}
+
+bool ConfigOption::parseLongOpt(const char *arg)
+{
+    auto vars = ConfigParser::split(arg, strlen(arg), "=");
+
+    std::string key = std::move(vars.front());
+    vars.pop_front();
+    auto it = l_opt_map.find(key);
+
+    if(it == l_opt_map.end()) {
+        std::cerr << "Unknown option --" << key << std::endl;
+        return false;
+    }
+
+    switch(it->second.type)
+    {
+    case arg_require:
+        if(vars.empty()) {
+            std::cerr << "Lack of argument for option --" << key << std::endl;
+            return false;
+        }
+        opt_pack.emplace_back(it->second.mark, it->second.type, std::move(vars.front()));
+        break;
+    case arg_none:
+        opt_pack.emplace_back(it->second.mark, it->second.type);
+        break;
+    case help_message:
+        return false;
+    }
+
+    return true;
+}
+
+bool ConfigOption::parseShortOpt(char key, int argc, char *argv[], int &idx)
+{
+    auto it = s_opt_map.find(key);
+    if(it == s_opt_map.end()) {
+        std::cerr << "Unknown option -" << key << std::endl;
+        return false;
+    }
+
+    switch(it->second.type)
+    {
+    case arg_require:
+        if((idx + 1) >= argc || *argv[idx + 1] == '-') {
+            std::cerr << "Lack of argument for option -" << key << std::endl;
+            return false;
+        }
+        opt_pack.emplace_back(it->second.mark, it->second.type, ConfigValue(argv[++idx]));
+        break;
+    case arg_none:
+        opt_pack.emplace_back(it->second.mark, it->second.type);
+        break;
+    case help_message:
+        return false;
+    }
+
+    return true;
+}
+
+bool ConfigOption::ParseArgs(int argc, char *argv[])
+{
+    if (argc < 1)
+        return false;
+
+    argv0 = argv[0];
+
+    bool success = true;
+    arg_pack.clear();
+    opt_pack.clear();
+
+    for(int i = 1; i < argc; ++i)
+    {
+        char* ptr = argv[i];
+        // option
+        if(*ptr == '-') {
+            // long option
+            if(*(ptr + 1) == '-') {
+                success &= parseLongOpt(ptr + 2);
+            // short option
+            } else {
+                success &= parseShortOpt(*(ptr + 1), argc, argv, i);
+            }
+        // arguments
+        } else {
+            arg_pack.emplace_back(ptr);
+        }
+    }
+
+    return success;
+}
+
+void ConfigOption::SetDesc(const char *desc)
+{
+    base_desc = desc;
+}
+
+void ConfigOption::SetDesc(char mark, const char *desc)
+{
+    std::string option;
+    bool found_mark = false;
+    for(auto &it : s_opt_map)
+    {
+        if(it.second.mark != mark) continue;
+        option = " - ";
+        option.back() = it.first;
+        if(it.second.type == arg_require)
+            option += " <arg>";
+        option += ",";
+        found_mark = true;
+    }
+
+    for(auto &it : l_opt_map)
+    {
+        if(it.second.mark != mark) continue;
+        option += " --" + it.first;
+        if(it.second.type == arg_require)
+            option += "=<arg>";
+        option += ",";
+        found_mark = true;
+    }
+
+    if(!found_mark) {
+        std::cerr << "Config Option: Cannot find any option with mark <"
+                  << mark << ">, abort adding description." << std::endl;
+        return;
+    }
+
+    option.back() = ':';
+    option += " ";
+    option += desc;
+    option_desc.emplace_back(option);
+}
+
+std::string ConfigOption::GetInstruction()
+{
+    std::string res = base_desc + "\noptions:\n";
+
+    auto pvar = res.find("%0");
+    if (pvar != std::string::npos) {
+        res.replace(pvar, 2, argv0);
+    }
+
+    for(auto &option : option_desc)
+    {
+        res += "\t" + option + "\n";
+    }
+    return res;
+}
+
diff --git a/src/ConfigOption.h b/src/ConfigOption.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ca1f7c158b6ccbc853f3226ad079dd08dc63877
--- /dev/null
+++ b/src/ConfigOption.h
@@ -0,0 +1,66 @@
+#ifndef CONFIG_OPTION_H
+#define CONFIG_OPTION_H
+
+#include "ConfigValue.h"
+#include <vector>
+#include <string>
+#include <unordered_map>
+
+class ConfigOption
+{
+public:
+    enum OptType : int
+    {
+        arg_none = 0,
+        arg_require,
+        help_message,
+    };
+
+    struct Opt
+    {
+        char mark;
+        OptType type;
+        ConfigValue var;
+
+        Opt() : mark(-1), type(arg_none) {}
+        Opt(char m, OptType t) : mark(m), type(t) {}
+        Opt(char m, OptType t, ConfigValue v) : mark(m), type(t), var(v) {}
+    };
+
+public:
+    ConfigOption();
+    virtual ~ConfigOption();
+
+    void AddOpt(OptType type, char s_term);
+    void AddOpt(OptType type, char s_term, char mark);
+    void AddLongOpt(OptType type, const char *l_term);
+    void AddLongOpt(OptType type, const char *l_term, char mark);
+    void AddOpts(OptType type, char s_term, const char *l_term);
+    void AddOpts(OptType type, char s_term, const char *l_term, char mark);
+    void SetDesc(const char *desc);
+    void SetDesc(char mark, const char *desc);
+    std::string GetInstruction();
+    bool ParseArgs(int argc, char *argv[]);
+    size_t NbofArgs() const {return arg_pack.size();}
+    size_t NbofOpts() const {return opt_pack.size();}
+    const std::string &GetArgv0() {return argv0;}
+    const ConfigValue &GetArgument(size_t i) {return arg_pack.at(i);}
+    const std::vector<ConfigValue> &GetArguments() {return arg_pack;}
+    const std::vector<Opt> &GetOptions() {return opt_pack;}
+
+private:
+    bool parseLongOpt(const char *arg);
+    bool parseShortOpt(char key, int argc, char *argv[], int &idx);
+
+private:
+    std::unordered_map<char, Opt> s_opt_map;
+    std::unordered_map<std::string, Opt> l_opt_map;
+    std::vector<Opt> opt_pack;
+    std::vector<ConfigValue> arg_pack;
+    std::string argv0;
+    std::string base_desc;
+    std::vector<std::string> option_desc;
+};
+
+
+#endif // CONFIG_OPTION_H
diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad496d48e13bfeacdfda01dd92178482dd778c69
--- /dev/null
+++ b/src/ConfigParser.cpp
@@ -0,0 +1,966 @@
+//============================================================================//
+// A simple parser class to read text file and deal with strings              //
+//                                                                            //
+// Chao Peng                                                                  //
+// 06/07/2016                                                                 //
+//============================================================================//
+
+#include "ConfigParser.h"
+#include <cstring>
+#include <climits>
+#include <algorithm>
+
+using namespace std;
+
+
+
+//============================================================================//
+// Constructors, Destructor, Assignment Operators                             //
+//============================================================================//
+
+// constructor, with format input
+ConfigParser::ConfigParser(Format f)
+: form(f), line_number(0)
+{
+    // place holder
+}
+
+// copy constructor, only copy format
+ConfigParser::ConfigParser(const ConfigParser &that)
+: form(that.form), line_number(0)
+{
+    // place holder
+}
+
+// move constructor, only move format
+ConfigParser::ConfigParser(ConfigParser &&that)
+: form(that.form), line_number(0)
+{
+    // place holder
+}
+
+// desctructor
+ConfigParser::~ConfigParser()
+{
+    CloseFile();
+}
+
+// copy assignment operator
+ConfigParser &ConfigParser::operator = (const ConfigParser &rhs)
+{
+    form = rhs.form;
+    return *this;
+}
+
+// move assignment operator
+ConfigParser &ConfigParser::operator = (ConfigParser &&rhs)
+{
+    form = rhs.form;
+    return *this;
+}
+
+//============================================================================//
+// Public Member Function                                                     //
+//============================================================================//
+
+// open a file for future parsing
+bool ConfigParser::OpenFile(const string &path, size_t cap)
+{
+    Clear();
+
+    infile.open(path);
+
+    if(!infile.is_open())
+        return false;
+
+    buf.data.resize(cap);
+
+    // success!
+    return true;
+}
+
+// read the whole file into a buffer and break it into lines
+bool ConfigParser::ReadFile(const string &path)
+{
+    Clear();
+
+    infile.open(path);
+
+    if(!infile.is_open())
+        return false;
+
+    infile.seekg(0, ios::end);
+    buf.end = infile.tellg();
+    buf.data.resize(buf.end);
+    infile.seekg(0, ios::beg);
+
+    infile.read(&buf.data[0], buf.end);
+    infile.close();
+
+    return true;
+}
+
+// close file
+void ConfigParser::CloseFile()
+{
+    return infile.close();
+}
+
+// clear stored lines
+void ConfigParser::Clear()
+{
+    buf.Reset();
+
+    // reset line
+    line_number = 0;
+    cur_line.Reset();
+
+    // close file
+    CloseFile();
+}
+
+// read a buffer in
+void ConfigParser::ReadBuffer(const char *buf_in)
+{
+    Clear();
+
+    buf.end = strlen(buf_in);
+    buf.data.resize(buf.end + 2);
+
+    strncpy(&buf.data[0], buf_in, buf.end);
+}
+
+// parse a line from the file or buffer
+// if the line is empty (all white spaces or comments), it will be skipped
+// return false if reached the end
+bool ConfigParser::ParseLine()
+{
+    elements.clear();
+
+    while(elements.empty())
+    {
+        if(!getLine(cur_line))
+            return false;
+
+        // count the line number
+        ++line_number;
+
+        parseBuffer(cur_line);
+    }
+
+    return true;
+}
+
+// parse the whole file or buffer
+// return false if nothing was found
+bool ConfigParser::ParseAll()
+{
+    elements.clear();
+
+    while(true)
+    {
+        if(!getLine(cur_line))
+            return !elements.empty();
+
+        // count the line number
+        ++line_number;
+
+        parseBuffer(cur_line);
+    }
+}
+
+// parse an input string, split the string into elements
+// the trail white spaces in the elements will be trimmed
+int ConfigParser::ParseString(const string &line)
+{
+    deque<string> eles = split(line.c_str(), line.size(), form.split);
+
+    int count = 0;
+    for(auto &ele : eles)
+    {
+        string trim_ele = trim(ele, form.white);
+        if(!trim_ele.empty()) {
+            elements.emplace_back(move(trim_ele));
+            count++;
+        }
+    }
+
+    return count;
+}
+
+// check if the current elemtns number is in the range [num, num + optional]
+// output a warning message if not
+bool ConfigParser::CheckElements(int num, int optional)
+{
+    string num_str;
+
+    if(optional > 0) {
+        if((elements.size() >= (size_t)num) &&
+           (elements.size() <= (size_t)(num + optional))) {
+            return true;
+        }
+
+        num_str = to_string(num) + " - " + to_string(num + optional);
+
+    } else if(optional == 0) {
+
+        if(elements.size() == (size_t)num) {
+            return true;
+        }
+
+        num_str = to_string(num);
+
+    } else { // optional < 0
+        if(elements.size() >= (size_t)num) {
+            return true;
+        }
+
+        num_str = " >= " + to_string(num);
+    }
+
+
+    cout << "Config Parser Warning: Wrong format at line "
+         << line_number
+         << ", expecting " << num_str << " elements. "
+         << endl
+         << "\"" << cur_line.String() << "\""
+         << endl;
+    return false;
+}
+
+
+// take the first element
+ConfigValue ConfigParser::TakeFirst()
+{
+    if(elements.empty()) {
+        cout << "Config Parser Warning: Trying to take elements while there is "
+             << "nothing, 0 value returned." << endl;
+        return ConfigValue("0");
+    }
+
+    ConfigValue output(move(elements.front()));
+    elements.pop_front();
+
+    return output;
+}
+
+
+
+//============================================================================//
+// Private Member Function                                                    //
+//============================================================================//
+
+// get buffer from the file or the input buffer
+// return false if reached input end
+bool ConfigParser::getBuffer()
+{
+    if(buf.begin < buf.end)
+        return true;
+
+    if(!infile.is_open() || infile.bad() || infile.eof())
+        return false;
+
+    infile.read(&buf.data[0], buf.data.size());
+
+    buf.begin = 0;
+    buf.end = infile.gcount();
+
+    return true;
+}
+
+// trim white spaces
+inline void trimbuf(const vector<char> &buf, size_t &begin, size_t &end, const string &w)
+{
+    while(begin < end)
+    {
+        if(w.find(buf[begin]) == string::npos)
+            break;
+
+        begin++;
+    }
+
+    while(end > begin)
+    {
+        if(w.find(buf[end - 1]) == string::npos)
+            break;
+
+        end--;
+    }
+}
+
+inline bool compare(const char ch, const string &str, size_t &c1)
+{
+    if(str.empty())
+        return false;
+
+    c1 = (ch == str[c1]) ? (c1 + 1) : 0;
+
+    return (c1 >= str.size());
+}
+
+inline bool rcompare(const ConfigParser::CharBuffer &buf, const string &str)
+{
+    if(str.empty() || buf.end <= buf.begin || buf.end - buf.begin < str.size())
+        return false;
+
+    for(size_t i = 1; i <= str.size(); ++i)
+    {
+        if(str[str.size() - i] != buf[buf.end - i])
+            return false;
+    }
+
+    return true;
+}
+
+// a helper structure to check context status
+struct TextStatus
+{
+    int val;
+    size_t cmt1, cmt2, delim;
+
+    TextStatus() : val(0), cmt1(0), cmt2(0), delim(0) {}
+    inline void Set(int i) {val = i; cmt1 = 0; cmt2 = 0;}
+};
+
+// get a line from the file or buffer
+// it deals with comments, white spaces
+// return false if reached the end
+bool ConfigParser::getLine(CharBuffer &line_buf, bool recursive)
+{
+    if(!recursive)
+        line_buf.Reset();
+    bool success = false;
+    TextStatus stat;
+
+    while(getBuffer())
+    {
+        success = true;
+
+        while(buf.begin < buf.end)
+        {
+            auto &ch = buf[buf.begin++];
+            switch(stat.val)
+            {
+            default:
+            case 0:
+                line_buf.Add(ch);
+                // check if it is the end
+                if(compare(ch, form.delim, stat.delim)) {
+                    line_buf.end -= form.delim.size();
+                    trimbuf(line_buf.data, line_buf.begin, line_buf.end, form.white);
+                    // glue lines
+                    if(rcompare(line_buf, form.glue)) {
+                        line_buf.end -= form.glue.size();
+                        return getLine(line_buf, true);
+                    } else {
+                        return success;
+                    }
+                } else if(compare(ch, form.cmtopen, stat.cmt1)) {
+                    stat.Set(1);
+                    line_buf.end -= form.cmtopen.size();
+                } else if(compare(ch, form.cmtmark, stat.cmt2)) {
+                    stat.Set(2);
+                    line_buf.end -= form.cmtmark.size();
+                }
+                break;
+            case 1:
+                if(compare(ch, form.cmtclose, stat.cmt1)) {
+                    stat.Set(0);
+                }
+                break;
+            case 2:
+                if(ch == '\n') {
+                    stat.Set(0);
+                    buf.begin -= 1;
+                }
+                break;
+            }
+        }
+    }
+
+    trimbuf(line_buf.data, line_buf.begin, line_buf.end, form.white);
+    return success;
+}
+
+// parse an input char buffer, split the string into elements
+// the trail white spaces in the elements will be trimmed
+int ConfigParser::parseBuffer(const CharBuffer &line)
+{
+    if(line.begin >= line.end)
+        return 0;
+
+    size_t ele_begin = line.begin;
+    int count = 0;
+
+    // intended to visit i == line.end, so the rest of the string get parsed
+    for(size_t i = 0; i <= line.end; ++i)
+    {
+        if(i == line.end || form.split.find(line[i]) != string::npos) {
+            size_t ele_end = i;
+            trimbuf(line.data, ele_begin, ele_end, form.white);
+            if(ele_begin < ele_end) {
+                elements.emplace_back(&line[ele_begin], ele_end - ele_begin);
+                count++;
+            }
+            ele_begin = i + 1;
+        }
+    }
+
+    return count;
+}
+
+//============================================================================//
+// Public Static Function                                                     //
+//============================================================================//
+
+// comment out a string, remove chars from the comment mark to the line break
+void ConfigParser::comment_line(string &str, const string &c, const string &b)
+{
+    // no need to continue
+    if(str.empty() || c.empty() || b.empty())
+        return;
+
+    // loop until no marks found
+    while(true)
+    {
+        size_t c_begin = str.find(c);
+        if(c_begin != string::npos) {
+            size_t c_end = str.find(b, c_begin + c.size());
+            // found, comment out until the line break
+            if(c_end != string::npos) {
+                // do not remove line break
+                str.erase(c_begin, c_end - c_begin);
+            // not found, comment out until the end
+            } else {
+                str.erase(c_begin);
+                // can stop now, since everything afterwards is removed
+                return;
+            }
+        } else {
+            // comment marks not found
+            return;
+        }
+    }
+}
+
+// comment out between a pair of comment marks
+// NOTICE: does not support nested structure of comment marks
+void ConfigParser::comment_between(string &str, const string &open, const string &close)
+{
+    // no need to continue
+    if(str.empty() || open.empty() || close.empty())
+        return;
+
+    while(true)
+    {
+        // find the openning comment mark
+        size_t pos1 = str.find(open);
+        if(pos1 != string::npos) {
+            size_t pos2 = str.find(close, pos1 + open.size());
+            // found pair
+            if(pos2 != string::npos) {
+                // remove everything between, including this pair
+                str.erase(pos1, pos2 + close.size() - pos1);
+            // comment pair not found
+            } else {
+                return;
+            }
+        } else {
+            // comment pair not found
+            return;
+        }
+    }
+}
+
+// trim all the characters defined as white space at both ends
+string ConfigParser::trim(const string &str, const string &w)
+{
+
+    const auto strBegin = str.find_first_not_of(w);
+    if (strBegin == string::npos)
+        return ""; // no content
+
+    const auto strEnd = str.find_last_not_of(w);
+
+    const auto strRange = strEnd - strBegin + 1;
+    return str.substr(strBegin, strRange);
+}
+
+// split a string into several pieces by all the characters defined as splitter
+deque<string> ConfigParser::split(const string &str, const string &s)
+{
+    deque<string> eles;
+
+    char *cstr = new char[str.length() + 1];
+
+    strcpy(cstr, str.c_str());
+
+    char *pch = strtok(cstr, s.c_str());
+
+    while(pch != nullptr)
+    {
+        eles.emplace_back(pch);
+        pch = strtok(nullptr, s.c_str());
+    }
+
+    delete[] cstr;
+
+    return eles;
+}
+
+// split a char array into several pieces
+deque<string> ConfigParser::split(const char* str, const size_t &len, const string &s)
+{
+    deque<string> eles;
+
+    char *str_cpy = new char[len + 1];
+
+    strncpy(str_cpy, str, len);
+    // end of C string
+    str_cpy[len] = '\0';
+
+    char *pch = strtok(str_cpy, s.c_str());
+
+    while(pch != nullptr)
+    {
+        eles.emplace_back(pch);
+        pch = strtok(nullptr, s.c_str());
+    }
+
+    delete[] str_cpy;
+
+    return eles;
+}
+
+// split a string and convert all parts to float numbers
+vector<int> ConfigParser::stois(const string &str, const string &s, const string &w)
+{
+    vector<int> res;
+    for(auto &val : split(str, s))
+    {
+        res.push_back(stoi(trim(val, w)));
+    }
+    return res;
+}
+
+// split a string and convert all parts to float numbers
+vector<float> ConfigParser::stofs(const string &str, const string &s, const string &w)
+{
+    vector<float> res;
+    for(auto &val : split(str, s))
+    {
+        res.push_back(stof(trim(val, w)));
+    }
+    return res;
+}
+
+// split a string and convert all parts to double numbers
+vector<double> ConfigParser::stods(const string &str, const string &s, const string &w)
+{
+    vector<double> res;
+    for(auto &val : split(str, s))
+    {
+        res.push_back(stod(trim(val, w)));
+    }
+    return res;
+}
+
+// get the split part at num
+string ConfigParser::get_split_part(int num, const char *str, const char &s)
+{
+    // unavailable
+    if(num < 0) return "";
+
+    int beg = 0, cur = 0;
+    while(str[cur] != '\0')
+    {
+        if(str[cur] == s) {
+            // number macthed
+            if(num-- == 0) {
+                return string(&str[beg], cur - beg);
+            // update segment
+            } else {
+                beg = cur + 1;
+            }
+        }
+        ++cur;
+    }
+
+    // last element
+    if(num == 0)
+        return string(&str[beg], cur - beg);
+
+    return "";
+}
+
+// check if the short string is the same with the first part of a long string
+bool cstr_cmp_helper(const char *cmp, const char *str, int size)
+{
+    for(int i = 0; i < size; ++i)
+    {
+        if(cmp[i] != str[i] || cmp[i] == '\0' || str[i] == '\0')
+            return false;
+    }
+
+    if(cmp[size] != '\0')
+        return false;
+
+    return true;
+}
+
+// split a long string and find if a short string is belong to its elements
+int ConfigParser::get_part_count(const char *cmp, const char *str, const char &s)
+{
+    int cnt = 0, beg = 0, cur = 0;
+    while(str[cur] != '\0')
+    {
+        if(str[cur] == s) {
+            if(cstr_cmp_helper(cmp, &str[beg], cur - beg)) {
+                return cnt;
+            }
+
+            ++cnt;
+            beg = cur + 1;
+        }
+        ++cur;
+    }
+
+    if(cstr_cmp_helper(cmp, &str[beg], cur-beg))
+        return cnt;
+
+    return -1;
+}
+
+// find the integer in a string
+int ConfigParser::find_integer(const string &str, const size_t &pos)
+{
+    vector<int> integers = find_integers(str);
+    if(pos >= integers.size())
+    {
+        cerr << "Config Parser: Cannot find " << pos + 1 << " integers from "
+             << "\"" << str << "\"."
+             << endl;
+        return 0;
+    }
+
+    return integers.at(pos);
+}
+
+// find all the integers in a string
+vector<int> ConfigParser::find_integers(const string &str)
+{
+    vector<int> result;
+
+    find_integer_helper(str, result);
+
+    return result;
+}
+
+// helper function for finding a integer
+void ConfigParser::find_integer_helper(const string &str, vector<int> &result)
+{
+   if(str.empty())
+       return;
+
+   int negative = 1;
+   auto numBeg = str.find_first_of("-0123456789");
+   if(numBeg == string::npos)
+       return;
+
+   // check negative sign
+   string str2 = str.substr(numBeg);
+
+   if(str2.at(0) == '-')
+   {
+       negative = -1;
+       int num_check;
+
+       do {
+           str2.erase(0, 1);
+
+           if(str2.empty())
+               return;
+
+           num_check = str2.at(0) - '0';
+       } while (num_check > 9 || num_check < 0);
+   }
+
+   auto numEnd = str2.find_first_not_of("0123456789");
+   if(numEnd == string::npos)
+       numEnd = str2.size();
+
+   int num = 0;
+   size_t i = 0;
+
+   for(; i < numEnd; ++i)
+   {
+       if( (num > INT_MAX/10) ||
+           (num == INT_MAX/10 && ((str2.at(i) - '0') > (INT_MAX - num*10))) )
+       {
+           ++i;
+           break;
+       }
+
+       num = num*10 + str2.at(i) - '0';
+   }
+
+   result.push_back(negative*num);
+   find_integer_helper(str2.substr(i), result);
+}
+
+// return the lower case of this string
+string ConfigParser::str_lower(const string &str)
+{
+    string res = str;
+    for(auto &c : res)
+    {
+        c = tolower(c);
+    }
+    return res;
+}
+
+// return the upper case of this string
+string ConfigParser::str_upper(const string &str)
+{
+    string res = str;
+    for(auto &c : res)
+    {
+        c = toupper(c);
+    }
+    return res;
+}
+
+// remove characters in ignore list
+string ConfigParser::str_remove(const string &str, const string &iignore)
+{
+    string res = str;
+
+    for(auto &c : iignore)
+    {
+        res.erase(remove(res.begin(), res.end(), c), res.end());
+    }
+    return res;
+}
+
+// replace characters in the list with certain char
+string ConfigParser::str_replace(const string &str, const string &list, const char &rc)
+{
+    if(list.empty())
+        return str;
+
+    string res = str;
+
+    for(auto &c : res)
+    {
+        if(list.find(c) != string::npos)
+            c = rc;
+    }
+
+    return res;
+}
+
+// compare two strings, can be case insensitive
+bool ConfigParser::case_ins_equal(const string &str1, const string &str2)
+{
+    if(str1.size() != str2.size()) {
+        return false;
+    }
+
+    for(auto c1 = str1.begin(), c2 = str2.begin(); c1 != str1.end(); ++c1, ++c2)
+    {
+        if(tolower(*c1) != tolower(*c2)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// find the first pair position in a string
+// it will return the most outer pair if the first pair was in a nested structure
+pair<size_t, size_t> ConfigParser::find_pair(const string &str,
+                                             const string &open,
+                                             const string &close,
+                                             size_t pos)
+{
+    pair<size_t, size_t> res(string::npos, string::npos);
+
+    if(open.empty() || close.empty() || str.size() <= pos)
+        return res;
+
+    res.first = str.find(open, pos);
+
+    // pair not found
+    if(res.first == string::npos) {
+        return res;
+    }
+
+    int open_bracket = 1;
+    size_t search_beg = res.first + open.size();
+
+    // loop for nested structure
+    while(open_bracket > 0)
+    {
+        size_t next_close = str.find(close, search_beg);
+
+        // pair not found
+        if(next_close == string::npos) {
+            // change back to npos for the not-found indication
+            res.first = string::npos;
+            return res;
+        }
+
+        // check for nested structure
+        size_t next_open = str.find(open, search_beg);
+
+        // the comparison is based on the definition of string::npos
+        // npos for not found is size_t = -1, which is the biggest size_t value
+        // find another open before close
+        if(next_open < next_close) {
+            open_bracket++;
+            search_beg = next_open + open.size();
+        // else cases
+        // 1. close mark found before open mark
+        // 2. close mark found, open mark not
+        // 3. close mark is the same as open mark, so the position is the same
+        } else {
+            open_bracket--;
+            search_beg = next_close + close.size();
+            res.second = next_close;
+        }
+    }
+
+    return res;
+}
+
+// get file name and directory from a path
+ConfigParser::PathInfo ConfigParser::decompose_path(const string &path)
+{
+    PathInfo res;
+    if(path.empty()) return res;
+
+    // find directory
+    auto dir_pos = path.find_last_of("/");
+
+    if(dir_pos != string::npos) {
+        res.dir = path.substr(0, dir_pos);
+        res.name = path.substr(dir_pos + 1);
+    } else {
+        res.name = path;
+    }
+
+    // find extension
+    auto ext_pos = res.name.find_last_of(".");
+    if(ext_pos != string::npos) {
+        res.ext = res.name.substr(ext_pos + 1);
+        res.name = res.name.substr(0, ext_pos);
+    }
+
+    return res;
+}
+
+// form the path
+string ConfigParser::compose_path(const ConfigParser::PathInfo &path)
+{
+    string res(path.dir);
+    res.reserve(path.dir.size() + path.name.size() + path.ext.size() + 2);
+
+    if(!res.empty() && res.back() != '/')
+        res += '/';
+
+    res += path.name;
+
+    if(!path.ext.empty())
+        res += "." + path.ext;
+
+    return res;
+}
+
+// form a path from given directory and file name, automatically add / if it is missing
+string ConfigParser::form_path(const string &dir, const string &file)
+{
+    string file_path;
+    file_path.reserve(dir.size() + file.size() + 1);
+
+    file_path = dir;
+    if(file_path.size() && file_path.back() != '/') file_path += "/";
+    file_path += file;
+
+    return file_path;
+}
+
+// read a file and return its content in a char string
+string ConfigParser::file_to_string(const string &path)
+{
+    ifstream inf(path);
+
+    if(!inf.is_open())
+        return "";
+
+    // read the whole file in
+    string str;
+
+    inf.seekg(0, ios::end);
+    str.reserve(inf.tellg());
+    inf.seekg(0, ios::beg);
+
+    str.assign((istreambuf_iterator<char>(inf)), istreambuf_iterator<char>());
+    inf.close();
+
+    return str;
+}
+
+// break text file into several blocks in the format
+// <label> <open_mark> <content> <close_mark>
+// return extracted <residual> {<label> <content>}
+ConfigParser::TextBlocks ConfigParser::break_into_blocks(const string &buf,
+                                                         const string &open,
+                                                         const string &close,
+                                                         const string &seps)
+{
+    TextBlocks result;
+
+    if(buf.empty() || open.empty() || close.empty())
+        return result;
+
+    size_t last_end = 0;
+    // loop until no blocks found
+    while(true)
+    {
+        // find the contents in block brackets
+        auto p = find_pair(buf, open, close, last_end);
+
+        // no pair found anymore
+        if(p.first == string::npos || p.second == string::npos)
+            break;
+
+        // add content
+        TextBlock block;
+        block.content = trim(buf.substr(p.first + open.size(), p.second - p.first - open.size()), seps);
+
+        // find label
+        string head = buf.substr(last_end, p.first - last_end);
+        if(head.empty()) {
+            block.label = "";
+        } else {
+            // find end of label
+            auto end = head.find_last_not_of(seps);
+            if(end == string::npos) end = head.size() - 1;
+            // find begin of label
+            auto beg = head.find_last_of(seps, end);
+            if(beg == string::npos) beg = 0;
+            // add label
+            block.label = trim(head.substr(beg, end - beg + 1), seps);
+            // other content goes to residual
+            result.residual += head.substr(0, beg);
+        }
+        // combine blocks
+        result.blocks.emplace_back(move(block));
+        last_end = p.second + close.size();
+    }
+
+    // trim
+    result.residual = trim(result.residual, seps);
+
+    return result;
+}
diff --git a/src/ConfigParser.h b/src/ConfigParser.h
new file mode 100644
index 0000000000000000000000000000000000000000..5e2810b4b0ea14d3f0167fa05e9089c5542eed1d
--- /dev/null
+++ b/src/ConfigParser.h
@@ -0,0 +1,235 @@
+#ifndef CONFIG_PARSER_H
+#define CONFIG_PARSER_H
+
+#include <string>
+#include <vector>
+#include <deque>
+#include <fstream>
+#include "ConfigValue.h"
+
+// a macro to auto generate enum2str and str2enum
+// name mapping begins at bias and continuously increase, split by '|'
+// an example:
+// enum ABC {a = 3, b, c};
+// ENUM_MAP(ABC, 3, "a|b|c")
+// ABC2str(3) = "a"
+// str2ABC("b") = 4
+#define ENUM_MAP(type, bias, strings) \
+    static std::string type ## 2str(int T) \
+    { \
+        return ConfigParser::get_split_part(T - (bias), strings, '|'); \
+    }; \
+    static type str2 ## type(const char *str) \
+    { \
+        return static_cast<type>(bias + ConfigParser::get_part_count(str, strings, '|')); \
+    }
+
+// config parser class
+class ConfigParser
+{
+    typedef std::pair<std::string, std::string> string_pair;
+
+public:
+    struct Format
+    {
+        std::string split;              // element splitters (chars)
+        std::string white;              // white spaces (chars)
+        std::string delim;              // line delimiter (string)
+        std::string glue;               // line glue (string)
+        std::string cmtmark;            // comment marks (string), until the line breaker '\n'
+        std::string cmtopen;            // comment-block opening mark (string)
+        std::string cmtclose;           // comment-block closing mark (string)
+
+        static Format Basic() {return {" \t,", " \t", "\n", "", "", "", ""};}
+        static Format BashLike() {return {" \t,", " \t", "\n", "\\", "#", "\'", "\'"};}
+        static Format CLike() {return {" \t,\n", " \t\n", ";", "", "//", "/*", "*/"};}
+    };
+
+    struct CharBuffer
+    {
+        std::vector<char> data;
+        size_t begin, end;
+
+        CharBuffer(size_t cap = 256) : begin(0), end(0)
+        {
+            data.resize(cap);
+        }
+
+        void Reset() {begin = 0; end = 0; data.clear();}
+        void Add(char ch)
+        {
+            if(data.size() <= end)
+                data.resize(2*data.size());
+
+            data[end++] = ch;
+        }
+
+        std::string String()
+        const
+        {
+            std::string str;
+            if(end > begin)
+                str.assign(&data[begin], end - begin);
+            return str;
+        }
+
+        inline const char &operator [] (size_t idx) const {return data[idx];}
+        inline char &operator [] (size_t idx) {return data[idx];}
+    };
+
+public:
+    ConfigParser(Format f = Format::BashLike());
+
+    ConfigParser(ConfigParser &&that);
+    ConfigParser(const ConfigParser &that);
+
+    virtual ~ConfigParser();
+
+    ConfigParser &operator = (ConfigParser &&rhs);
+    ConfigParser &operator = (const ConfigParser &rhs);
+
+    // format related
+    inline void SetFormat(Format &&f) {form = f;}
+    inline void SetFormat(const Format &f) {form = f;}
+    inline void SetSplitters(std::string s) {form.split = s;}
+    inline void SetWhiteSpaces(std::string w) {form.white = w;}
+    inline void SetCommentMark(std::string c) {form.cmtmark = c;}
+    inline void SetCommentPair(std::string o, std::string c) {form.cmtopen = o; form.cmtclose = c;}
+    inline void SetLineGlues(std::string g) {form.glue = g;}
+    inline void SetLineBreaks(std::string b) {form.delim = b;}
+
+    const Format &GetFormat() const {return form;}
+
+    // dealing with file/buffer
+    bool OpenFile(const std::string &path, size_t cap = 64*1024);
+    bool ReadFile(const std::string &path);
+    void ReadBuffer(const char*);
+    void CloseFile();
+    void Clear();
+
+    // parse line, return false if no more line to parse
+    bool ParseLine();
+    // parse the whole file or buffer, return false if no elements found
+    bool ParseAll();
+    // parse a string, trim and split it into elements
+    int ParseString(const std::string &line);
+
+    // get current parsing status
+    bool CheckElements(int num, int optional = 0);
+    int NbofElements() const {return elements.size();}
+    int LineNumber() const {return line_number;}
+    std::string CurrentLine() const {return cur_line.String();}
+
+    // take the elements
+    ConfigValue TakeFirst();
+
+    template<typename T>
+    T TakeFirst()
+    {
+        return TakeFirst().Convert<T>();
+    }
+
+    template<typename T>
+    ConfigParser &operator >>(T &t)
+    {
+        t = (*this).TakeFirst().Convert<T>();
+        return *this;
+    }
+
+    template<class BidirIt>
+    int Take(BidirIt first, BidirIt last)
+    {
+        int count = 0;
+        for(auto it = first; it != last; ++it, ++count)
+        {
+            if(elements.empty())
+                break;
+
+            *it = elements.front();
+            elements.pop_front();
+        }
+        return count;
+    }
+
+    template<template<class, class> class Container>
+    Container<ConfigValue, std::allocator<ConfigValue>> TakeAll()
+    {
+        Container<ConfigValue, std::allocator<ConfigValue>> res;
+        while(elements.size())
+        {
+            res.emplace_back(std::move(elements.front()));
+            elements.pop_front();
+        }
+        return res;
+    }
+
+    template<template<class, class> class Container, class T>
+    Container<T, std::allocator<T>> TakeAll()
+    {
+        Container<T, std::allocator<T>> res;
+        while(elements.size())
+        {
+            ConfigValue tmp(std::move(elements.front()));
+            elements.pop_front();
+            res.emplace_back(tmp.Convert<T>());
+        }
+        return res;
+    }
+
+
+private:
+    // private functions
+    bool getBuffer();
+    bool getLine(CharBuffer &line_buf, bool recursive = false);
+    int parseBuffer(const CharBuffer &line);
+
+private:
+    // private members
+    Format form;
+    std::ifstream infile;
+    CharBuffer buf, cur_line;
+    int line_number;
+    std::deque<std::string> elements;
+
+public:
+    // static functions
+    static void comment_line(std::string &str, const std::string &cmt, const std::string &brk);
+    static void comment_between(std::string &str, const std::string &open, const std::string &close);
+    static std::string trim(const std::string &str, const std::string &w);
+    static std::deque<std::string> split(const std::string &str, const std::string &s);
+    static std::deque<std::string> split(const char* str, const size_t &len, const std::string &s);
+    static std::string get_split_part(int num, const char *str, const char &s);
+    static int get_part_count(const char *cmp, const char *str, const char &s);
+    static std::vector<int> stois(const std::string &str, const std::string &s, const std::string &w);
+    static std::vector<float> stofs(const std::string &str, const std::string &s, const std::string &w);
+    static std::vector<double> stods(const std::string &str, const std::string &s, const std::string &w);
+    static std::string str_remove(const std::string &str, const std::string &ignore);
+    static std::string str_replace(const std::string &str, const std::string &ignore, const char &rc = ' ');
+    static std::string str_lower(const std::string &str);
+    static std::string str_upper(const std::string &str);
+    static std::pair<size_t, size_t> find_pair(const std::string &str,
+                                               const std::string &open,
+                                               const std::string &close,
+                                               size_t pos = 0);
+    static bool case_ins_equal(const std::string &str1, const std::string &str2);
+    static int find_integer(const std::string &str, const size_t &pos = 0);
+    static std::vector<int> find_integers(const std::string &str);
+    static void find_integer_helper(const std::string &str, std::vector<int> &result);
+    struct PathInfo { std::string dir, name, ext; };
+    static PathInfo decompose_path(const std::string &path);
+    static std::string compose_path(const PathInfo &path);
+    static std::string form_path(const std::string &dir, const std::string &file);
+    static std::string file_to_string(const std::string &path);
+    // break text file into several blocks in the format
+    // <label> <open_mark> <content> <close_mark>, this structure can be separated by sep characters
+    // return extracted <residual> {<label> <content>} with white characters trimmed
+    struct TextBlock {std::string label, content;};
+    struct TextBlocks {std::string residual; std::vector<TextBlock> blocks;};
+    static TextBlocks break_into_blocks(const std::string &buf,
+                                        const std::string &open = "{",
+                                        const std::string &close = "}",
+                                        const std::string &seps = " \t\n");
+
+};
+
+#endif
diff --git a/src/ConfigValue.cpp b/src/ConfigValue.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..96bd4b2ead9db0fe957b8cb11cb1c260f4e75fae
--- /dev/null
+++ b/src/ConfigValue.cpp
@@ -0,0 +1,317 @@
+//============================================================================//
+// A string wrapper class that convert string to other data types             //
+//                                                                            //
+// Chao Peng                                                                  //
+// 06/07/2016                                                                 //
+//============================================================================//
+
+#include "ConfigValue.h"
+#include "ConfigParser.h"
+#include <climits>
+#include <algorithm>
+
+using namespace std;
+
+
+
+//============================================================================//
+// Constructors, Destructor and Assignment Operators                          //
+//============================================================================//
+
+ConfigValue::ConfigValue(const string &value)
+: _value(value)
+{}
+
+ConfigValue::ConfigValue(string &&value)
+: _value(move(value))
+{}
+
+ConfigValue::ConfigValue(const char *value)
+: _value(value)
+{}
+
+ConfigValue::ConfigValue(const bool &value)
+{
+    if(value)
+        _value = "1";
+    else
+        _value = "0";
+}
+
+ConfigValue::ConfigValue(const int &value)
+: _value(to_string(value))
+{}
+
+ConfigValue::ConfigValue(const long &value)
+: _value(to_string(value))
+{}
+
+ConfigValue::ConfigValue(const long long &value)
+: _value(to_string(value))
+{}
+
+ConfigValue::ConfigValue(const unsigned &value)
+: _value(to_string(value))
+{}
+
+ConfigValue::ConfigValue(const unsigned long &value)
+: _value(to_string(value))
+{}
+
+ConfigValue::ConfigValue(const unsigned long long &value)
+: _value(to_string(value))
+{}
+
+ConfigValue::ConfigValue(const float &value)
+: _value(to_string(value))
+{}
+
+ConfigValue::ConfigValue(const double &value)
+: _value(to_string(value))
+{}
+
+ConfigValue::ConfigValue(const long double &value)
+: _value(to_string(value))
+{}
+
+ConfigValue &ConfigValue::operator =(const string &str)
+{
+    (*this)._value = str;
+    return *this;
+}
+
+ConfigValue &ConfigValue::operator =(string &&str)
+{
+    (*this)._value = move(str);
+    return *this;
+}
+
+
+//============================================================================//
+// Public Member functions                                                    //
+//============================================================================//
+
+bool ConfigValue::Bool()
+const
+{
+    if((_value == "1") ||
+       (ConfigParser::case_ins_equal(_value, "T")) ||
+       (ConfigParser::case_ins_equal(_value, "True")) ||
+       (ConfigParser::case_ins_equal(_value, "Y")) ||
+       (ConfigParser::case_ins_equal(_value, "Yes")))
+        return true;
+
+    if((_value == "0") ||
+       (ConfigParser::case_ins_equal(_value, "F")) ||
+       (ConfigParser::case_ins_equal(_value, "False")) ||
+       (ConfigParser::case_ins_equal(_value, "N")) ||
+       (ConfigParser::case_ins_equal(_value, "No")))
+        return false;
+
+    cout << "Config Value: Failed to convert "
+         << _value << " to bool type. Return false."
+         << endl;
+    return false;
+}
+
+char ConfigValue::Char()
+const
+{
+    try {
+       int value = stoi(_value);
+       if(value > CHAR_MAX)
+           cout << "Config Value: Limit exceeded while converting "
+                << _value << " to char." << endl;
+       return (char) value;
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to char. 0 returned." << endl;
+             return 0;
+    }
+}
+
+unsigned char ConfigValue::UChar()
+const
+{
+    try {
+       unsigned long value = stoul(_value);
+       if(value > UCHAR_MAX)
+           cout << "Config Value: Limit exceeded while converting "
+                << _value << " to unsigned char." << endl;
+       return (unsigned char) value;
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to unsigned char. 0 returned." << endl;
+             return 0;
+    }
+}
+
+short ConfigValue::Short()
+const
+{
+    try {
+       int value = stoi(_value);
+       if(value > SHRT_MAX)
+           cout << "Config Value: Limit exceeded while converting "
+                << _value << " to short." << endl;
+       return (short) value;
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to short. 0 returned." << endl;
+             return 0;
+    }
+}
+
+unsigned short ConfigValue::UShort()
+const
+{
+    try {
+       unsigned long value = stoul(_value);
+       if(value > USHRT_MAX)
+           cout << "Config Value: Limit exceeded while converting "
+                << _value << " to unsigned short." << endl;
+       return (unsigned short) value;
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to unsigned short. 0 returned." << endl;
+             return 0;
+    }
+}
+
+int ConfigValue::Int()
+const
+{
+    try {
+       return stoi(_value);
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to int. 0 returned." << endl;
+             return 0;
+    }
+}
+
+unsigned int ConfigValue::UInt()
+const
+{
+    try {
+        return (unsigned int)stoul(_value);
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to unsigned int. 0 returned." << endl;
+             return 0;
+    }
+}
+
+long ConfigValue::Long()
+const
+{
+    try {
+        return stol(_value);
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to long. 0 returned." << endl;
+             return 0;
+    }
+}
+
+long long ConfigValue::LongLong()
+const
+{
+    try {
+        return stoll(_value);
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to long long. 0 returned." << endl;
+             return 0;
+    }
+}
+
+unsigned long ConfigValue::ULong()
+const
+{
+    try {
+        return stoul(_value);
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to unsigned long. 0 returned." << endl;
+             return 0;
+    }
+}
+
+unsigned long long ConfigValue::ULongLong()
+const
+{
+    try {
+        return stoull(_value);
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to unsigned long long. 0 returned." << endl;
+             return 0;
+    }
+}
+
+float ConfigValue::Float()
+const
+{
+    try {
+        return stof(_value);
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to float. 0 returned." << endl;
+             return 0;
+    }
+}
+
+double ConfigValue::Double()
+const
+{
+    try {
+        return stod(_value);
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to double. 0 returned." << endl;
+             return 0;
+    }
+}
+
+long double ConfigValue::LongDouble()
+const
+{
+    try {
+        return stold(_value);
+    } catch (exception &e) {
+        cerr << e.what() << endl;
+        cerr << "Config Value: Failed to convert "
+             << _value << " to long double. 0 returned." << endl;
+             return 0;
+    }
+}
+
+const char *ConfigValue::c_str()
+const
+{
+    return _value.c_str();
+}
+
+
+
+//============================================================================//
+// Other functions                                                            //
+//============================================================================//
+
+ostream &operator << (ostream &os, const ConfigValue &b)
+{
+    return  os << b.c_str();
+}
diff --git a/src/ConfigValue.h b/src/ConfigValue.h
new file mode 100644
index 0000000000000000000000000000000000000000..aaf3a36103cf96af200f2b68f1f330278a8ae46a
--- /dev/null
+++ b/src/ConfigValue.h
@@ -0,0 +1,138 @@
+#ifndef CONFIG_VALUE_H
+#define CONFIG_VALUE_H
+
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <utility>
+#include <typeinfo>
+
+// demangle type name
+#ifdef __GNUG__
+#include <cstdlib>
+#include <memory>
+#include <cxxabi.h>
+// gnu compiler needs to demangle type info
+static inline std::string demangle(const char* name)
+{
+
+    int status = 0;
+
+    //enable c++11 by passing the flag -std=c++11 to g++
+    std::unique_ptr<char, void(*)(void*)> res {
+        abi::__cxa_demangle(name, NULL, NULL, &status),
+        std::free
+    };
+
+    return (status==0) ? res.get() : name ;
+}
+#else
+// do nothing if not gnu compiler
+static inline std::string demangle(const char* name)
+{
+    return name;
+}
+#endif
+
+// this helps template specialization in class
+template <typename T>
+struct __cv_id { typedef T type; };
+
+class ConfigValue
+{
+public:
+    friend class ConfigParser;
+    friend class ConfigObject;
+
+public:
+    ConfigValue() {}
+
+    ConfigValue(const std::string &value);
+    ConfigValue(std::string &&value);
+    ConfigValue(const int &value);
+    ConfigValue(const double &value);
+    explicit ConfigValue(const char *value);
+    explicit ConfigValue(const bool &value);
+    explicit ConfigValue(const long &value);
+    explicit ConfigValue(const long long &value);
+    explicit ConfigValue(const unsigned &value);
+    explicit ConfigValue(const unsigned long &value);
+    explicit ConfigValue(const unsigned long long &value);
+    explicit ConfigValue(const float &value);
+    explicit ConfigValue(const long double &value);
+
+    ConfigValue &operator =(const std::string &str);
+    ConfigValue &operator =(std::string &&str);
+
+    bool Bool() const;
+    char Char() const;
+    unsigned char UChar() const;
+    short Short() const;
+    unsigned short UShort() const;
+    int Int() const;
+    unsigned int UInt() const;
+    long Long() const;
+    long long LongLong() const;
+    unsigned long ULong() const;
+    unsigned long long ULongLong() const;
+    float Float() const;
+    double Double() const;
+    long double LongDouble() const;
+    const char *c_str() const;
+    const std::string &String() const {return _value;}
+    bool IsEmpty() const {return _value.empty();}
+
+    operator std::string()
+    const
+    {
+        return _value;
+    }
+
+    bool operator ==(const std::string &rhs)
+    const
+    {
+        return _value == rhs;
+    }
+
+    template<typename T>
+    T Convert()
+    const
+    {
+        return convert( __cv_id<T>());
+    }
+
+private:
+    std::string _value;
+
+    template<typename T>
+    T convert(__cv_id<T> &&)
+    const
+    {
+        std::stringstream iss(_value);
+        T _cvalue;
+
+        if(!(iss >> _cvalue)) {
+            std::cerr << "Config Value Warning: Undefined value returned, failed to convert "
+                      <<  _value
+                      << " to "
+                      << demangle(typeid(T).name())
+                      << std::endl;
+        }
+
+        return _cvalue;
+    }
+
+    ConfigValue convert(__cv_id<ConfigValue>) const {return *this;}
+    bool convert(__cv_id<bool> &&) const {return (*this).Bool();}
+    float convert(__cv_id<float> &&) const {return (*this).Float();}
+    double convert(__cv_id<double> &&) const {return (*this).Double();}
+    long double convert(__cv_id<long double> &&) const {return (*this).LongDouble();}
+    std::string convert(__cv_id<std::string> &&) const {return (*this)._value;}
+    const char* convert(__cv_id<const char*> &&) const {return (*this)._value.c_str();}
+
+};
+
+// show string content of the config value to ostream
+std::ostream &operator << (std::ostream &os, const ConfigValue &b);
+
+#endif