FileParse supports standard C++ containers: std::vector, std::set, std::array, std::map, and std::unordered_map.
#include <fileParse/Vector.hxx>
#include <fileParse/Set.hxx>
#include <fileParse/Array.hxx>
#include <fileParse/Map.hxx>
#include <fileParse/Common.hxx>
#include <fileParse/FileDataHandler.hxx>struct VectorData {
std::vector<double> values;
std::vector<std::string> names;
};template<typename NodeAdapter>
NodeAdapter& operator<<(NodeAdapter& node, const VectorData& v) {
// The path {"Values", "Value"} creates: <Values><Value>...</Value><Value>...</Value></Values>
node << FileParse::Child{{"Values", "Value"}, v.values};
node << FileParse::Child{{"Names", "Name"}, v.names};
return node;
}
template<typename NodeAdapter>
const NodeAdapter& operator>>(const NodeAdapter& node, VectorData& v) {
node >> FileParse::Child{{"Values", "Value"}, v.values};
node >> FileParse::Child{{"Names", "Name"}, v.names};
return node;
}<VectorData>
<Values>
<Value>1.5</Value>
<Value>2.7</Value>
<Value>3.9</Value>
</Values>
<Names>
<Name>Alice</Name>
<Name>Bob</Name>
</Names>
</VectorData>{
"VectorData": {
"Values": {
"Value": ["1.5", "2.7", "3.9"]
},
"Names": {
"Name": ["Alice", "Bob"]
}
}
}Sets work identically to vectors:
struct SetData {
std::set<int> uniqueIds;
};
template<typename NodeAdapter>
NodeAdapter& operator<<(NodeAdapter& node, const SetData& s) {
node << FileParse::Child{{"UniqueIds", "Id"}, s.uniqueIds};
return node;
}
template<typename NodeAdapter>
const NodeAdapter& operator>>(const NodeAdapter& node, SetData& s) {
node >> FileParse::Child{{"UniqueIds", "Id"}, s.uniqueIds};
return node;
}Fixed-size arrays with std::array:
struct ArrayData {
std::array<double, 3> coordinates; // Fixed size of 3
};
template<typename NodeAdapter>
NodeAdapter& operator<<(NodeAdapter& node, const ArrayData& a) {
node << FileParse::Child{{"Coordinates", "Coord"}, a.coordinates};
return node;
}
template<typename NodeAdapter>
const NodeAdapter& operator>>(const NodeAdapter& node, ArrayData& a) {
node >> FileParse::Child{{"Coordinates", "Coord"}, a.coordinates};
return node;
}Maps with string keys serialize naturally:
struct MapData {
std::map<std::string, double> properties;
};
template<typename NodeAdapter>
NodeAdapter& operator<<(NodeAdapter& node, const MapData& m) {
node << FileParse::Child{"Properties", m.properties};
return node;
}
template<typename NodeAdapter>
const NodeAdapter& operator>>(const NodeAdapter& node, MapData& m) {
node >> FileParse::Child{"Properties", m.properties};
return node;
}<MapData>
<Properties>
<Height>1.75</Height>
<Weight>70.5</Weight>
</Properties>
</MapData>{
"MapData": {
"Properties": {
"Height": "1.75",
"Weight": "70.5"
}
}
}For maps with complex key types, use serializeMapAsChilds and deserializeMapAsChilds:
struct ComplexMapData {
std::map<std::string, double> items;
};
template<typename NodeAdapter>
NodeAdapter& operator<<(NodeAdapter& node, const ComplexMapData& m) {
FileParse::MapStructure mapStruct{"Item", "Key", "Value"};
FileParse::serializeMapAsChilds(node, mapStruct, m.items);
return node;
}
template<typename NodeAdapter>
const NodeAdapter& operator>>(const NodeAdapter& node, ComplexMapData& m) {
FileParse::MapStructure mapStruct{"Item", "Key", "Value"};
FileParse::deserializeMapAsChilds(node, mapStruct, m.items);
return node;
}<ComplexMapData>
<Item>
<Key>temperature</Key>
<Value>23.5</Value>
</Item>
<Item>
<Key>humidity</Key>
<Value>65.0</Value>
</Item>
</ComplexMapData>- Vector/Set/Array elements are created as repeated child nodes
- The node path
{"Parent", "Child"}creates nested structure - Empty containers result in no elements being written
- Maps with string keys use the key as the XML tag name