How to get JsonCPP values as strings? - c++

I am parsing json data using JsonCpp. I don't really need to understand the data, i just need to print out some properties and their values out. It somehow is hard to do. First I need to know what type the value is and then get the value and then convert it to string again! There is a styled writer but I don't want to use it as it appends some CRLF at the end.
I do something like this
CJsonHelper::getUInt(Json::Value &root, std::string key){
return root.get(key, 0-1).isInt() ? root.get(key, 0-1).asUInt() : 0-1;
}
Could I just write a single function to get all the properties with just that function which doesn't really care about the types etc?

The project has moved to GitHub.
To avoid all linefeeds, use a StreamWriterBuilder:
Json::Value whatever = ...;
Json::StreamWriterBuilder builder;
builder.settings_["indentation"] = "";
std::string out = Json::writeString(builder, whatever);

You can trivially create your own writer that does whatever you want. Have look at the code for StyledWriter. The CRLF's you don't like come from StyledWriter::Write. You can create your own writer class that doesn't have those CRLF's.
If you don't mind modifying the library, change the writer so that functions like writeValue are protected rather than private. Then you can derive your own class from StyledWriter with a different Write function and still use the various write* functions to do the details of the conversion.

Related

Setting a property that I can access in the serialize functions when using Cereal serialization library

I'm using the 'Cereal' serialization library (uscilab.github.io/cereal/) to serialize objects that can have millions of numbers, and the meta-data that describes the numbers. In some instances, I do not need the numbers to be serialized, just the meta-data; other times I would like both in the archive.
The only way I could think to achieve was to add a boolean property to the OutputArchive class defined in the cereal.hpp file. My thinking is that when I construct the archive, I set this value. Then, when the serialization code runs, any object could access this property and serialize the appropriate values. Most objects would ignore this property, but the objects holding the (potentially) millions of numbers could either ignore the numbers or not, based on the value of this property.
Here is some pseudocode to help explain (derived from the examples on the Cereal website). Creating an archive would look like this:
int main()
{
std::stringstream ss;
{
cereal::BinaryOutputArchive oarchive(ss, true); // I modified the constructor to accept a boolean parameter, and set the property
...
}
...
Then, within the function that serializes my data object (the object that holds metadata and the millions of numbers):
template<class Archive>
void save(Archive& ar) const
{
ar(metadata);
ar(more_meta_data);
boolean bArchiveEverything = ar.ArchiveNumbers(); //<<-- this is what I don't know how to accomplish
ar(bArchiveEverything); // put this into the archive, so I know what to expect when deserializing
if (bArchiveEverything) {
ar(bigVectorOfNumbers);
}
}
My questions:
1) Am I going about this all wrong? Is there a simpler more elegant way I'm missing?
2) If not, and this seems reasonable, I'm not sure how I can access my property in the OutputArchive through the 'Archive&' parameter that gets passed into the template functions that Cereal needs for serializing.
Thanks in advance for any help.
I still don't know if this was the best way, so I can't answer my first question.
However, accessing the property didn't end up being that difficult. It turns out, that as long as all of the classes that get passed into the 'save' function as 'ar' have the same function, I can use that function just like my pseudo-code function "ArchiveNumbers()". So, all I had to do was add that function to the 'OutputArchive' class in Cereal, and have it return my property.
I didn't think that would even compile, but I was wrong about that. I'm still trying to wrap my head around template programming. While I got this to work, I certainly can't say this is a 'best practice'.

Invoke different functions for different file extensions

