mirror of
https://github.com/fraillt/bitsery.git
synced 2026-08-18 09:09:52 +00:00
added bitpacking and context usage examples
This commit is contained in:
@@ -32,7 +32,7 @@ Look at the numbers and features list, and decide yourself.
|
||||
| | binary size | data size | serialize | deserialize |
|
||||
|------------------------------|-------------|-----------|-------------|-------------|
|
||||
| **test_bitsery** | 64704 | **7565** | **1229 ms** | **1086 ms** |
|
||||
| **test_bitsery_compression** | 44000 | **4784** | **1370 ms** | **2463 ms** |
|
||||
| **test_bitsery_compression** | 64880 | **4784** | **1641 ms** | **2462 ms** |
|
||||
| test_yas | 63864 | 11311 | 1616 ms | 1712 ms |
|
||||
| test_yas_compression | 72688 | 8523 | 2387 ms | 2890 ms |
|
||||
| test_cereal | 74848 | 11261 | 6708 ms | 6799 ms |
|
||||
|
||||
64
examples/bit_packing.cpp
Normal file
64
examples/bit_packing.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include <bitsery/bitsery.h>
|
||||
#include <bitsery/adapter/buffer.h>
|
||||
//we'll be using std::array as a buffer type, so include traits for this
|
||||
#include <bitsery/traits/array.h>
|
||||
#include <bitsery/traits/string.h>
|
||||
#include <bitsery/traits/vector.h>
|
||||
//include extension that will allow to compress our data
|
||||
#include <bitsery/ext/value_range.h>
|
||||
|
||||
namespace MyTypes {
|
||||
|
||||
struct Vec3 { float x, y, z; };
|
||||
|
||||
struct Monster {
|
||||
Vec3 pos;
|
||||
std::vector<Vec3> path;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
template<typename S>
|
||||
void serialize(S& s, MyTypes::Vec3 &o) {
|
||||
s.value4b(o.x);
|
||||
s.value4b(o.y);
|
||||
s.value4b(o.z);
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
void serialize (S& s, Monster& o) {
|
||||
s.text1b(o.name, 20);
|
||||
s.object(o.pos);
|
||||
//compress path in a range of -1.0 .. 1.0 with 0.01 precision
|
||||
//enableBitPacking creates separate serializer/deserializer object, that contains bit packing operations
|
||||
s.enableBitPacking([&o](typename S::BPEnabledType& sbp) {
|
||||
sbp.container(o.path, 1000, [&sbp](Vec3& vec3) {
|
||||
constexpr bitsery::ext::ValueRange<float> range{-1.0f,1.0f, 0.01f};
|
||||
sbp.ext(vec3.x, range);
|
||||
sbp.ext(vec3.y, range);
|
||||
sbp.ext(vec3.z, range);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
using namespace bitsery;
|
||||
|
||||
//use fixed-size buffer
|
||||
using Buffer = std::array<uint8_t, 10000>;
|
||||
using OutputAdapter = OutputBufferAdapter<Buffer>;
|
||||
using InputAdapter = InputBufferAdapter<Buffer>;
|
||||
|
||||
int main() {
|
||||
//set some random data
|
||||
MyTypes::Monster data{};
|
||||
data.name = "lew";
|
||||
|
||||
//create buffer to store data to
|
||||
Buffer buffer{};
|
||||
auto writtenSize = quickSerialization<OutputAdapter>(buffer, data);
|
||||
|
||||
MyTypes::Monster res;
|
||||
auto state = quickDeserialization<InputAdapter>({buffer.begin(), writtenSize}, res);
|
||||
|
||||
assert(state.first == ReaderError::NoError && state.second);
|
||||
}
|
||||
90
examples/context_usage.cpp
Normal file
90
examples/context_usage.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include <bitsery/bitsery.h>
|
||||
#include <bitsery/adapter/buffer.h>
|
||||
|
||||
#include <bitsery/traits/string.h>
|
||||
#include <bitsery/traits/vector.h>
|
||||
|
||||
#include <bitsery/ext/value_range.h>
|
||||
|
||||
//defines game mode parameters
|
||||
struct GameMode {
|
||||
uint32_t maxMonsters;
|
||||
uint32_t damageRange[2];
|
||||
};
|
||||
|
||||
namespace MyTypes {
|
||||
|
||||
struct Monster {
|
||||
std::string name;
|
||||
uint32_t minDamage;
|
||||
uint32_t maxDamage;
|
||||
//...
|
||||
};
|
||||
|
||||
struct GameState {
|
||||
std::vector<Monster> monsters;
|
||||
};
|
||||
|
||||
//default flow for monster
|
||||
template <typename S>
|
||||
void serialize (S& s, Monster& o) {
|
||||
s.text1b(o.name, 20);
|
||||
s.value4b(o.minDamage);
|
||||
s.value4b(o.maxDamage);
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
void serialize(S& s, GameState &o) {
|
||||
auto mode = static_cast<GameMode*>(s.context());
|
||||
//we know max number of monsters from context
|
||||
s.container(o.monsters, mode->maxMonsters, [&s, mode] (Monster& m) {
|
||||
s.text1b(m.name, 20);
|
||||
//we know min/max damage range for monsters, so we can use this range instead of full value
|
||||
bitsery::ext::ValueRange<uint32_t> range{mode->damageRange[0], mode->damageRange[1]};
|
||||
//enable bit packing
|
||||
s.enableBitPacking([&m, &range](typename S::BPEnabledType& sbp) {
|
||||
sbp.ext(m.minDamage, range);
|
||||
sbp.ext(m.maxDamage, range);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using namespace bitsery;
|
||||
|
||||
//use fixed-size buffer
|
||||
using Buffer = std::vector<uint8_t>;
|
||||
using OutputAdapter = OutputBufferAdapter<Buffer>;
|
||||
using InputAdapter = InputBufferAdapter<Buffer>;
|
||||
|
||||
int main() {
|
||||
MyTypes::GameState data{};
|
||||
data.monsters.push_back({"weaksy", 100, 200});
|
||||
data.monsters.push_back({"bigsy", 500, 1000});
|
||||
data.monsters.push_back({"tootoo", 350, 750});
|
||||
|
||||
//set game mode
|
||||
//this store game mode parameters
|
||||
GameMode mode{};
|
||||
mode.maxMonsters = 4;
|
||||
mode.damageRange[0] = 100;
|
||||
mode.damageRange[1] = 1000;
|
||||
|
||||
//create buffer to store data to
|
||||
Buffer buffer{};
|
||||
//pass game mode object to serializer as context
|
||||
Serializer<OutputAdapter> ser{buffer, &mode};
|
||||
ser.object(data);
|
||||
|
||||
auto& w = AdapterAccess::getWriter(ser);
|
||||
w.flush();
|
||||
auto writtenSize = w.writtenBytesCount();
|
||||
|
||||
MyTypes::GameState res;
|
||||
Deserializer <InputAdapter> des { InputAdapter{buffer.begin(), writtenSize}, &mode};
|
||||
des.object(res);
|
||||
auto& r = AdapterAccess::getReader(des);
|
||||
|
||||
assert(r.error() == ReaderError::NoError && r.isCompletedSuccessfully());
|
||||
}
|
||||
Reference in New Issue
Block a user