将向量的内容添加到 Capnproto 地图对象中
Add content of a vector into a Capnproto map object
如中的回答:
Note that an individual List value in a Cap'n Proto structure has a limit of 2^29-1 elements
由于单个列表的这一限制,我试图将一个包含超过此数量的项目的列表拆分为一个列表映射。为此,我使用以下架构:
struct Map64UInt{
entries @0: List(Entry);
struct Entry{
key @0: UInt64;
value @1: List(UInt64);
}
}
我一直在研究 Cap'n Proto 的所有示例,但找不到包含有关如何创建 itens 并将其添加到 Capn'Proto 列表,然后将此列表添加到Cap'n 原始地图。例如,考虑以下代码:
void addVecToCapnprotoMap(std::vector<uint64_t> &v){
unsigned int key = 0;
//Here: how do I create a Capn' Proto List of uint64_t
//and add it to a Capn Proto map that follows the schema
//described above?
}
遗憾的是,您无法向列表动态添加新元素;您必须在首次创建列表时指定列表的完整大小。这是 Cap'n Proto 的零拷贝特性的副作用。由于列表直接就地分配到最终消息缓冲区中,因此以后无法调整其大小。
您可以做的是单独维护一个地图,然后在最后一步编写最终列表,例如:
// WARNING: Not tested, probably has typos.
class MapHelper {
public:
MapHelper(Map64UInt::Builder finalBuilder)
: finalBuilder(finalBuilder),
orphanage(capnp::Orphanage::getForMessageContaining(finalBuilder)) {}
void add(uint64_t key, const std::vector<unit64_t>& v) {
auto orphan = orphanage.newOrphan<capnp::List<uint64_t>>(v.size());
auto listBuilder = orphan.get();
for (size_t i = 0; i < v.size(); i++) {
listBuilder[i] = v[i];
}
contents.insert(std::make_pair(key, kj::mv(orphan)));
}
void finish() {
// Write all entries to the final map.
auto entriesBuilder = finalBuilder.initEntries(contents.size());
size_t i = 0;
for (auto& entry: contents) {
auto entryBuilder = entriesBuilder[i];
entryBuilder.setKey(entry.first);
entryBuilder.adoptValue(kj::mv(entry.second));
++i;
}
}
private:
Map64UInt::Builder finalBuilder;
capnp::Orphanage orphanage;
std::map<uint64_t, capnp::Orphan<capnp::List<uint64_t>>> contents;
};
如
Note that an individual List value in a Cap'n Proto structure has a limit of 2^29-1 elements
由于单个列表的这一限制,我试图将一个包含超过此数量的项目的列表拆分为一个列表映射。为此,我使用以下架构:
struct Map64UInt{
entries @0: List(Entry);
struct Entry{
key @0: UInt64;
value @1: List(UInt64);
}
}
我一直在研究 Cap'n Proto 的所有示例,但找不到包含有关如何创建 itens 并将其添加到 Capn'Proto 列表,然后将此列表添加到Cap'n 原始地图。例如,考虑以下代码:
void addVecToCapnprotoMap(std::vector<uint64_t> &v){
unsigned int key = 0;
//Here: how do I create a Capn' Proto List of uint64_t
//and add it to a Capn Proto map that follows the schema
//described above?
}
遗憾的是,您无法向列表动态添加新元素;您必须在首次创建列表时指定列表的完整大小。这是 Cap'n Proto 的零拷贝特性的副作用。由于列表直接就地分配到最终消息缓冲区中,因此以后无法调整其大小。
您可以做的是单独维护一个地图,然后在最后一步编写最终列表,例如:
// WARNING: Not tested, probably has typos.
class MapHelper {
public:
MapHelper(Map64UInt::Builder finalBuilder)
: finalBuilder(finalBuilder),
orphanage(capnp::Orphanage::getForMessageContaining(finalBuilder)) {}
void add(uint64_t key, const std::vector<unit64_t>& v) {
auto orphan = orphanage.newOrphan<capnp::List<uint64_t>>(v.size());
auto listBuilder = orphan.get();
for (size_t i = 0; i < v.size(); i++) {
listBuilder[i] = v[i];
}
contents.insert(std::make_pair(key, kj::mv(orphan)));
}
void finish() {
// Write all entries to the final map.
auto entriesBuilder = finalBuilder.initEntries(contents.size());
size_t i = 0;
for (auto& entry: contents) {
auto entryBuilder = entriesBuilder[i];
entryBuilder.setKey(entry.first);
entryBuilder.adoptValue(kj::mv(entry.second));
++i;
}
}
private:
Map64UInt::Builder finalBuilder;
capnp::Orphanage orphanage;
std::map<uint64_t, capnp::Orphan<capnp::List<uint64_t>>> contents;
};