Boost:PropertyTree:Example
Boost:PropertyTree를 사용하는 샘플 코드.
/**
* @file Property.hpp
* @brief Property class prototype.
* @author username
* @date 2015-04-03
* @date 2015-06-13 (Create Xml, Ini, Json Property)
* @date 2015-08-22 (Move the world library)
*/
#ifndef __INCLUDE_WORLD__WORLD_PROPERTY_PROPERTY_HPP__
#define __INCLUDE_WORLD__WORLD_PROPERTY_PROPERTY_HPP__
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <string>
#if defined(__GNUC__) && defined(__cplusplus)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Winline"
#endif
#include <boost/property_tree/ptree.hpp>
#if defined(__GNUC__) && defined(__cplusplus)
# pragma GCC diagnostic pop
#endif
#include <boost/filesystem.hpp>
/**
* Create a property accessor & mutator macro.
*/
#define CREATE_PROPERTY(type, section, name, default_value, ptree) \
public: \
type get_##section##_##name() const \
{ \
return ptree.get<type>(#section "." #name, default_value); \
} \
public: \
void put_##section##_##name(type const & value = default_value) \
{ \
ptree.put(#section "." #name, value); \
}
#define CREATE_PROPERTY2(type, section, name, default_value) \
CREATE_PROPERTY(type, section, name, default_value, _ptree)
// --------------
namespace world {
// --------------
/**
* Basic property class.
*
* @author username
* @date 2015-04-03
* @date 2015-08-22 (Move the world library)
*/
class Property : public Noncopyable
{
protected:
std::string _path;
boost::property_tree::ptree _ptree;
public:
Property() = default;
virtual ~Property() = default;
Property(std::string const & path) : _path(path) {
// EMPTY.
}
public:
Property(std::string const & path);
public:
/** if not exist put the default and save. */
void loadOrDefaultSave() {
if (exists()) {
load();
} else {
putDefault();
save();
}
}
public:
inline void setPath(std::string const & path)
{ this->_path = path; }
inline std::string getPath() const
{ return this->_path; }
boost::property_tree::ptree & getPtree()
{ return this->_ptree; }
// File system.
public:
/** Check the property file exists. */
bool exists() const {
return boost::filesystem::exists(boost::filesystem::path(_path));
}
/** Remove property file. */
bool remove() const {
return boost::filesystem::remove(boost::filesystem::path(_path));
}
public:
virtual void putDefault() {
// EMPTY.
}
// save & load.
public:
virtual bool load() = 0;
virtual bool save() = 0;
};
// -----------------
} // namespace world
// -----------------
#if defined(WORLD_COMP_GNUC) && defined(WORLD_LANG_STDCPP)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Winline"
# pragma GCC diagnostic ignored "-Wreturn-type"
# if !defined(WORLD_COMP_LLVM)
# pragma GCC diagnostic ignored "-Wunused-local-typedefs"
# endif
#endif
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/json_parser.hpp>
#if defined(WORLD_COMP_GNUC) && defined(WORLD_LANG_STDCPP)
# pragma GCC diagnostic pop
#endif
#define __PROPERTY_CLASS(classname, parsername, reader, writer, error) \
class classname : public Property \
{ \
public: \
classname() : Property() { } \
classname(std::string const & path) : Property(path) { } \
virtual ~classname() { } \
public: \
bool load() override \
{ \
try { \
boost::property_tree::parsername::reader(_path, _ptree); \
} catch (boost::property_tree::error & e) { \
return false; \
} \
return true; \
} \
public: \
bool save() override \
{ \
try { \
boost::property_tree::parsername::writer(_path, _ptree); \
} catch (boost::property_tree::error & e) { \
return false; \
} \
return true; \
} \
};
#define __PROPERTY_CLASS2(type) \
__PROPERTY_CLASS(type##Property, type##_parser, read_##type, write_##type, type##_parser_error)
// --------------
namespace world {
// --------------
__PROPERTY_CLASS2(ini);
__PROPERTY_CLASS2(xml);
__PROPERTY_CLASS2(json);
/**
* @defgroup __DOXYGEN_GROUP__PROPERTY_LIST__ Property list
* @brief List of Property class.
* @{
*/
using IniProperty = iniProperty;
using XmlProperty = xmlProperty;
using JsonProperty = jsonProperty;
/**
* @}
*/
// -----------------
} // namespace world
// -----------------
#endif // __INCLUDE_WORLD__WORLD_PROPERTY_PROPERTY_HPP__
사용 방법은 아래와 같다.
using namespace world;
static char const * TEST_INI_FILE_PATH = "world.test.ini";
static char const * DEFAULT_TEST_STRING = "DEFAULT_STRING";
static int const DEFAULT_TEST_INTEGER = 60;
class PropertyTest : public IniProperty
{
private:
std::string TEST_STRING;
public:
PropertyTest() : IniProperty(TEST_INI_FILE_PATH)
{
TEST_STRING = "TestString";
}
virtual ~PropertyTest()
{
__EMPTY_BLOCK__
}
public:
virtual void putDefault() override
{
put_test_string();
put_test_integer();
}
public:
CREATE_PROPERTY2(std::string, test, string, DEFAULT_TEST_STRING);
CREATE_PROPERTY2(int, test, integer, DEFAULT_TEST_INTEGER);
};
int main()
{
if (this->exists() == true) {
this->remove();
}
assert(this->exists() == false);
assert(this->load() == false);
this->loadOrDefaultSave();
assert(this->get_test_string() == std::string(DEFAULT_TEST_STRING));
assert(this->get_test_integer() == std::string(DEFAULT_TEST_INTEGER));
assert(this->exists());
assert(this->remove());
return 0;
}