Unpacking msgpack to an arbitrary object, without msgpack_define - c++

I'm working on a body of code which deals with a custom String implementation rather than the std::string (long story but for various reasons this has to be used) which I will refer to as "String" from here on.
I was able to easily pack the String without issue using the "raw" type to pack the raw char bytes and the size but I'm having problems unpacking it.
I was able to manually unpack it as shown below.
// before this I've unpacked to the point where the following object has the string
msgpack::object_kv& kv = obj.via.map.ptr[0];
// kv.key == the String I want
String key = String(key.via.raw.ptr, key.via.raw.size); // this works
But I want to use the built in >> operator or the .as template function and haven't been able to manage it. I don't have access to modify the String class to add the msgpack_unpack function nor to add MSGPACK_DEFINE
I tried creating a struct and giving it a msgpack_unpack function, but apparently it calls it with msgpack::object::implicit_type which my compiler replies with
error: 'struct msgpack::object::implicit_type' is private
And then I can't figure out any way of getting the msgpack::object out of the "implicit_type" object.
Any ideas?

So I figured it out! Thanks to hetepeperfan for the idea
After taking another crack at using operator>> overloading, the problem that prevented it from working before the strange way the operator>> being overloaded is called from the msgpack code.
namespace msgpack {
String& operator>>(msgpack::object o, String& v) {
v = String(o.via.raw.ptr, o.via.raw.size);
return v;
}
}
I needed to both use the msgpack namespace, and match the signature by returning the String by reference and take the object in NOT by reference. This seems a little ridiculous but it works and I can now use the built in "as<>" and convert functionality. awesome!

Related

How can I transform a pointer to the type I input in C++?

I have a question here:
I want to generate a type_t pointer (type_t *), pointing to a memory block, with specified value stored in it.
In another word, its input is:
string value,
string type
and its output is:
(type*)pointer , pointing to some memory storing 'value'.
I don't know how to do this. I tried to use templates, but I think it need 'type', not the "string type". My only idea is to generate a new cpp file with these information and use it to achieve that. But that's quite awkward when I want to generate enoumous values...
I come up to this question when diving in clang tooling, with QualType and binary value in my hand, and I want to recover the original value. I tried to use the constructors in Expr or VarDecl, but failed to achieve my goal.
Can anyone provide some thoughts? Thanks a lot for your reading this message.
Thanks a lot for all your efforts! I think I should get the question clearer with some code
My goal is to write a function like this
type_t* func(QualType type_t, string value)
{ /* some magic here */}
or maybe
type_t* func(string type_t, string value)
{ /* some magic here */}
It sounds impossible, cause the type is not even determined before the input QualType is determined.
Sure void* is a great idea to be used as a middleware, I still wonder how I could write
type_t* func(string type_t, void* memory_block)
{ /* some magic here */}
I think the question is the same as: How can we input a type message and output some value (already existed maybe) with that type?
Thanks again.
This kind of functionality is not provided in c or c++.You can do that in python using exec().
One thing you can do to solve this problem is to declare some of the variables beforehand with the same name as the string that you want to pass.
You can use void pointers to cast any type of pointers. let me know if it works.IT would be great if you provide a script of what you want to do

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'.

Getting type of range for use in member declaration

I have a somewhat complex range I want to assign to a data member of a class.
chain(nicklist,
map!(a=>format("%s%d", nicklist[0], a))(sequence!"n+1"()))
nicklist is just a string[]. Normally my trusty friend auto would just take care of this but for a data member I need to declare the type and I'm at a loss for what that type should be. I've tried to figure out how to use typeof() to get it but the runtime arguments confuse me and I haven't been able to figure out how to formulate it.
(this is being used for an IRC bot. nicklist is a list of nicks I want it to try in order and after it has exhausted all of those with nick collisions it'll just try the first nick with numbers appended)
This would work:
typeof(chain(cast(string[])[], map!(a=>format("%s%d", "", a))(sequence!"n+1"()))) memberVar;
Another possibility would be to have a function wrap it and then take its return type and use that:
auto func(string[] nicklist)
{
return chain(nicklist,
map!(a=>format("%s%d", nicklist[0], a))(sequence!"n+1"()));
}
ReturnType!func memberVar;
ReturnType is in std.traits.

How to get JsonCPP values as strings?

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.

How to instantiate objects whose constructor requires parameters from a string holding the class name?

Is there a way to instantiate objects from a string holding their class name?
I got a problem basically the same with the above question. But I need to instantiate a class with some parameters. different class constructor name may require different number of variables and the type of each variable may differ either. And because the class contains constant variables so you could not new it with new T() and then set the parameter to the correct value. the "class name"-"constructor" map seems not suitable for my needs.
Any alternatives?
I'm going to preface this by saying, maybe C++ isn't the right language for whatever you're trying to accomplish. The more you try to control your program via external data, the closer you get to full on scripting. And there are lots of more powerful options when that is your goal.
That said, sure, it is possible, although not as easily. Two ways come immediately to mind. The first is to require all applicable types to have a constructor that accepts a std::string. This constructor will be responsible for its own parsing.
template<typename T> Base * createInstance(const std::string& s) { return new T(s); }
typedef std::map<std::string, Base*(*)(const std::string&)> map_type;
//...and similar changes as needed
If you don't want to change your type definitions, or this is otherwise unacceptable [perhaps your types already have such a constructor?], get rid of the templated createInstance method, and provide individual versions for each type you are interested in. This function does the parsing, and calls the appropriate constructor.
map["derivedA"] = createDerivedA;
map["derivedB"] = createDerivedB;
A third option might be possible using variadic templates [or boost-esque variadic-like templates] that would bring you back to the original simplicity.
template<typename T, typename... Args>
Base* create(std::string) {
//somehow pass the string to a generic function that packs the arguments into a tuple
//then somehow unpack that tuple and pass the bits to the constructor
}
map["derivedA"] = create<derivedA, int, double, std::string>;
However, I have no idea how to pull that off, or even if it is possible.
You could use a factory design patten. pass your string to the factory class and then let it decode your string choosing the correct version of the constructor and class to call. it would then pass back an instance of the correct class for the rest of your code to use.
Here's some info factory design pattern