0

Alright, so I've encounted a problem that my limited programming skills simply cannot solve, at least in an elegant fashion. I want to store the data from Valve KeyValues files, but I can't think of a good way of going about it. I'll illustrate the basic structure of the file format in this block of code.

"Key"
{
    "Key"
    {
        "Key" "Value"
        "Key" "Value"
    }
    "Key"
    {
        "Key" "Value"
        "Key" "Value"
    }
    "Key" "Value"
    "Key" "Value"
}

Each value can be one of a few types. Each key has to have a value with a certain type assigned to it. Wherever the key itself is located by change the type, but I doubt this. I can actually tokenize the file already, by keys, values, and brackets, so I don't need any help with that unless it's necessary. I'd like to create a system that isn't quick and dirty and relies on heavy amounts of repetitive code. If any of you have any questions, feel free to ask.

Freddy Pierson
  • 433
  • 2
  • 10
  • Take an existing solution, like Protocol Buffers, or CORBA, or XML+SOAP. Or JSON maybe. – Kerrek SB Jul 06 '13 at 22:45
  • I'll take your advice on finding an existing solution. Perhaps I could use a library to help me out, such as Boost, I'm thinking the tree container, if it has anything I'm looking for. While looking through the Valve source code, I also found that the KeyValue storer does not convert the value strings into types. Instead, individual functions take the value and turn the value into whatever type it needs. That's something to think about. I might take a walk and do some deep thinking. Until then, more help would be appreciated. – Freddy Pierson Jul 06 '13 at 22:59
  • One more thing to think about. Some keys are labelled "id", followed by an integer. Since anything with an id attached to it, is in high quantity, i could use that id to help me map my data. – Freddy Pierson Jul 06 '13 at 23:04

2 Answers2

0

A straightforward solution would be to use an std::map<std::string, boost::any> container. You'd need to use boost::any for this. Another solution is to store the key-value pairs as straightforward string in the sense of an std::map<std::string, std::string> and then use boost::lexical_cast to convert.

rwols
  • 2,968
  • 2
  • 19
  • 26
  • I was thinking about using boost::any myself. If I could use a map to store my data in, that leaves me with only one problem, if I want my values to be converted into their intended type. That could be easy to do, now that I think of it. I'd rate your answer up if I could. – Freddy Pierson Jul 06 '13 at 23:08
  • Well, you could also use boost::variant, see [this question](http://stackoverflow.com/questions/8344080/boost-variant-how-to-get-currently-held-type) on stackoverflow. – rwols Jul 06 '13 at 23:12
0

Here is a solution which I think can be applied to this problem:

I'm assuming that you may be given many blocks like this-

"Key"

{

...

}

"Key"

{

...

}

Now, construct a forest with trees rooted at the initial "Key" of a block. The children of the key will be the keys which are in sub-block and so-on. The leaves would contain the "Values".

The trees will be n-ary, not binary. The "Keys" in a level could be stored in a sorted order from left to right which would enhance the retrieval time of the value corresponding the key queried.

Such a storage would be one of the most elegant way that I could think of. Further thoughts and suggestions appreciated.

Community
  • 1
  • 1
Sankalp
  • 2,796
  • 3
  • 30
  • 43