From 424e315dfa9a78aebf0653c95f83fe6ed452dd8e Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 2 May 2017 21:26:58 +0300 Subject: Add hxx extension for headers and libstud prefix for library dir --- libstudxml/serializer.cxx | 325 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 libstudxml/serializer.cxx (limited to 'libstudxml/serializer.cxx') diff --git a/libstudxml/serializer.cxx b/libstudxml/serializer.cxx new file mode 100644 index 0000000..1a01d86 --- /dev/null +++ b/libstudxml/serializer.cxx @@ -0,0 +1,325 @@ +// file : libstudxml/serializer.cxx +// copyright : Copyright (c) 2013-2017 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include // std::bad_alloc +#include // std::strlen + +#include + +using namespace std; + +namespace xml +{ + // serialization + // + void serialization:: + init () + { + if (!name_.empty ()) + { + what_ += name_; + what_ += ": "; + } + + what_ += "error: "; + what_ += description_; + } + + // serializer + // + extern "C" genxStatus + genx_write (void* p, constUtf8 us) + { + // It would have been easier to throw the exception directly, + // however, the Genx code is most likely not exception safe. + // + ostream* os (static_cast (p)); + const char* s (reinterpret_cast (us)); + os->write (s, static_cast (strlen (s))); + return os->good () ? GENX_SUCCESS : GENX_IO_ERROR; + } + + extern "C" genxStatus + genx_write_bound (void* p, constUtf8 start, constUtf8 end) + { + ostream* os (static_cast (p)); + const char* s (reinterpret_cast (start)); + streamsize n (static_cast (end - start)); + os->write (s, n); + return os->good () ? GENX_SUCCESS : GENX_IO_ERROR; + } + + extern "C" genxStatus + genx_flush (void* p) + { + ostream* os (static_cast (p)); + os->flush (); + return os->good () ? GENX_SUCCESS : GENX_IO_ERROR; + } + + serializer:: + ~serializer () + { + if (s_ != 0) + genxDispose (s_); + } + + serializer:: + serializer (ostream& os, const string& oname, unsigned short ind) + : os_ (os), os_state_ (os.exceptions ()), oname_ (oname), depth_ (0) + { + // Temporarily disable exceptions on the stream. + // + os_.exceptions (ostream::goodbit); + + // Allocate the serializer. Make sure nothing else can throw after + // this call since otherwise we will leak it. + // + s_ = genxNew (0, 0, 0); + + if (s_ == 0) + throw bad_alloc (); + + genxSetUserData (s_, &os_); + + if (ind != 0) + genxSetPrettyPrint (s_, ind); + + sender_.send = &genx_write; + sender_.sendBounded = &genx_write_bound; + sender_.flush = &genx_flush; + + if (genxStatus e = genxStartDocSender (s_, &sender_)) + { + string m (genxGetErrorMessage (s_, e)); + genxDispose (s_); + throw serialization (oname, m); + } + } + + void serializer:: + handle_error (genxStatus e) const + { + switch (e) + { + case GENX_ALLOC_FAILED: + throw bad_alloc (); + case GENX_IO_ERROR: + // Restoring the original exception state should trigger the + // exception. If it doesn't (e.g., because the user didn't + // configure the stream to throw), then fall back to the + // serialiation exception. + // + os_.exceptions (os_state_); + // Fall through. + default: + throw serialization (oname_, genxGetErrorMessage (s_, e)); + } + } + + void serializer:: + start_element (const string& ns, const string& name) + { + if (genxStatus e = genxStartElementLiteral ( + s_, + reinterpret_cast (ns.empty () ? 0 : ns.c_str ()), + reinterpret_cast (name.c_str ()))) + handle_error (e); + + depth_++; + } + + void serializer:: + end_element () + { + if (genxStatus e = genxEndElement (s_)) + handle_error (e); + + // Call EndDocument() if we are past the root element. + // + if (--depth_ == 0) + { + if (genxStatus e = genxEndDocument (s_)) + handle_error (e); + + // Also restore the original exception state on the stream. + // + os_.exceptions (os_state_); + } + } + + void serializer:: + end_element (const string& ns, const string& name) + { + constUtf8 cns, cn; + genxStatus e; + if ((e = genxGetCurrentElement (s_, &cns, &cn)) || + reinterpret_cast (cn) != name || + (cns == 0 ? !ns.empty () : reinterpret_cast (cns) != ns)) + { + handle_error (e != GENX_SUCCESS ? e : GENX_SEQUENCE_ERROR); + } + + end_element (); + } + + void serializer:: + element (const string& ns, const string& n, const string& v) + { + start_element (ns, n); + element (v); + } + + void serializer:: + start_attribute (const string& ns, const string& name) + { + if (genxStatus e = genxStartAttributeLiteral ( + s_, + reinterpret_cast (ns.empty () ? 0 : ns.c_str ()), + reinterpret_cast (name.c_str ()))) + handle_error (e); + } + + void serializer:: + end_attribute () + { + if (genxStatus e = genxEndAttribute (s_)) + handle_error (e); + } + + void serializer:: + end_attribute (const string& ns, const string& name) + { + constUtf8 cns, cn; + genxStatus e; + if ((e = genxGetCurrentAttribute (s_, &cns, &cn)) || + reinterpret_cast (cn) != name || + (cns == 0 ? !ns.empty () : reinterpret_cast (cns) != ns)) + { + handle_error (e != GENX_SUCCESS ? e : GENX_SEQUENCE_ERROR); + } + + end_attribute (); + } + + void serializer:: + attribute (const string& ns, + const string& name, + const string& value) + { + if (genxStatus e = genxAddAttributeLiteral ( + s_, + reinterpret_cast (ns.empty () ? 0 : ns.c_str ()), + reinterpret_cast (name.c_str ()), + reinterpret_cast (value.c_str ()))) + handle_error (e); + } + + void serializer:: + characters (const string& value) + { + if (genxStatus e = genxAddCountedText ( + s_, + reinterpret_cast (value.c_str ()), value.size ())) + handle_error (e); + } + + void serializer:: + namespace_decl (const string& ns, const string& p) + { + if (genxStatus e = ns.empty () && p.empty () + ? genxUnsetDefaultNamespace (s_) + : genxAddNamespaceLiteral ( + s_, + reinterpret_cast (ns.c_str ()), + reinterpret_cast (p.c_str ()))) + handle_error (e); + } + + void serializer:: + xml_decl (const string& ver, const string& enc, const string& stl) + { + if (genxStatus e = genxXmlDeclaration ( + s_, + reinterpret_cast (ver.c_str ()), + (enc.empty () ? 0 : reinterpret_cast (enc.c_str ())), + (stl.empty () ? 0 : reinterpret_cast (stl.c_str ())))) + handle_error (e); + } + + void serializer:: + doctype_decl (const string& re, + const string& pi, + const string& si, + const string& is) + { + if (genxStatus e = genxDoctypeDeclaration ( + s_, + reinterpret_cast (re.c_str ()), + (pi.empty () ? 0 : reinterpret_cast (pi.c_str ())), + (si.empty () ? 0 : reinterpret_cast (si.c_str ())), + (is.empty () ? 0 : reinterpret_cast (is.c_str ())))) + handle_error (e); + } + + bool serializer:: + lookup_namespace_prefix (const string& ns, string& p) const + { + // Currently Genx will create a namespace mapping if one doesn't + // already exist. + // + genxStatus e; + genxNamespace gns ( + genxDeclareNamespace ( + s_, reinterpret_cast (ns.c_str ()), 0, &e)); + + if (e != GENX_SUCCESS) + handle_error (e); + + p = reinterpret_cast (genxGetNamespacePrefix (gns)); + return true; + } + + qname serializer:: + current_element () const + { + constUtf8 ns, n; + if (genxStatus e = genxGetCurrentElement (s_, &ns, &n)) + handle_error (e); + + return qname (ns != 0 ? reinterpret_cast (ns) : "", + reinterpret_cast (n)); + } + + qname serializer:: + current_attribute () const + { + constUtf8 ns, n; + if (genxStatus e = genxGetCurrentAttribute (s_, &ns, &n)) + handle_error (e); + + return qname (ns != 0 ? reinterpret_cast (ns) : "", + reinterpret_cast (n)); + } + + void serializer:: + suspend_indentation () + { + if (genxStatus e = genxSuspendPrettyPrint (s_)) + handle_error (e); + } + + void serializer:: + resume_indentation () + { + if (genxStatus e = genxResumePrettyPrint (s_)) + handle_error (e); + } + + size_t serializer:: + indentation_suspended () const + { + return static_cast (genxPrettyPrintSuspended (s_)); + } +} -- cgit v1.1