Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Boost property tree seems like an excellent library to use for parsing config files. However, I can't figure out how to handle situations where there are multiple values per key. For example, let's say I was specifying a box like this:

box
{
    x -1 1
    y -1 1
    z -1 1
}

where x, y, and z are the bounds of the box on the x, y, and z axes respectively, specified using property_tree's INFO format. I see mention in the manual of using quotes for values that use spaces, but then I don't see that I could import those values as numbers. I'd have to parse the string into numbers, which seems to defeat the purpose of using property_tree in the first place. I could certainly give each number a key:

box 
{
    xlo -1
    xhi 1
    ylo -1
    yhi 1
    zlo -1
    zhi 1
}    

but that seems cumbersome, and will inflate my config file. I also noted that I could handle this situation in program_options, but I lose the nested config file capabilities (yeah, I know I can use dot notation to "nest", but it's not the same).

Is there a way to import e.g. x as a list of numbers like this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
364 views
Welcome To Ask or Share your Answers For Others

1 Answer

The standard property_tree handles only one string value per key since it is defined as:

typedef basic_ptree<std::string, std::string> ptree;

So, the only option is to use strings and parse them. I think the best method is to define a new class that stores the low and high values and then create a translator class for the get and set methods. For example:

struct low_high_value
{
  low_high_value() : m_low(0), m_high(0) { }
  low_high_value(double low, double high) : m_low(low), m_high(high) { }
  double m_low;
  double m_high;
};

The translator would be:

struct low_high_value_translator
{
  typedef std::string    internal_type;
  typedef low_high_value external_type;
  // Get a low_high_value from a string
  boost::optional<external_type> get_value(const internal_type& str)
  {
    if (!str.empty())
    {
      low_high_value val;
      std::stringstream s(str);
      s >> val.m_high >> val.m_low;
      return boost::optional<external_type>(val);
    }
    else
      return boost::optional<external_type>(boost::none);
  }

  // Create a string from a low_high_value
  boost::optional<internal_type> put_value(const external_type& b)
  {
    std::stringstream ss;
    ss << b.m_low << " " << b.m_high;
    return boost::optional<internal_type>(ss.str());
  }
};

The previous get_value method is very simple. It should be improved if the file could be written by the user.

This class should be registered using:

namespace boost { namespace property_tree 
{
  template<typename Ch, typename Traits, typename Alloc> 
  struct translator_between<std::basic_string< Ch, Traits, Alloc >, low_high_value>
  {
    typedef low_high_value_translator type;
  };
} }

After you include the previous code, you can use property_tree as:

  pt.get<low_high_value>("box.x")
  pt.put("box.u", low_high_value(-110, 200));

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...