msgpack-c icon indicating copy to clipboard operation
msgpack-c copied to clipboard

Creating collection of msgpack::object

Open taushkanov opened this issue 6 years ago • 7 comments

I'm looking for a simple way for creating a collection of msgpack::object, for example: [1, 2, 3][4, 5, 6][7, 8, 9]

Recently I reached this by serializing several msgpack::object into buffer and deserializing it back into one object holding three arrays. I hope it can be done with much simpler approach.

taushkanov avatar Jan 21 '19 09:01 taushkanov

How about this? https://wandbox.org/permlink/h9JPuQeMNFfS9nkC https://wandbox.org/permlink/x4tOyPvlfIvnm0AQ

redboltz avatar Jan 21 '19 13:01 redboltz

You can also do like this. https://wandbox.org/permlink/8C1s0e1N7G5xXSzm

redboltz avatar Jan 21 '19 13:01 redboltz

In the approaches above, you need to care the lifetime of msgpack::zone.

You can make a pair of msgpack::object and msgpack::zone as follows:

#include <msgpack.hpp>
#include <iostream>

int main() {
  auto z = std::make_unique<msgpack::zone>();
  auto obj = msgpack::object(
    std::make_tuple( std::make_tuple(1, 2.34, "ABC"), std::make_tuple(false, 5) ),
    *z
  );
  std::cout << obj << std::endl;
  msgpack::object_handle oh(obj, std::move(z));
  std::cout << oh.get() << std::endl;
}

https://wandbox.org/permlink/tgNoHz16MFM3ajpc

You can treat the value oh like as the deserialized one ( msgpack::object_handle oh = msgpack::unpack(...);).

redboltz avatar Jan 21 '19 14:01 redboltz

Thank you for quick answer. Please advice how to resolve next task:

We have some created objects:

msgpack::object Obj1;
msgpack::object Obj2;
msgpack::object Obj3;

How to put them into one msgpack::object as array in the most efficient way?

taushkanov avatar Jan 26 '19 04:01 taushkanov

msgpack::object is basically designed as a kind of view type. msgpack::object can be created from any C++ types that support adaptor. In addition msgpack::object can be created from MessagePack formatted byte stream. It is called unpacking.

However, you cannot add elements dynamically to the msgpack::object that is previously created.

So, you need to do something like as follows:

#include <msgpack.hpp>
#include <iostream>

int main() {
  auto z = std::make_unique<msgpack::zone>();
  msgpack::object o1(1);
  msgpack::object o2(2);
  msgpack::object o3(3);

  // create a vector of msgpack::object
  std::vector<msgpack::object> vmo;
  // add msgpack::object to the vector
  vmo.push_back(o1);
  vmo.push_back(o2);
  vmo.push_back(o3);

  // create the new msgpack::object from the vector
  auto obj = msgpack::object(
    vmo,
    *z
  );

  std::cout << obj << std::endl;
  msgpack::object_handle oh(obj, std::move(z));
  std::cout << oh.get() << std::endl;
}

https://wandbox.org/permlink/snQMompWOHD4YwrP

redboltz avatar Jan 26 '19 04:01 redboltz

Thank you. It seems that this solution fits all described tasks ^) But there is some inconvenience caused by need to keep zone alive when passing msgpack::object between functions.

taushkanov avatar Jan 26 '19 05:01 taushkanov

But there is some inconvenience caused by need to keep zone alive when passing msgpack::object between functions.

See https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_object

msgpack::object_handle can treat zone and msgpack::object (including recursive sub objects) well.

NOTE:

You might think why msgpack::zone is needed, msgpack::object can manage their sub object by itself. It is for performance.

I used to try to eliminate msgpack::zone from the msgpack-c library. During that process, I noticed that I need to implement msgpack::object destructor recursively. If a msgpack::object has sub objects, the parent destructor need to call the sub-objects' destructor recursively. That means the destructor cannot be inlined. Inline or not inline is decided at compile time. That means most of leaf objects destructor that do nothing is actually called. It wasteful. I measured the performance. Using zone version is better.

redboltz avatar Jan 26 '19 11:01 redboltz