Here's the situation:
I have a Graph class written in C++ and I need to build Graph objects from Files. The problem is that Graph are memorized in files in a lot of different ways, so I was thinking about a function that, using the file extension, could invoke the correct procedure for building a Graph in a certain format. How should I proceed? Am I wrong or I can't just overload operator>> in my class?Thanks in advance.
operator>> is (should be) agnostic to any details of the stream from which it is extracting, so using this operator is probably the wrong tact.
The best way to do this would be:
graph_type load_from_file(const std::string& file_path) { //or use something like boost::filesystem::path
std::ofstream file { file_path };
if(endswith(file_path, ".graph") {
return deserialize_from_graph(ofstream);
}
if(endswith(file_path, ".g2") {
return deserialize_from_g2(ofstream);
}
//other formats here
//else throw
}
note, endswith is not from the standard library, boost however has an implementation in it's string algorithms.
How do you determine how the data is memorized. If it is just
the extension, all you need is a map
std::string→pointer_to_function. If the same
extension can have several different representations,
distinguished, for example, by the first couple of bytes in the
file, or information in some common header, you'll have to
differ the final choice until you've read these
bytes—again, a map to the a pointer to function will do
the trick.
Depending on the complexity of the formats to read, you may want
to replace the pointer to a reader function with a pointer to
a factory function, which returns an instance of a reader class,
which derives from an abstract reader.

C++ - parameter question

I am looking for some simple and efficient parameter container that would act like a in-memory-xml file representation (or ini-file, as another sample).
I mean, basically it could store sections and sets of parameters for each section, have easy accessors like GetValue("ParameterName") and simple return value casting.
It would be great if it is serializable.
I wrote something like that yesterday and, well, it suits my needs, but probably there is something more convenient and flexible available?
Maybe some kind of parameter map in boost?
Thank you
Take a look at boost::program_options. It does what you want and more: INI file parsing, environment variables parsing, commandline options parsing and extensibility.
Have you considered std::map<>?
Dunno if it's overkill or not, but the Message class in MUSCLE does all of the things you listed above. You can use it to serialize any kind of data (structured or not), or use it as an in-memory container for parsed .ini style config files via ParseFile()/UnparseFile().
You can use Boost.PropertyTree.
It reads and writes xml and ini files.
It stores the parameters as a tree and you can use dot notation to access the values:
std::string value = pt.get<std::string>("debug.filename");
You can also insert new values using:
pt.put("debug.filename", fileName);

Generating data structures by parsing plain text files

I wrote a file parser for a game I'm writing to make it easy for myself to change various aspects of the game (things like the character/stage/collision data). For example, I might have a character class like this:
class Character
{
public:
int x, y; // Character's location
Character* teammate;
}
I set up my parser to read in from a file the data structure with syntax similar to C++
Character Sidekick
{
X = 12
Y = 0
}
Character AwesomeDude
{
X = 10
Y = 50
Teammate = Sidekick
}
This will create two data structures and put them in a map<std::string, Character*>, where the key string is whatever name I gave it (in this case Sidekick and AwesomeDude). When my parser sees a pointer to a class, like the teammate pointer, it's smart enough to look up in the map to fetch the pointer to that data structure. The problem is that I can't declare Sidekick's teammate to be AwesomeDude because it hasn't been placed into the Character map yet.
I'm trying to find the best way to solve this so that I can have my data structures reference objects that haven't yet been added to the map. The two easiest solutions that I can think of are (a) add the ability to forward declare data structures or (b) have the parser read through the file twice, once to populate the map with pointers to empty data structures and a second time to go through and fill them in.
The problem with (a) is that I also can decide which constructor to call on a class, and if I forward declare something I'd have to have the constructor be apart from the rest of the data, which could be confusing. The problem with (b) is that I might want to declare Sidekick and AwesomeDude in their own files. I'd have to make my parser be able to take a list of files to read rather than just one at a time (this isn't so bad I guess, although sometimes I might want to get a list of files to read from a file). (b) also has the drawback of not being able to use data structures declared later in the constructor itself, but I don't think that's a huge deal.
Which way sounds like a better approach? Is there a third option I haven't thought of? It seems like there ought to be some clever solution to this with pointer references or binding or something... :-/ I suppose this is somewhat subjective based on what features I want to give myself, but any input is welcome.
When you encounter the reference the first time, simply store it as a reference. Then, you can put the character, or the reference, or whatever on a list of "references that need to be resolved later".
When the file is done, run through those that have references and resolve them.
Well, you asked for a third option. You don't have to use XML, but if you follow the following structure, it would be very simple to use a SAX parser to build your data structure.
At any rate, instead of referencing a teammate, each character references a team (Blue team in this case). This will decouple the circular reference issue. Just make sure you list the teams before the characters.
<team>Blue</team>
<character>
<name>Sidekick</name>
<X>12</X>
<Y>0</Y>
<teamref>Blue</teamref>
</character>
<character>
<name>Sidekick</name>
<X>10</X>
<Y>50</Y>
<teamref>Blue</teamref>
</character>
Personally, I'd go with b). Splitting your code into Parser and Validator classes, both operating on the same data structure. The Parser will read and parse a file, filling the data structure and storing any object references as their textual names, leaving the real pointer null in your structure for now.
When you are finished loading the files, use the Validator class to validate and resolve any references, filling in the "real" pointers. You will want to consider how to structure your data to make these lookups nice and fast.
Will said exactly what I was about to write. Just keep a list or something with the unsolved references.
And don't forget to throw an error if there are unsolved references once you finish reading the file =P
Instead of storing Character object in your map, store a proxy for Character. The proxy will than contain a pointer to the actual Character object when the object is loaded. The type of Character::teammate will be changed to this proxy type. When you read in a reference that is not already in your map, you create a proxy and use the proxy. When you load an character which you already have an empty proxy in the map, populate it with your newly loaded character. You may also want to add a counter to keep track of how many empty proxy you have in the map so you know when all referenced characters have been loaded.
Another layer of indirection....it always make programming easier and slower.
One option would be to reverse the obligation. The Map is responsible for filling in the reference
template<T> class SymbolMap // I never could rememeber C++ template syntax
{
...
/// fill in target with thing name
/// if no name yet, add it to the list of thing that will be name
void Set(T& target, std::string name);
/// define name as target
/// go back and fill in anything that needs to be name
void Define(T target, std::string name);
/// make sure everything is resolved
~SymbolMap()
}
that won't interact well with value/moving semantics but I suspect that not much will.

Best way to take a snapshot of an object to a file

What's the best way to output the public contents of an object to a human-readable file? I'm looking for a way to do this that would not require me to know of all the members of the class, but rather use the compiler to tell me what members exist, and what their names are. There have to be macros or something like that, right?
Contrived example:
class Container
{
public:
Container::Container() {/*initialize members*/};
int stuff;
int otherStuff;
};
Container myCollection;
I would like to be able to do something to see output along the lines of "myCollection: stuff = value, otherStuff = value".
But then if another member is added to Container,
class Container
{
public:
Container::Container() {/*initialize members*/};
int stuff;
string evenMoreStuff;
int otherStuff;
};
Container myCollection;
This time, the output of this snapshot would be "myCollection: stuff = value, evenMoreStuff=value, otherStuff = value"
Is there a macro that would help me accomplish this? Is this even possible? (Also, I can't modify the Container class.)
Another note: I'm most interested about a potential macros in VS, but other solutions are welcome too.
What you're looking for is "[reflection](http://en.wikipedia.org/wiki/Reflection_(computer_science)#C.2B.2B)".
I found two promising links with a Google search for "C++ reflection":
http://www.garret.ru/cppreflection/docs/reflect.html
http://seal-reflex.web.cern.ch/seal-reflex/index.html
Boost has a serialization library that can serialize into text files. You will, however, not be able to get around with now knowing what members the class contains. You would need reflection, which C++ does not have.
Take a look at this library .
What you need is object serialization or object marshalling. A recurrent thema in stackoverflow.
I'd highly recommend taking a look at Google's Protocol Buffers.
There's unfortunately no macro that can do this for you. What you're looking for is a reflective type library. These can vary from fairly simple to home-rolled monstrosities that have no place in a work environment.
There's no real simple way of doing this, and though you may be tempted to simply dump the memory at an address like so:
char *buffer = new char[sizeof(Container)];
memcpy(buffer, containerInstance, sizeof(Container));
I'd really suggest against it unless all you have are simple types.
If you want something really simple but not complete, I'd suggest writing your own
printOn(ostream &) member method.
XDR is one way to do this in a platform independent way.