libnop: C++ 本机对象协议
libnop 是一个仅包含头文件的库,用于在没有外部代码生成器或运行时支持库的情况下序列化和反序列化 C++ 数据类型。唯一的强制要求是支持 C++14 标准的编译器。
注意:目前这不是官方支持的 Google 产品。
目标
libnop 有以下目标:
- 使简单的序列化任务变得容易,复杂的任务变得可行。
- 消除使用代码生成器和模式文件来描述数据类型、格式和协议的需要:在 C++ 语言中自然执行这些任务。
- 避免序列化的额外运行时支持要求。
- 提供当代功能,如双向二进制兼容性、数据验证、类型安全性和类型可互换性。
- 以最小的工作量处理内部类型、常见 STL 类型和容器以及用户定义的类型。
- 生成易于分析和剖析的优化代码。 -在可能的情况下避免内部动态内存分配。
入门指南
请查看《入门指南》以了解该库的简介。
快速示例
这里是一系列快速示例,演示了如何使用 libnop。您可以在存储库的 examples/ 目录下找到更多示例。
将 STL 容器写入流中
#include <iostream>
#include <map>
#include <sstream>
#include <utility>
#include <vector>
#include <nop/serializer.h>
#include <nop/utility/stream_writer.h>
int main(int argc, char** argv) {
using Writer = nop::StreamWriter<std::stringstream>;
nop::Serializer<Writer> serializer;
serializer.Write(std::vector<int>{1, 2, 3, 4});
serializer.Write(std::vector<std::string>{"foo", "bar", "baz"});
using MapType =
std::map<std::uint32_t, std::pair<std::uint64_t, std::string>>;
serializer.Write(
MapType{{0, {10, "foo"}}, {1, {20, "bar"}}, {2, {30, "baz"}}});
const std::string data = serializer.writer().stream().str();
std::cout << "Wrote " << data.size() << " bytes." << std::endl;
return 0;
}
简单自定义类型
#include <cstdint>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <nop/serializer.h>
#include <nop/structure.h>
#include <nop/utility/stream_writer.h>
namespace example {
struct Person {
std::string name;
std::uint32_t age_years;
std::uint8_t height_inches;
std::uint16_t weight_pounds;
NOP_STRUCTURE(Person, name, age_years, height_inches, weight_pounds);
};
} // namespace example
int main(int argc, char** argv) {
using Writer = nop::StreamWriter<std::stringstream>;
nop::Serializer<Writer> serializer;
serializer.Write(example::Person{"John Doe", 37, 72, 180});
serializer.Write(std::vector<example::Person>{
{"John Doe", 37, 72, 180}, {"Jane Doe", 36, 69, 130}});
const std::string data = serializer.writer().stream().str();
std::cout << "Wrote " << data.size() << " bytes." << std::endl;
return 0;
}
复杂自定义类型
#include <array>
#include <iostream>
#include <sstream>
#include <string>
#include <nop/serializer.h>
#include <nop/structure.h>
#include <nop/utility/stream_writer.h>
namespace example {
// Contrived template type with private members.
template <typename T>
struct UserDefined {
public:
UserDefined() = default;
UserDefined(std::string label, std::vector<T> vector)
: label_{std::move(label)}, vector_{std::move(vector)} {}
const std::string label() const { return label_; }
const std::vector<T>& vector() const { return vector_; }
private:
std::string label_;
std::vector<T> vector_;
NOP_STRUCTURE(UserDefined, label_, vector_);
};
} // namespace example
int main(int argc, char** argv) {
using Writer = nop::StreamWriter<std::stringstream>;
nop::Serializer<Writer> serializer;
serializer.Write(example::UserDefined<int>{"ABC", {1, 2, 3, 4, 5}});
using ArrayType = std::array<example::UserDefined<float>, 2>;
serializer.Write(
ArrayType{{{"ABC", {1, 2, 3, 4, 5}}, {"XYZ", {3.14, 2.72, 23.14}}}});
const std::string data = serializer.writer().stream().str();
std::cout << "Wrote " << data.size() << " bytes." << std::endl;
return 0;
}
更加复杂的用户自定义类型
#include <array>
#include <iostream>
#include <sstream>
#include <string>
#include <nop/serializer.h>
#include <nop/structure.h>
#include <nop/utility/stream_writer.h>
namespace example {
// Contrived template type with private members.
template <typename T>
struct UserDefined {
public:
UserDefined() = default;
UserDefined(std::string label, std::vector<T> vector)
: label_{std::move(label)}, vector_{std::move(vector)} {}
const std::string label() const { return label_; }
const std::vector<T>& vector() const { return vector_; }
private:
std::string label_;
std::vector<T> vector_;
NOP_STRUCTURE(UserDefined, label_, vector_);
};
} // namespace example
int main(int argc, char** argv) {
using Writer = nop::StreamWriter<std::stringstream>;
nop::Serializer<Writer> serializer;
serializer.Write(example::UserDefined<int>{"ABC", {1, 2, 3, 4, 5}});
using ArrayType = std::array<example::UserDefined<float>, 2>;
serializer.Write(
ArrayType{{{"ABC", {1, 2, 3, 4, 5}}, {"XYZ", {3.14, 2.72, 23.14}}}});
const std::string data = serializer.writer().stream().str();
std::cout << "Wrote " << data.size() << " bytes." << std::endl;
return 0;
}