简体   繁体   中英

c++ write data with cyclic dependencies in binary file using flatbuffers

I'm trying to write a Graph into a binary file by using flatbuffers. A graph consists of nodes and edges. Every node has at least one edge and every edge consists of two nodes.

Excerpt from MyGraph.fbs:

namespace MyGraph;

table Node {
  edges:[Edge];
}

table Edge {
  startNode:Node;
  endNode:Node;
}

table Graph {
  allNodes:[Node];
}

root_type Graph;

Now I want to create a simple graph and write it into a bytefile:

FlatBufferBuilder fbb;
// create first node
auto node1mloc = DG::CreateNode(fbb, 0, 0);

// create second node
auto node2mloc = DG::CreateNode(fbb, 0, 0);

// create edge between first and second node
auto edgeloc = DG::CreateEdge(fbb, node1mloc, node2mloc);


// ???
// store the edge in the edges-vector of node1 and node2
// ???

// store nodes in graph
flatbuffers::Offset<Node> nodes[] = {node1mloc, node2mloc};

auto allNodes = fbb.CreateVector(nodes, 2);

auto graphloc = DG::CreateGraph(fbb, allNodes);

DG::FinishGraphBuffer(fbb, graphloc);


// write graph into file
auto buffer_pointer = fbb.GetBufferPointer();
SaveFile("myfile2.bin", reinterpret_cast<const char *>(buffer_pointer), fbb.GetSize(), true);



// load graph from file
string binData;
LoadFile("myfile2.bin", true, &binData);

auto graph = DG::GetGraph(binData.data());
cout << graph->allNodes()->size() << endl;
assert(graph->allNodes()->size() == 2);

The Problem is, that after creating the nodes, I can't add the edge to the edges-vector of node1 and node2. Is there a solution for that kind of cyclic dependencies between two types.

You cannot store cyclic structures in a FlatBuffer (it enforces that children always come before parents, using unsigned offsets).

You can store DAGs, however.

To encode a cyclic structure, you'll have to use indices for either Nodes or Edge references, eg

table Edge {
  startNode:uint;
  endNode:uint;
}

This means these node references are an index into allNodes .

Note that there's very few serialization formats that allow graphs, eg Protocol Buffers and JSON both only allow trees.

This works in FlatBuffersSwift but is not supported in the official FlatBuffers implementation.

//: Playground - noun: a place where people can play

import Foundation

var str = "Hello, playground"


let (f1, f2, f3, f4) = (Friend(), Friend(), Friend(), Friend())

f1.name = "Maxim"
f2.name = "Leo"
f3.name = "Boris"
f4.name = "Marc"

let f5 = Friend()
f5.name = "Daria"

f1.friends = [f1, f2, f3, f4]
f2.friends = [f1, f4]
f3.friends = [f2, f4]

f1.lover = Female(ref: f5)
f5.lover = Male(ref: f1)

f1.father = Friend()
f1.father?.name = "Issai"

f1.mother = Friend()
f1.mother?.name = "Margo"

let data = f1.toByteArray()

let f = Friend.fromByteArray(UnsafeBufferPointer(start:UnsafePointer<UInt8>(data), count: data.count))

print(f.friends[2]?.friends[0]?.friends[0]?.name)

print(((f.lover as? Female)?.ref?.lover as? Male)?.ref?.name)


let lazyF = Friend.Fast(data)

let girlFriend = (lazyF.lover as! Female.Fast).ref
let boyFriend = (girlFriend?.lover as! Male.Fast).ref

lazyF == boyFriend

I asked in the google groups chat if it would be of interest for main project. Seems like it will not happen any time soon.

https://groups.google.com/forum/#!topic/flatbuffers/Y9K9wRKSHxg

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM