Konfigurationsfiler med Boost.

23Jul11

Det enklaste sättet att hantera konfigurationsfiler är att helt enkelt ta en textfil med de inställningarna man vill ha och sedan läsa in rad för rad i från textfilen. Denna metoden kan fort bli svår för slutanvändaren att hantera och blir lätt kryptisk och vad händer om någon råkar tex skriva höjden på den raden man för väntar sig ha bredden?

En enklare lösning är att använda sig av Boost PropertyTree, lösningen är enkel och stödjer xml, ini, json och boost eget info format. Alla filformaten med undantag .ini klarar av nästlade element (men vad kan man begära av något som härstammar från Windows 95?). För att demonstrera den praktiska användningen ska vi skapa en konfiguration för ett grafiskt program, tex ett spel.

Huvudprogrammet:

#include <string>
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

class settings {
public:
  void read(const std::string &filename);
  void save(const std::string &filename);

  void print();

private:
  std::string m_appName;
  int m_screenWidth;
  int m_screenHeight;
  int m_depth;
  bool m_fullscreen;
  int m_soundVolume;
};

void settings::read(const std::string &filename){
  boost::property_tree::ptree pt;
  boost::property_tree::read_xml(filename, pt);
  m_appName = pt.get<std::string>("settings.app_name");
  m_screenWidth = pt.get<int>("settings.screen_width");
  m_screenHeight = pt.get<int>("settings.screen_height");
  m_depth = pt.get<int>("settings.colordepth");
  if(pt.get<std::string>("settings.fullscreen")=="true"){
    m_fullscreen = true;
  }else{
    m_fullscreen = false;
  }
  m_soundVolume = pt.get<int>("settings.sound_volume");
}

void settings::save(const std::string &filename){
  boost::property_tree::ptree pt;

  pt.put("settings.app_name", m_appName);
  pt.put("settings.screen_width", m_screenWidth);
  pt.put("settings.screen_height", m_screenHeight);
  pt.put("settings.screen_colorDepth", m_depth);
  if(m_fullscreen){
    pt.put("settings.fullscreen", "true");
  }else{
    pt.put("settings.fullscreen", "false");
  }
  pt.put("settings.sound_volume", m_soundVolume);

  boost::property_tree::write_xml(filename, pt);
}

void settings::print(){
  std::cout << "Name: " << m_appName << std::endl;
  std::cout << "Res: " << m_screenWidth << "x" << m_screenHeight << "@" << m_depth << "bit" << std::endl;
  if(m_fullscreen){
    std::cout << "Fullscreen mode." << std::endl;
  }else{
    std::cout << "Windowed mode." << std::endl;
  }
  std::cout << "Sound volume: " << m_soundVolume << std::endl;
}

int main(){
  settings s;
  s.read("./settings.xml");
  s.print();
  s.save("./tmp_settings.xml");
  return 0;
}

cmake: För att använda boost property_tree behöver vi inte lägga till mer än boost i vår cmake.

cmake_minimum_required (VERSION 2.8)
project(demo)

find_package(Boost 1.4.2)

include_directories(${Boost_INCLUDE_DIR})

set(CORELIBS ${Boost_LIBRARIES})

add_executable(demo ${CORELIBS} main.cpp)
target_link_libraries(demo ${CORELIBS})

xml-filen – Storlek: 287 byte.

<?xml version="1.0" encoding="utf-8"?>
<settings>
  <app_name>Ett coolt demo av Fredrik Persson</app_name>
  <screen_width>800</screen_width>
  <screen_height>600</screen_height>
  <colordepth>32</colordepth>
  <fullscreen>true</fullscreen>
  <sound_volume>80</sound_volume>
</settings>

Ändringar för andra filformat än xml:

För att använda ini, json eller info i stället för xml behöver vi bara göra små justeringar i programmet.

På rad 4 byter vi ut boost/property_tree/xml_parser.hpp mot någon av följade headerfiler:

boost/property_tree/ini_parser.hpp
boost/property_tree/json_parser.hpp
boost/property_tree/info_parser.hpp

Där efter är det bara att ändra xml_read på rad 24  mot tex ini_read eller vad man nu vill ha gör sedan samma sak för xml_write på rad 51. En sista ändring krävs i main funktionen, där vi ändrar .xml till passande fil ändelse.

ini-filen – Storlek: 136 byte.

[settings]
app_name=Ett coolt demo av Fredrik Persson
screen_width=800
screen_height=600
colordepth=32
fullscreen=true
sound_volume=80

json-filen – Storlek: 194 byte.

{
  "settings":
  {
    "app_name":"Ett coolt demo av Fredrik Persson",
    "screen_width":800,
    "screen_height":600,
    "colordepth":32,
    "fullscreen":true,
    "sound_volume":80
  }
}

info-filen – Storlek 170 byte

settings
{
    app_name "Ett coolt demo av Fredrik Persson"
    screen_width 800
    screen_height 600
    screen_colordepth 32
    fullscreen true
    sound_volume 80
}

Vad är för och nackdelarna med de olika filformaten?

Jag är ingen expert och har inte lusläst boost källkod. Fördelarna med XML är strukturen och att det är välanvänt över allt, på minussidan finns filstorleken och att det lär vara krävande att evaluera filen. Det är dock inget som märks i ett så lite data mängd. ini-filer är gamla och beprövade med ett rent och lättläst innehåll. Json är populärt på weben då det är JavaScipt och lär vara snabbare att evaluera än XML. Boost egna info format är inte så välspritt, det påminner lite om json.

//Fredrik



No Responses Yet to “Konfigurationsfiler med Boost.”

  1. Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: