You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
7.3 KiB
180 lines
7.3 KiB
#ifndef DYNAMIC_DEPTH_INTERNAL_XMPMETA_XML_SERIALIZER_IMPL_H_ // NOLINT
|
|
#define DYNAMIC_DEPTH_INTERNAL_XMPMETA_XML_SERIALIZER_IMPL_H_ // NOLINT
|
|
|
|
#include <libxml/tree.h>
|
|
|
|
#include <string>
|
|
#include <unordered_map>
|
|
|
|
#include "xmpmeta/xml/serializer.h"
|
|
|
|
namespace dynamic_depth {
|
|
namespace xmpmeta {
|
|
namespace xml {
|
|
|
|
// Writes properties, lists, and child nodes into an XML structure.
|
|
//
|
|
// Usage example:
|
|
// std::unordered_map<string, xmlNsPtr> namespaces;
|
|
// string device_name("Device");
|
|
// string cameras_name("Cameras");
|
|
// string camera_name("Camera");
|
|
// string audio_name("Audio");
|
|
// string image_name("Image");
|
|
// PopulateNamespaces(&namespaces);
|
|
// DoSerialization();
|
|
//
|
|
// // Serialization example.
|
|
// void DoSerialization() {
|
|
// xmlNodePtr device_node = xmlNewNode(nullptr, device_name);
|
|
// Serializer device_serializer(namespaces, device_node);
|
|
//
|
|
// std::unique_ptr<Serializer> cameras_serializer =
|
|
// serializer->CreateListSerializer(cameras_name);
|
|
// for (XdmCamera *camera : camera_list_) {
|
|
// std::unique_ptr<Serializer> camera_serializer =
|
|
// cameras_serializer->CreateItemSerializer("Device", camera_name);
|
|
// success &= camera->Serialize(camera_serializer.get());
|
|
//
|
|
// // Serialize Audio.
|
|
// std::unique_ptr<Serializer> audio_serializer =
|
|
// camera_serializer->CreateSerializer("Camera", audio_name);
|
|
// audio_serializer->WriteProperty(camera_name, "Data", audio_data);
|
|
// audio_serializer->WriteProperty(camera_name, "Mime", "audio/mp4");
|
|
//
|
|
// // Serialize Image.
|
|
// std::unique_ptr<Serializer> image_serializer =
|
|
// camera_serializer->CreateSerializer("Camera", image_name);
|
|
// image_serializer->WriteProperty(image_name, "Data", image_data);
|
|
// image_serializer->WriteProperty(image_name, "Mime", "image/jpeg");
|
|
//
|
|
// // Serialize ImagingModel.
|
|
// std::unique_ptr<Serializer> imaging_model_serializer =
|
|
// camera_serializer->CreateSerializer("Camera", "ImagingModel");
|
|
// std::unique_ptr<Serializer> equirect_model_serializer =
|
|
// imaging_model_serializer->CreateSerializer("Camera",
|
|
// "EquirectModel");
|
|
// // Serializer equirect model fields here.
|
|
// }
|
|
// }
|
|
//
|
|
// Resulting XML structure:
|
|
// /*
|
|
// * <Device>
|
|
// * <Device:Cameras>
|
|
// * <rdf:Seq>
|
|
// * <rdf:li>
|
|
// * <Device:Camera>
|
|
// * <Camera:Audio Audio:Mime="audio/mp4" Audio:Data="DataValue"/>
|
|
// * <Camera:Image Image:Mime="image/jpeg" Image:Data="DataValue"/>
|
|
// * <Camera:ImagingModel>
|
|
// * <Camera:EquirectModel ...properties/>
|
|
// * </Camera:ImagingModel>
|
|
// * </Device:Camera>
|
|
// * </rdf:li>
|
|
// * </rdf:Seq>
|
|
// * </Device:Cameras>
|
|
// * </Device>
|
|
// */
|
|
//
|
|
// // Namespace population example.
|
|
// void PopulateNamespaces(std::unordered_map<string, xmlNsPtr>* namespaces) {
|
|
// xmlNsPtr device_ns =
|
|
// xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/device")
|
|
// ToXmlChar(device_name.data()));
|
|
// xmlNsPtr camera_ns =
|
|
// xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/camera")
|
|
// ToXmlChar(camera_name.data()));
|
|
// xmlNsPtr audio_ns =
|
|
// xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/audio")
|
|
// ToXmlChar(audio_name.data()));
|
|
// xmlNsPtr image_ns =
|
|
// xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/image")
|
|
// ToXmlChar(image_name.data()));
|
|
// namespaces->insert(device_name, device_ns);
|
|
// namespaces->insert(camera_name, camera_ns);
|
|
// namespaces->insert(audio_name, audio_ns);
|
|
// namespaces->insert(image_name, image_ns);
|
|
// }
|
|
|
|
class SerializerImpl : public Serializer {
|
|
public:
|
|
// Constructor.
|
|
// The prefix map is required if one of the CreateSerializer methods will be
|
|
// called on this object. In particular, the RDF namespace must be present in
|
|
// the prefix map if CreateItemSerializer or CreateListSerializer will be
|
|
// called.
|
|
// The namespaces map serves to keep XML namespace creation out of this
|
|
// Serializer, to simplify memory management issues. Note that the libxml
|
|
// xmlDocPtr will own all namespace and node pointers.
|
|
// The namespaces parameter is a map of node names to full namespaces.
|
|
// This contains all the namespaces (nodes and properties) that will be used
|
|
// in serialization.
|
|
// The node parameter is the caller node. This will be the node in which
|
|
// serialization takes place in WriteProperties.
|
|
SerializerImpl(const std::unordered_map<string, xmlNsPtr>& namespaces,
|
|
xmlNodePtr node);
|
|
|
|
// Returns a new Serializer for an object that is part of an rdf:Seq list
|
|
// of objects.
|
|
// The parent serializer must be created with CreateListSerializer.
|
|
std::unique_ptr<Serializer> CreateItemSerializer(
|
|
const string& prefix, const string& item_name) const override;
|
|
|
|
// Returns a new Serializer for a list of objects that correspond to an
|
|
// rdf:Seq XML node, where each object is to be serialized as a child node of
|
|
// every rdf:li node in the list.
|
|
// The serializer is created on an rdf:Seq node, which is the child of a
|
|
// newly created XML node with the name list_name.
|
|
std::unique_ptr<Serializer> CreateListSerializer(
|
|
const string& prefix, const string& list_name) const override;
|
|
|
|
// Creates a serializer from the current serializer.
|
|
// @param node_name The name of the caller node. This will be the parent of
|
|
// any new nodes or properties set by this serializer.
|
|
std::unique_ptr<Serializer> CreateSerializer(
|
|
const string& node_ns_name, const string& node_name) const override;
|
|
|
|
// Writes the property into the current node, prefixed with prefix if it
|
|
// has a corresponding namespace href in namespaces_, fails otherwise.
|
|
// Returns true if serialization is successful.
|
|
// If prefix is empty, the property will not be set on an XML namespace.
|
|
// name must not be empty.
|
|
// value may be empty.
|
|
bool WriteBoolProperty(const string& prefix, const string& name,
|
|
bool value) const override;
|
|
bool WriteProperty(const string& prefix, const string& name,
|
|
const string& value) const override;
|
|
|
|
// Writes the collection of numbers into a child rdf:Seq node.
|
|
bool WriteIntArray(const string& prefix, const string& array_name,
|
|
const std::vector<int>& values) const override;
|
|
bool WriteDoubleArray(const string& prefix, const string& array_name,
|
|
const std::vector<double>& values) const override;
|
|
|
|
// Class-specific methods.
|
|
// Constructs a serializer object and writes the xmlNsPtr objects in
|
|
// namespaces_ to node_.
|
|
static std::unique_ptr<SerializerImpl> FromDataAndSerializeNamespaces(
|
|
const std::unordered_map<string, xmlNsPtr>& namespaces, xmlNodePtr node);
|
|
|
|
// Disallow copying.
|
|
SerializerImpl(const SerializerImpl&) = delete;
|
|
void operator=(const SerializerImpl&) = delete;
|
|
|
|
private:
|
|
// Writes the xmlNsPtr objects in namespaces_ to node_.
|
|
// Modifies namespaces_ by setting each xmlNsPtr's next pointer to the
|
|
// subsequent entry in the collection.
|
|
bool SerializeNamespaces();
|
|
|
|
xmlNodePtr node_;
|
|
std::unordered_map<string, xmlNsPtr> namespaces_;
|
|
};
|
|
|
|
} // namespace xml
|
|
} // namespace xmpmeta
|
|
} // namespace dynamic_depth
|
|
|
|
#endif // DYNAMIC_DEPTH_INTERNAL_XMPMETA_XML_SERIALIZER_IMPL_H_ // NOLINT
|