diff options
Diffstat (limited to 'examples/cxx/hybrid/binary')
27 files changed, 2475 insertions, 0 deletions
diff --git a/examples/cxx/hybrid/binary/README b/examples/cxx/hybrid/binary/README new file mode 100644 index 0000000..73e3491 --- /dev/null +++ b/examples/cxx/hybrid/binary/README @@ -0,0 +1,16 @@ +This directory contains a number of examples that show how to serialize +the object model into a number of predefined and custom binary formats. +The following list gives an overview of each example: + +cdr + Shows how to save/load the object model to/from CDR (Common Data + Representation) binary format using ACE CDR streams. + +xdr + Shows how to save/load the object model to/from XDR (eXternal Data + Representation) binary format using the XDR API provided as part of + Sun RPC. + +custom + Shows how to save/load the C++/Hybrid object model to/from a custom + format using the raw binary representation as an example. diff --git a/examples/cxx/hybrid/binary/cdr/README b/examples/cxx/hybrid/binary/cdr/README new file mode 100644 index 0000000..52045f0 --- /dev/null +++ b/examples/cxx/hybrid/binary/cdr/README @@ -0,0 +1,51 @@ +This example shows how to save/load the C++/Hybrid object model to/from +CDR (Common Data Representation) binary format using ACE CDR streams. +You will need the ACE library installed in order to build and run this +example: + +http://www.cs.wustl.edu/~schmidt/ACE.html + +The example consists of the following files: + +library.xsd + XML Schema which describes a library of books. + +library.xml + Sample XML instance document. + +library.hxx +library.cxx + +library-pskel.hxx +library-pskel.cxx +library-pimpl.hxx +library-pimpl.cxx + +library-pskel.hxx +library-pskel.cxx +library-pimpl.hxx +library-pimpl.cxx + Object model (the first pair of files), parser skeletons (the + second pair), parser implementations (the third pair), serializer + skeletons (the fourth pair), and serializer implementations (the + fifth pair). These files are generated by the XSD/e compiler from + library.xsd. The --generate-parser, --generate-serializer, and + --generate-aggregate options were used to request the generation + of the parsing and serialization code. The --generate-insertion and + --generate-extraction options were used to generate the insertion + and extraction operations for the CDR streams. + +driver.cxx + Driver for the example. It first calls the parser that constructs + the object model from the input XML file. It then saves the object + model to the CDR representation and loads it back. Finally, the + driver calls the serializer to serialize the loaded object model + back to XML. + +To run the example on the sample XML instance document simply execute: + +$ ./driver library.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver <library.xml diff --git a/examples/cxx/hybrid/binary/cdr/driver.cxx b/examples/cxx/hybrid/binary/cdr/driver.cxx new file mode 100644 index 0000000..18848eb --- /dev/null +++ b/examples/cxx/hybrid/binary/cdr/driver.cxx @@ -0,0 +1,128 @@ +// file : examples/cxx/hybrid/binary/cdr/driver.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include <string.h> // memcpy + +#include <memory> // std::auto_ptr +#include <iostream> + +#include <ace/Log_Msg.h> // ACE_HEX_DUMP +#include <ace/CDR_Stream.h> + +#include "library.hxx" +#include "library-pimpl.hxx" +#include "library-simpl.hxx" + +using std::cerr; +using std::endl; + +int +main (int argc, char* argv[]) +{ + const char* input; + + if (argc < 2) + { + input = "STDIN"; + cerr << "XML file not specified, reading from STDIN" << endl; + } + else + input = argv[1]; + + try + { + using namespace library; + + // Parse. + // + catalog_paggr catalog_p; + + xml_schema::document_pimpl doc_p ( + catalog_p.root_parser (), + catalog_p.root_namespace (), + catalog_p.root_name ()); + + catalog_p.pre (); + + if (argc < 2) + doc_p.parse (std::cin); + else + doc_p.parse (argv[1]); + + std::auto_ptr<catalog> c (catalog_p.post ()); + + // Save the object model to a CDR stream. + // + ACE_OutputCDR ace_ocdr; + xml_schema::ocdrstream ocdr (ace_ocdr); + ocdr << *c; + + // Print the binary representation and at the same time save + // it into a continuous buffer. + // + cerr << "binary representation size: " << ace_ocdr.total_length () << endl + << endl; + + xml_schema::buffer buf (ace_ocdr.total_length ()); + char* data = buf.data (); + + for (const ACE_Message_Block* mb = ace_ocdr.begin (); + mb != 0; + mb = mb->cont ()) + { + memcpy (data, mb->rd_ptr (), mb->length ()); + data += mb->length (); + + ACE_HEX_DUMP ((LM_DEBUG, mb->rd_ptr (), mb->length ())); + } + + // Load the object model from a CDR stream. Note that ACE_InputCDR + // expects the buffer to be properly aligned. Since our buffer is + // dynamically allocated, its alignment should be good enough. + // + ACE_InputCDR ace_icdr (buf.data (), buf.size ()); + xml_schema::icdrstream icdr (ace_icdr); + std::auto_ptr<catalog> copy (new catalog); + icdr >> *copy; + + // Serialize the copy back to XML. + // + catalog_saggr catalog_s; + + xml_schema::document_simpl doc_s ( + catalog_s.root_serializer (), + catalog_s.root_namespace (), + catalog_s.root_name ()); + + doc_s.add_prefix ("lib", "http://www.codesynthesis.com/library"); + doc_s.add_schema ("http://www.codesynthesis.com/library", "library.xsd"); + + catalog_s.pre (*c); + doc_s.serialize (std::cout); + catalog_s.post (); + } + catch (const xml_schema::cdr_exception&) + { + cerr << "CDR operation failed" << endl; + return 1; + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const xml_schema::serializer_exception& e) + { + cerr << "error: " << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read/write failure" << endl; + return 1; + } + + return 0; +} diff --git a/examples/cxx/hybrid/binary/cdr/library.xml b/examples/cxx/hybrid/binary/cdr/library.xml new file mode 100644 index 0000000..6bfb4d8 --- /dev/null +++ b/examples/cxx/hybrid/binary/cdr/library.xml @@ -0,0 +1,53 @@ +<?xml version="1.0"?> + +<!-- + +file : examples/cxx/hybrid/binary/cdr/library.xml +author : Boris Kolpackov <boris@codesynthesis.com> +copyright : not copyrighted - public domain + +--> + +<lib:catalog xmlns:lib="http://www.codesynthesis.com/library" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.codesynthesis.com/library library.xsd"> + + <book available="false"> + <isbn>0679760806</isbn> + <title>The Master and Margarita</title> + <genre>fiction</genre> + + <author> + <name>Mikhail Bulgakov</name> + <born>1891-05-15</born> + <died>1940-03-10</died> + </author> + </book> + + + <book available="true" > + <isbn>0679600841</isbn> + <title>War and Peace</title> + <genre>history</genre> + + <author> + <name>Leo Tolstoy</name> + <born>1828-09-09</born> + <died>1910-11-20</died> + </author> + </book> + + + <book available="false"> + <isbn>0679420290</isbn> + <title>Crime and Punishment</title> + <genre>philosophy</genre> + + <author> + <name>Fyodor Dostoevsky</name> + <born>1821-11-11</born> + <died>1881-02-09</died> + </author> + </book> + +</lib:catalog> diff --git a/examples/cxx/hybrid/binary/cdr/library.xsd b/examples/cxx/hybrid/binary/cdr/library.xsd new file mode 100644 index 0000000..0b0d9d1 --- /dev/null +++ b/examples/cxx/hybrid/binary/cdr/library.xsd @@ -0,0 +1,69 @@ +<?xml version="1.0"?> + +<!-- + +file : examples/cxx/hybrid/binary/cdr/library.xsd +author : Boris Kolpackov <boris@codesynthesis.com> +copyright : not copyrighted - public domain + +--> + +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:lib="http://www.codesynthesis.com/library" + targetNamespace="http://www.codesynthesis.com/library"> + + <xsd:simpleType name="isbn"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + + + <xsd:complexType name="title"> + <xsd:simpleContent> + <xsd:extension base="xsd:string"> + <xsd:attribute name="lang" type="xsd:string"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + + + <xsd:simpleType name="genre"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="romance"/> + <xsd:enumeration value="fiction"/> + <xsd:enumeration value="horror"/> + <xsd:enumeration value="history"/> + <xsd:enumeration value="philosophy"/> + </xsd:restriction> + </xsd:simpleType> + + + <xsd:complexType name="author"> + <xsd:sequence> + <xsd:element name="name" type="xsd:string"/> + <xsd:element name="born" type="xsd:date"/> + <xsd:element name="died" type="xsd:date" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + + + <xsd:complexType name="book"> + <xsd:sequence> + <xsd:element name="isbn" type="lib:isbn"/> + <xsd:element name="title" type="lib:title"/> + <xsd:element name="genre" type="lib:genre"/> + <xsd:element name="author" type="lib:author" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="available" type="xsd:boolean" use="required"/> + </xsd:complexType> + + + <xsd:complexType name="catalog"> + <xsd:sequence> + <xsd:element name="book" type="lib:book" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + + + <xsd:element name="catalog" type="lib:catalog"/> + +</xsd:schema> diff --git a/examples/cxx/hybrid/binary/cdr/makefile b/examples/cxx/hybrid/binary/cdr/makefile new file mode 100644 index 0000000..eba1c77 --- /dev/null +++ b/examples/cxx/hybrid/binary/cdr/makefile @@ -0,0 +1,112 @@ +# file : examples/cxx/hybrid/binary/cdr/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../../build/bootstrap.make + +xsd := library.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,\ +$(cxx:.cxx=.o) \ +$(xsd:.xsd=.o) \ +$(xsd:.xsd=-pskel.o) \ +$(xsd:.xsd=-pimpl.o) \ +$(xsd:.xsd=-sskel.o) \ +$(xsd:.xsd=-simpl.o)) + +dep := $(obj:.o=.o.d) + +xsde.l := $(out_root)/libxsde/xsde/xsde.l +xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options + +driver := $(out_base)/driver +dist := $(out_base)/.dist +dist-win := $(out_base)/.dist-win +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.cxx) \ + $(xsd:.xsd=-pskel.hxx) $(xsd:.xsd=-pskel.cxx) \ + $(xsd:.xsd=-pimpl.hxx) $(xsd:.xsd=-pimpl.cxx) \ + $(xsd:.xsd=-sskel.hxx) $(xsd:.xsd=-sskel.cxx) \ + $(xsd:.xsd=-simpl.hxx) $(xsd:.xsd=-simpl.cxx) + +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-serializer \ +--generate-aggregate --generate-insertion CDR --generate-extraction CDR + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Dist. +# +dist-common := $(out_base)/.dist-common + +.PHONY: $(dist) $(dist-win) $(dist-common) + +$(dist) $(dist-win) $(dist-common): path := $(subst $(src_root)/,,$(src_base)) + +$(dist-common): + $(call install-data,$(src_base)/driver.cxx,$(dist_prefix)/$(path)/driver.cxx) + $(call install-data,$(src_base)/library.xsd,$(dist_prefix)/$(path)/library.xsd) + $(call install-data,$(src_base)/library.xml,$(dist_prefix)/$(path)/library.xml) + +$(dist): $(dist-common) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README) + +$(dist-win): $(dist-common) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README.txt) + $(call message,,unix2dos $(dist_prefix)/$(path)/README.txt) + + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean)) + + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(gen): | $(out_base)/.gitignore +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(genf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/install.make) +$(call include,$(scf_root)/xsde/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/hybrid/binary/custom/README b/examples/cxx/hybrid/binary/custom/README new file mode 100644 index 0000000..b7475d8 --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/README @@ -0,0 +1,77 @@ +This example shows how to save/load the C++/Hybrid object model to/from +a custom format using the raw binary representation as an example. Note +that if you would like to use this format in your applications, make sure +that all the targets use exactly the same base type sizes (e.g., int, long, +float, double, size_t, etc.) and byte order. + +The example consists of the following files: + +library.xsd + XML Schema which describes a library of books. + +library.xml + Sample XML instance document. + +xml-schema.hxx +xml-schema-pskel.hxx +xml-schema-sskel.hxx + Base object model types (the first file), parser skeletons (the second + file), and serializer skeletons (the third file) for the XML Schema + built-in types. These header files are generated by the XSD/e compiler + using the --generate-xml-schema option. The --generate-parser and + --generate-serializer options were also specified. + +irawstream.hxx +irawstream.ixx +irawstream.txx +irawstream.cxx + +orawstream.hxx +orawstream.ixx +orawstream.txx +orawstream.cxx + Implementation of the raw binary representation streams. The header + files include xml-schema.hxx to gain access to the base object model + types. You can use this implementation as a base for your custom + format. + +library.hxx +library.cxx + +library-pskel.hxx +library-pskel.cxx +library-pimpl.hxx +library-pimpl.cxx + +library-pskel.hxx +library-pskel.cxx +library-pimpl.hxx +library-pimpl.cxx + Object model (the first pair of files), parser skeletons (the second + pair), parser implementations (the third pair), serializer skeletons + (the fourth pair), and serializer implementations (the fifth pair). + These files are generated by the XSD/e compiler from library.xsd. The + --generate-parser, --generate-serializer, and --generate-aggregate + options were used to request the generation of the parsing and + serialization code. The --generate-insertion and --generate-extraction + options were used to generate the insertion and extraction operations + for the orawstream and irawstream, respectively. The --hxx-prologue + option was used to include the orawstream.hxx and irawstream.hxx + header files at the beginning of library.hxx. Finally, the + --extern-xml-schema option was used to include xml-schema* files + instead of generating the same code directly. + +driver.cxx + Driver for the example. It first calls the parser that constructs + the object model from the input XML file. It then saves the object + model to the raw binary representation and loads it back. Finally, + the driver calls the serializer to serialize the loaded object model + back to XML. + +To run the example on the sample XML instance document simply execute: + +$ ./driver library.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver <library.xml diff --git a/examples/cxx/hybrid/binary/custom/driver.cxx b/examples/cxx/hybrid/binary/custom/driver.cxx new file mode 100644 index 0000000..e453a37 --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/driver.cxx @@ -0,0 +1,107 @@ +// file : examples/cxx/hybrid/binary/custom/driver.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include <memory> // std::auto_ptr +#include <iostream> + +#include "orawstream.hxx" +#include "irawstream.hxx" + +#include "library.hxx" +#include "library-pimpl.hxx" +#include "library-simpl.hxx" + +using std::cerr; +using std::endl; + +int +main (int argc, char* argv[]) +{ + const char* input; + + if (argc < 2) + { + input = "STDIN"; + cerr << "XML file not specified, reading from STDIN" << endl; + } + else + input = argv[1]; + + try + { + using namespace library; + + // Parse. + // + catalog_paggr catalog_p; + + xml_schema::document_pimpl doc_p ( + catalog_p.root_parser (), + catalog_p.root_namespace (), + catalog_p.root_name ()); + + catalog_p.pre (); + + if (argc < 2) + doc_p.parse (std::cin); + else + doc_p.parse (argv[1]); + + std::auto_ptr<catalog> c (catalog_p.post ()); + + // Save the object model to a RAW stream. + // + xml_schema::buffer buf; + orawstream oraw (buf); + oraw << *c; + + cerr << "binary representation size: " << buf.size () << endl + << endl; + + // Load the object model from a RAW stream. + // + irawstream iraw (buf); + std::auto_ptr<catalog> copy (new catalog); + iraw >> *copy; + + // Serialize the copy back to XML. + // + catalog_saggr catalog_s; + + xml_schema::document_simpl doc_s ( + catalog_s.root_serializer (), + catalog_s.root_namespace (), + catalog_s.root_name ()); + + doc_s.add_prefix ("lib", "http://www.codesynthesis.com/library"); + doc_s.add_schema ("http://www.codesynthesis.com/library", "library.xsd"); + + catalog_s.pre (*c); + doc_s.serialize (std::cout); + catalog_s.post (); + } + catch (const raw_exception&) + { + cerr << "RAW stream operation failed" << endl; + return 1; + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const xml_schema::serializer_exception& e) + { + cerr << "error: " << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read/write failure" << endl; + return 1; + } + + return 0; +} diff --git a/examples/cxx/hybrid/binary/custom/exceptions.cxx b/examples/cxx/hybrid/binary/custom/exceptions.cxx new file mode 100644 index 0000000..0ad8c4b --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/exceptions.cxx @@ -0,0 +1,11 @@ +// file : examples/cxx/hybrid/binary/custom/exceptions.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include "exceptions.hxx" + +const char* raw_exception:: +what () const throw () +{ + return "RAW stream operation failed"; +} diff --git a/examples/cxx/hybrid/binary/custom/exceptions.hxx b/examples/cxx/hybrid/binary/custom/exceptions.hxx new file mode 100644 index 0000000..0111799 --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/exceptions.hxx @@ -0,0 +1,16 @@ +// file : examples/cxx/hybrid/binary/custom/exceptions.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#ifndef EXCEPTIONS_HXX +#define EXCEPTIONS_HXX + +#include <exception> // std::exception + +struct raw_exception: std::exception +{ + virtual const char* + what () const throw (); +}; + +#endif // EXCEPTIONS_HXX diff --git a/examples/cxx/hybrid/binary/custom/irawstream.cxx b/examples/cxx/hybrid/binary/custom/irawstream.cxx new file mode 100644 index 0000000..d3d6aae --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/irawstream.cxx @@ -0,0 +1,296 @@ +// file : examples/cxx/hybrid/binary/custom/irawstream.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include <string.h> // memcpy + +#include "irawstream.hxx" + +using namespace xml_schema; + +const char* irawstream:: +align (size_t a, size_t n) +{ + size_t r = pos_ % a; + + if (r) + n += a - r; + + if (buf_.size () - pos_ < n) + throw raw_exception (); + + const char* p = buf_.data () + pos_; + + if (r) + p += a - r; + + pos_ += n; + return p; +} + +void irawstream:: +operator>> (std::string& x) +{ + size_t n = *reinterpret_cast<const size_t*> ( + align (sizeof (size_t), sizeof (size_t))); + + x.clear (); + + if (n != 0) + { + x.resize (n); + memcpy (const_cast<char*> (x.c_str ()), align (1, n), n); + } +} + +void irawstream:: +operator>> (buffer& x) +{ + size_t n = *reinterpret_cast<const size_t*> ( + align (sizeof (size_t), sizeof (size_t))); + + x.size (n); + + if (n != 0) + memcpy (x.data (), align (1, n), n); +} + +void +operator>> (irawstream& s, str_seq& x) +{ + size_t n; + irawstream::as_size as_size (n); + s >> as_size; + + x.clear (); + + if (n > 0) + { + x.reserve (n); + std::string i; + + while (n--) + { + s >> i; + x.push_back (i); + } + } +} + +void +operator>> (irawstream& s, qname& x) +{ + std::string p, n; + + s >> p; + s >> n; + + x.prefix (p); + x.name (n); +} + +void +operator>> (irawstream& s, time_zone& x) +{ + short h, m; + s >> h; + s >> m; + + x.zone_hours (h); + x.zone_minutes (m); +} + +void +operator>> (irawstream& s, date& x) +{ + int y; + unsigned short m, d; + bool zp; + + s >> y; + s >> m; + s >> d; + s >> zp; + + x.year (y); + x.month (m); + x.day (d); + + if (zp) + { + time_zone& z = x; + s >> z; + } +} + +void +operator>> (irawstream& s, date_time& x) +{ + int y; + unsigned short m, d, h, mi; + double se; + bool zp; + + s >> y; + s >> m; + s >> d; + s >> h; + s >> mi; + s >> se; + s >> zp; + + x.year (y); + x.month (m); + x.day (d); + x.hours (h); + x.minutes (mi); + x.seconds (se); + + if (zp) + { + time_zone& z = x; + s >> z; + } +} + +void +operator>> (irawstream& s, duration& x) +{ + bool n; + unsigned int y, m, d, h, mi; + double se; + + s >> n; + s >> y; + s >> m; + s >> d; + s >> h; + s >> mi; + s >> se; + + x.negative (n); + x.years (y); + x.months (m); + x.days (d); + x.hours (h); + x.minutes (mi); + x.seconds (se); +} + +void +operator>> (irawstream& s, gday& x) +{ + unsigned short d; + bool zp; + + s >> d; + s >> zp; + + x.day (d); + + if (zp) + { + time_zone& z = x; + s >> z; + } +} + +void +operator>> (irawstream& s, gmonth& x) +{ + unsigned short m; + bool zp; + + s >> m; + s >> zp; + + x.month (m); + + if (zp) + { + time_zone& z = x; + s >> z; + } +} + +void +operator>> (irawstream& s, gmonth_day& x) +{ + unsigned short d, m; + bool zp; + + s >> d; + s >> m; + s >> zp; + + x.day (d); + x.month (m); + + if (zp) + { + time_zone& z = x; + s >> z; + } +} + +void +operator>> (irawstream& s, gyear& x) +{ + int y; + bool zp; + + s >> y; + s >> zp; + + x.year (y); + + if (zp) + { + time_zone& z = x; + s >> z; + } +} + +void +operator>> (irawstream& s, gyear_month& x) +{ + int y; + unsigned short m; + bool zp; + + s >> y; + s >> m; + s >> zp; + + x.year (y); + x.month (m); + + if (zp) + { + time_zone& z = x; + s >> z; + } +} + +void +operator>> (irawstream& s, xml_schema::time& x) +{ + unsigned short h, m; + double se; + bool zp; + + s >> h; + s >> m; + s >> se; + s >> zp; + + x.hours (h); + x.minutes (m); + x.seconds (se); + + if (zp) + { + time_zone& z = x; + s >> z; + } +} diff --git a/examples/cxx/hybrid/binary/custom/irawstream.hxx b/examples/cxx/hybrid/binary/custom/irawstream.hxx new file mode 100644 index 0000000..94d2382 --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/irawstream.hxx @@ -0,0 +1,92 @@ +// file : examples/cxx/hybrid/binary/custom/irawstream.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#ifndef IRAWSTREAM_HXX +#define IRAWSTREAM_HXX + +#include <stddef.h> // size_t + +#include <string> + +#include "exceptions.hxx" +#include "xml-schema.hxx" + +class irawstream +{ +public: + explicit + irawstream (const xml_schema::buffer&, size_t start = 0); + +public: + struct as_size + { + explicit as_size (size_t& s) : s_ (s) {} + size_t& s_; + }; + +public: + void operator>> (bool&); + void operator>> (signed char&); + void operator>> (unsigned char&); + void operator>> (short&); + void operator>> (unsigned short&); + void operator>> (int&); + void operator>> (unsigned int&); + void operator>> (long&); + void operator>> (unsigned long&); + +#ifdef XSDE_LONGLONG + void operator>> (long long&); + void operator>> (unsigned long long&); +#endif + + void operator>> (as_size&); + void operator>> (float&); + void operator>> (double&); + + void operator>> (std::string&); + void operator>> (xml_schema::buffer&); + +private: + irawstream (const irawstream&); + irawstream& operator= (const irawstream&); + +public: + const char* + align (size_t alignment, size_t size); + +private: + const xml_schema::buffer& buf_; + size_t pos_; +}; + +void operator>> (irawstream&, xml_schema::any_type&); +void operator>> (irawstream&, xml_schema::any_simple_type&); +void operator>> (irawstream&, xml_schema::qname&); +void operator>> (irawstream&, xml_schema::time_zone&); +void operator>> (irawstream&, xml_schema::date&); +void operator>> (irawstream&, xml_schema::date_time&); +void operator>> (irawstream&, xml_schema::duration&); +void operator>> (irawstream&, xml_schema::gday&); +void operator>> (irawstream&, xml_schema::gmonth&); +void operator>> (irawstream&, xml_schema::gmonth_day&); +void operator>> (irawstream&, xml_schema::gyear&); +void operator>> (irawstream&, xml_schema::gyear_month&); +void operator>> (irawstream&, xml_schema::time&); + +void operator>> (irawstream&, xml_schema::str_seq&); + +template <typename T> +void operator>> (irawstream&, xml_schema::pod_seq<T>&); + +template <typename T> +void operator>> (irawstream&, xml_schema::fix_seq<T>&); + +template <typename T> +void operator>> (irawstream&, xml_schema::var_seq<T>&); + +#include "irawstream.ixx" +#include "irawstream.txx" + +#endif // IRAWSTREAM_HXX diff --git a/examples/cxx/hybrid/binary/custom/irawstream.ixx b/examples/cxx/hybrid/binary/custom/irawstream.ixx new file mode 100644 index 0000000..bc9ff9a --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/irawstream.ixx @@ -0,0 +1,110 @@ +// file : examples/cxx/hybrid/binary/custom/irawstream.ixx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +inline irawstream:: +irawstream (const xml_schema::buffer& buf, size_t start) + : buf_ (buf), pos_ (start) +{ +} + +inline void irawstream:: +operator>> (bool& x) +{ + x = *align (1, 1); +} + +inline void irawstream:: +operator>> (signed char& x) +{ + x = *reinterpret_cast<const signed char*> (align (1, 1)); +} + +inline void irawstream:: +operator>> (unsigned char& x) +{ + x = *reinterpret_cast<const unsigned char*> (align (1, 1)); +} + +inline void irawstream:: +operator>> (short& x) +{ + x = *reinterpret_cast<const short*> (align (2, 2)); +} + +inline void irawstream:: +operator>> (unsigned short& x) +{ + x = *reinterpret_cast<const unsigned short*> (align (2, 2)); +} + +inline void irawstream:: +operator>> (int& x) +{ + x = *reinterpret_cast<const int*> (align (4, 4)); +} + +inline void irawstream:: +operator>> (unsigned int& x) +{ + x = *reinterpret_cast<const unsigned int*> (align (4, 4)); +} + +inline void irawstream:: +operator>> (long& x) +{ + x = *reinterpret_cast<const long*> ( + align (sizeof (long), sizeof (long))); +} + +inline void irawstream:: +operator>> (unsigned long& x) +{ + x = *reinterpret_cast<const unsigned long*> ( + align (sizeof (unsigned long), sizeof (unsigned long))); +} + +#ifdef XSDE_LONGLONG +inline void irawstream:: +operator>> (long long& x) +{ + x = *reinterpret_cast<const long long*> (align (8, 8)); +} + +inline void irawstream:: +operator>> (unsigned long long& x) +{ + x = *reinterpret_cast<const unsigned long long*> (align (8, 8)); +} +#endif + +inline void irawstream:: +operator>> (as_size& x) +{ + x.s_ = *reinterpret_cast<const size_t*> ( + align (sizeof (size_t), sizeof (size_t))); +} + +inline void irawstream:: +operator>> (float& x) +{ + x = *reinterpret_cast<const float*> ( + align (sizeof (float), sizeof (float))); +} + +inline void irawstream:: +operator>> (double& x) +{ + x = *reinterpret_cast<const double*> ( + align (sizeof (double), sizeof (double))); +} + +inline void +operator>> (irawstream&, xml_schema::any_type&) +{ +} + +inline void +operator>> (irawstream&, xml_schema::any_simple_type&) +{ +} diff --git a/examples/cxx/hybrid/binary/custom/irawstream.txx b/examples/cxx/hybrid/binary/custom/irawstream.txx new file mode 100644 index 0000000..2d4965e --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/irawstream.txx @@ -0,0 +1,72 @@ +// file : examples/cxx/hybrid/binary/custom/irawostream.txx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include <string.h> // memcpy + +template <typename T> +void +operator>> (irawstream& s, xml_schema::pod_seq<T>& x) +{ + size_t n; + irawstream::as_size as_size (n); + s >> as_size; + + x.clear (); + + if (n > 0) + { + x.reserve (n); + size_t mn = sizeof (T) * n; + memcpy (x.data_, s.align (sizeof (T), mn), mn); + x.size_ = n; + } +} + +template <typename T> +void +operator>> (irawstream& s, xml_schema::fix_seq<T>& x) +{ + size_t n; + irawstream::as_size as_size (n); + s >> as_size; + + x.clear (); + + if (n > 0) + { + x.reserve (n); + + while (n--) + { + T i; + s >> i; + x.push_back (i); + } + } +} + +template <typename T> +void +operator>> (irawstream& s, xml_schema::var_seq<T>& x) +{ + size_t n; + irawstream::as_size as_size (n); + s >> as_size; + + x.clear (); + + if (n > 0) + { + x.reserve (n); + + while (n--) + { + T* p = new T; + typename xml_schema::var_seq<T>::guard g (p); + s >> *p; + g.release (); + x.push_back (p); + } + } +} diff --git a/examples/cxx/hybrid/binary/custom/library.xml b/examples/cxx/hybrid/binary/custom/library.xml new file mode 100644 index 0000000..e93bab4 --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/library.xml @@ -0,0 +1,53 @@ +<?xml version="1.0"?> + +<!-- + +file : examples/cxx/hybrid/binary/custom/library.xml +author : Boris Kolpackov <boris@codesynthesis.com> +copyright : not copyrighted - public domain + +--> + +<lib:catalog xmlns:lib="http://www.codesynthesis.com/library" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.codesynthesis.com/library library.xsd"> + + <book available="false"> + <isbn>0679760806</isbn> + <title>The Master and Margarita</title> + <genre>fiction</genre> + + <author> + <name>Mikhail Bulgakov</name> + <born>1891-05-15</born> + <died>1940-03-10</died> + </author> + </book> + + + <book available="true" > + <isbn>0679600841</isbn> + <title>War and Peace</title> + <genre>history</genre> + + <author> + <name>Leo Tolstoy</name> + <born>1828-09-09</born> + <died>1910-11-20</died> + </author> + </book> + + + <book available="false"> + <isbn>0679420290</isbn> + <title>Crime and Punishment</title> + <genre>philosophy</genre> + + <author> + <name>Fyodor Dostoevsky</name> + <born>1821-11-11</born> + <died>1881-02-09</died> + </author> + </book> + +</lib:catalog> diff --git a/examples/cxx/hybrid/binary/custom/library.xsd b/examples/cxx/hybrid/binary/custom/library.xsd new file mode 100644 index 0000000..7b75c2d --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/library.xsd @@ -0,0 +1,69 @@ +<?xml version="1.0"?> + +<!-- + +file : examples/cxx/hybrid/binary/custom/library.xsd +author : Boris Kolpackov <boris@codesynthesis.com> +copyright : not copyrighted - public domain + +--> + +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:lib="http://www.codesynthesis.com/library" + targetNamespace="http://www.codesynthesis.com/library"> + + <xsd:simpleType name="isbn"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + + + <xsd:complexType name="title"> + <xsd:simpleContent> + <xsd:extension base="xsd:string"> + <xsd:attribute name="lang" type="xsd:string"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + + + <xsd:simpleType name="genre"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="romance"/> + <xsd:enumeration value="fiction"/> + <xsd:enumeration value="horror"/> + <xsd:enumeration value="history"/> + <xsd:enumeration value="philosophy"/> + </xsd:restriction> + </xsd:simpleType> + + + <xsd:complexType name="author"> + <xsd:sequence> + <xsd:element name="name" type="xsd:string"/> + <xsd:element name="born" type="xsd:date"/> + <xsd:element name="died" type="xsd:date" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + + + <xsd:complexType name="book"> + <xsd:sequence> + <xsd:element name="isbn" type="lib:isbn"/> + <xsd:element name="title" type="lib:title"/> + <xsd:element name="genre" type="lib:genre"/> + <xsd:element name="author" type="lib:author" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="available" type="xsd:boolean" use="required"/> + </xsd:complexType> + + + <xsd:complexType name="catalog"> + <xsd:sequence> + <xsd:element name="book" type="lib:book" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + + + <xsd:element name="catalog" type="lib:catalog"/> + +</xsd:schema> diff --git a/examples/cxx/hybrid/binary/custom/makefile b/examples/cxx/hybrid/binary/custom/makefile new file mode 100644 index 0000000..7ab91d0 --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/makefile @@ -0,0 +1,138 @@ +# file : examples/cxx/hybrid/binary/custom/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../../build/bootstrap.make + +xsd := library.xsd +cxx := driver.cxx exceptions.cxx orawstream.cxx irawstream.cxx + +obj := $(addprefix $(out_base)/,\ +$(cxx:.cxx=.o) \ +$(xsd:.xsd=.o) \ +$(xsd:.xsd=-pskel.o) \ +$(xsd:.xsd=-pimpl.o) \ +$(xsd:.xsd=-sskel.o) \ +$(xsd:.xsd=-simpl.o)) + +dep := $(obj:.o=.o.d) + +xsde.l := $(out_root)/libxsde/xsde/xsde.l +xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options + +driver := $(out_base)/driver +dist := $(out_base)/.dist +dist-win := $(out_base)/.dist-win +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.cxx) \ + $(xsd:.xsd=-pskel.hxx) $(xsd:.xsd=-pskel.cxx) \ + $(xsd:.xsd=-pimpl.hxx) $(xsd:.xsd=-pimpl.cxx) \ + $(xsd:.xsd=-sskel.hxx) $(xsd:.xsd=-sskel.cxx) \ + $(xsd:.xsd=-simpl.hxx) $(xsd:.xsd=-simpl.cxx) + +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-serializer \ +--generate-aggregate --extern-xml-schema xml-schema.xsd \ +--generate-insertion orawstream --hxx-prologue '\\\#include "orawstream.hxx"' \ +--generate-extraction irawstream --hxx-prologue '\\\#include "irawstream.hxx"' + +# Header files for XML Schema namespace. +# +$(out_base)/xml-schema%hxx \ +$(out_base)/xml-schema-pskel%hxx \ +$(out_base)/xml-schema-sskel%hxx: $(out_root)/xsde/xsde + $(call message,xsde $(src_base)/xml-schema.xsd,\ +$(out_root)/xsde/xsde cxx-hybrid --output-dir $(out_base) \ +--generate-xml-schema --generate-parser --generate-serializer xml-schema.xsd) + +genf += xml-schema.hxx xml-schema-pskel.hxx xml-schema-sskel.hxx + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Dist. +# +dist-common := $(out_base)/.dist-common + +.PHONY: $(dist) $(dist-win) $(dist-common) + +$(dist) $(dist-win) $(dist-common): path := $(subst $(src_root)/,,$(src_base)) + +$(dist-common): + $(call install-data,$(src_base)/driver.cxx,$(dist_prefix)/$(path)/driver.cxx) + $(call install-data,$(src_base)/exceptions.cxx,$(dist_prefix)/$(path)/exceptions.cxx) + $(call install-data,$(src_base)/exceptions.hxx,$(dist_prefix)/$(path)/exceptions.hxx) + $(call install-data,$(src_base)/orawstream.hxx,$(dist_prefix)/$(path)/orawstream.hxx) + $(call install-data,$(src_base)/orawstream.ixx,$(dist_prefix)/$(path)/orawstream.ixx) + $(call install-data,$(src_base)/orawstream.txx,$(dist_prefix)/$(path)/orawstream.txx) + $(call install-data,$(src_base)/orawstream.cxx,$(dist_prefix)/$(path)/orawstream.cxx) + $(call install-data,$(src_base)/irawstream.hxx,$(dist_prefix)/$(path)/irawstream.hxx) + $(call install-data,$(src_base)/irawstream.ixx,$(dist_prefix)/$(path)/irawstream.ixx) + $(call install-data,$(src_base)/irawstream.txx,$(dist_prefix)/$(path)/irawstream.txx) + $(call install-data,$(src_base)/irawstream.cxx,$(dist_prefix)/$(path)/irawstream.cxx) + $(call install-data,$(src_base)/library.xsd,$(dist_prefix)/$(path)/library.xsd) + $(call install-data,$(src_base)/library.xml,$(dist_prefix)/$(path)/library.xml) + +$(dist): $(dist-common) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README) + +$(dist-win): $(dist-common) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README.txt) + $(call message,,unix2dos $(dist_prefix)/$(path)/README.txt) + + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean)) + $(call message,rm $$1,rm -f $$1,$(out_base)/xml-schema.hxx) + $(call message,rm $$1,rm -f $$1,$(out_base)/xml-schema-pskel.hxx) + $(call message,rm $$1,rm -f $$1,$(out_base)/xml-schema-sskel.hxx) + + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(gen): | $(out_base)/.gitignore +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(genf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/install.make) +$(call include,$(scf_root)/xsde/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/hybrid/binary/custom/orawstream.cxx b/examples/cxx/hybrid/binary/custom/orawstream.cxx new file mode 100644 index 0000000..dc4b477 --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/orawstream.cxx @@ -0,0 +1,224 @@ +// file : examples/cxx/hybrid/binary/custom/orawstream.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include <string.h> // memcpy + +#include "orawstream.hxx" + +using namespace xml_schema; + +char* orawstream:: +align (size_t a, size_t n) +{ + size_t s = buf_.size (); + size_t c = buf_.capacity (); + size_t r = s % a; + + if (r) + n += a - r; + + if (c - s < n) + { + // Do exponential growth. + // + size_t nc = s + n; + c *= 2; + + if (nc < c) + nc = c; + + buf_.capacity (nc); + } + + char* p = buf_.data () + s; + + if (r) + p += a - r; + + buf_.size (s + n); + return p; +} + +void orawstream:: +operator<< (const std::string& x) +{ + size_t n = x.length (); + char* p = align (sizeof (size_t), sizeof (size_t) + n); + + *reinterpret_cast<size_t*> (p) = n; + p += sizeof (size_t); + memcpy (p, x.c_str (), n); +} + +void orawstream:: +operator<< (const buffer& x) +{ + size_t n = x.size (); + char* p = align (sizeof (size_t), sizeof (size_t) + n); + + *reinterpret_cast<size_t*> (p) = n; + p += sizeof (size_t); + memcpy (p, x.data (), n); +} + +void +operator<< (orawstream& s, const str_seq& x) +{ + s << orawstream::as_size (x.size ()); + + for (str_seq::const_iterator i = x.begin (); + i != x.end (); ++i) + { + s << *i; + } +} + +void +operator<< (orawstream& s, const qname& x) +{ + s << x.prefix (); + s << x.name (); +} + +void +operator<< (orawstream& s, const time_zone& x) +{ + s << x.zone_hours (); + s << x.zone_minutes (); +} + +void +operator<< (orawstream& s, const date& x) +{ + s << x.year (); + s << x.month (); + s << x.day (); + bool zp = x.zone_present (); + s << zp; + + if (zp) + { + const time_zone& z = x; + s << z; + } +} + +void +operator<< (orawstream& s, const date_time& x) +{ + s << x.year (); + s << x.month (); + s << x.day (); + s << x.hours (); + s << x.minutes (); + s << x.seconds (); + bool zp = x.zone_present (); + s << zp; + + if (zp) + { + const time_zone& z = x; + s << z; + } +} + +void +operator<< (orawstream& s, const duration& x) +{ + s << x.negative (); + s << x.years (); + s << x.months (); + s << x.days (); + s << x.hours (); + s << x.minutes (); + s << x.seconds (); +} + +void +operator<< (orawstream& s, const gday& x) +{ + s << x.day (); + bool zp = x.zone_present (); + s << zp; + + if (zp) + { + const time_zone& z = x; + s << z; + } +} + +void +operator<< (orawstream& s, const gmonth& x) +{ + s << x.month (); + bool zp = x.zone_present (); + s << zp; + + if (zp) + { + const time_zone& z = x; + s << z; + } +} + +void +operator<< (orawstream& s, const gmonth_day& x) +{ + s << x.month (); + s << x.day (); + bool zp = x.zone_present (); + s << zp; + + if (zp) + { + const time_zone& z = x; + s << z; + } +} + +void +operator<< (orawstream& s, const gyear& x) +{ + s << x.year (); + bool zp = x.zone_present (); + s << zp; + + if (zp) + { + const time_zone& z = x; + s << z; + } +} + +void +operator<< (orawstream& s, const gyear_month& x) +{ + s << x.year (); + s << x.month (); + bool zp = x.zone_present (); + s << zp; + + if (zp) + { + const time_zone& z = x; + s << z; + } +} + +void +operator<< (orawstream& s, const xml_schema::time& x) +{ + s << x.hours (); + s << x.minutes (); + s << x.seconds (); + bool zp = x.zone_present (); + s << zp; + + if (zp) + { + const time_zone& z = x; + s << z; + } +} diff --git a/examples/cxx/hybrid/binary/custom/orawstream.hxx b/examples/cxx/hybrid/binary/custom/orawstream.hxx new file mode 100644 index 0000000..9689e61 --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/orawstream.hxx @@ -0,0 +1,91 @@ +// file : examples/cxx/hybrid/binary/custom/orawstream.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#ifndef ORAWSTREAM_HXX +#define ORAWSTREAM_HXX + +#include <stddef.h> // size_t + +#include <string> + +#include "exceptions.hxx" +#include "xml-schema.hxx" + +class orawstream +{ +public: + explicit + orawstream (xml_schema::buffer&); + +public: + struct as_size + { + explicit as_size (size_t s) : s_ (s) {} + size_t s_; + }; + +public: + void operator<< (bool); + void operator<< (signed char); + void operator<< (unsigned char); + void operator<< (short); + void operator<< (unsigned short); + void operator<< (int); + void operator<< (unsigned int); + void operator<< (long); + void operator<< (unsigned long); + +#ifdef XSDE_LONGLONG + void operator<< (long long); + void operator<< (unsigned long long); +#endif + + void operator<< (as_size); + void operator<< (float); + void operator<< (double); + + void operator<< (const std::string&); + void operator<< (const xml_schema::buffer&); + +private: + orawstream (const orawstream&); + orawstream& operator= (const orawstream&); + +public: + char* + align (size_t alignment, size_t size); + +private: + xml_schema::buffer& buf_; +}; + +void operator<< (orawstream&, const xml_schema::any_type&); +void operator<< (orawstream&, const xml_schema::any_simple_type&); +void operator<< (orawstream&, const xml_schema::qname&); +void operator<< (orawstream&, const xml_schema::time_zone&); +void operator<< (orawstream&, const xml_schema::date&); +void operator<< (orawstream&, const xml_schema::date_time&); +void operator<< (orawstream&, const xml_schema::duration&); +void operator<< (orawstream&, const xml_schema::gday&); +void operator<< (orawstream&, const xml_schema::gmonth&); +void operator<< (orawstream&, const xml_schema::gmonth_day&); +void operator<< (orawstream&, const xml_schema::gyear&); +void operator<< (orawstream&, const xml_schema::gyear_month&); +void operator<< (orawstream&, const xml_schema::time&); + +void operator<< (orawstream&, const xml_schema::str_seq&); + +template <typename T> +void operator<< (orawstream&, const xml_schema::pod_seq<T>&); + +template <typename T> +void operator<< (orawstream&, const xml_schema::fix_seq<T>&); + +template <typename T> +void operator<< (orawstream&, const xml_schema::var_seq<T>&); + +#include "orawstream.ixx" +#include "orawstream.txx" + +#endif // ORAWSTREAM_HXX diff --git a/examples/cxx/hybrid/binary/custom/orawstream.ixx b/examples/cxx/hybrid/binary/custom/orawstream.ixx new file mode 100644 index 0000000..577eb1b --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/orawstream.ixx @@ -0,0 +1,110 @@ +// file : examples/cxx/hybrid/binary/custom/orawstream.ixx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +inline orawstream:: +orawstream (xml_schema::buffer& buf) + : buf_ (buf) +{ +} + +inline void orawstream:: +operator<< (bool x) +{ + *align (1, 1) = x; +} + +inline void orawstream:: +operator<< (signed char x) +{ + *reinterpret_cast<signed char*> (align (1, 1)) = x; +} + +inline void orawstream:: +operator<< (unsigned char x) +{ + *reinterpret_cast<unsigned char*> (align (1, 1)) = x; +} + +inline void orawstream:: +operator<< (short x) +{ + *reinterpret_cast<short*> (align (2, 2)) = x; +} + +inline void orawstream:: +operator<< (unsigned short x) +{ + *reinterpret_cast<unsigned short*> (align (2, 2)) = x; +} + +inline void orawstream:: +operator<< (int x) +{ + *reinterpret_cast<int*> (align (4, 4)) = x; +} + +inline void orawstream:: +operator<< (unsigned int x) +{ + *reinterpret_cast<unsigned int*> (align (4, 4)) = x; +} + +inline void orawstream:: +operator<< (long x) +{ + *reinterpret_cast<long*> ( + align (sizeof (long), sizeof (long))) = x; +} + +inline void orawstream:: +operator<< (unsigned long x) +{ + *reinterpret_cast<unsigned long*> ( + align (sizeof (unsigned long), sizeof (unsigned long))) = x; +} + +#ifdef XSDE_LONGLONG +inline void orawstream:: +operator<< (long long x) +{ + *reinterpret_cast<long long*> (align (8, 8)) = x; +} + +inline void orawstream:: +operator<< (unsigned long long x) +{ + *reinterpret_cast<unsigned long long*> (align (8, 8)) = x; +} +#endif + +inline void orawstream:: +operator<< (as_size x) +{ + *reinterpret_cast<size_t*> ( + align (sizeof (size_t), sizeof (size_t))) = x.s_; +} + +inline void orawstream:: +operator<< (float x) +{ + *reinterpret_cast<float*> ( + align (sizeof (float), sizeof (float))) = x; +} + +inline void orawstream:: +operator<< (double x) +{ + *reinterpret_cast<double*> ( + align (sizeof (double), sizeof (double))) = x; +} + +inline void +operator<< (orawstream&, const xml_schema::any_type&) +{ +} + +inline void +operator<< (orawstream&, const xml_schema::any_simple_type&) +{ +} diff --git a/examples/cxx/hybrid/binary/custom/orawstream.txx b/examples/cxx/hybrid/binary/custom/orawstream.txx new file mode 100644 index 0000000..46c5b71 --- /dev/null +++ b/examples/cxx/hybrid/binary/custom/orawstream.txx @@ -0,0 +1,47 @@ +// file : examples/cxx/hybrid/binary/custom/orawostream.txx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include <string.h> // memcpy + +template <typename T> +void +operator<< (orawstream& s, const xml_schema::pod_seq<T>& x) +{ + size_t n = x.size (); + + s << orawstream::as_size (x.size ()); + + if (n != 0) + { + size_t mn = sizeof (T) * n; + char* p = s.align (sizeof (T), mn); + memcpy (p, x.begin (), mn); + } +} + +template <typename T> +void +operator<< (orawstream& s, const xml_schema::fix_seq<T>& x) +{ + s << orawstream::as_size (x.size ()); + + for (typename xml_schema::fix_seq<T>::const_iterator i = x.begin (); + i != x.end (); ++i) + { + s << *i; + } +} + +template <typename T> +void +operator<< (orawstream& s, const xml_schema::var_seq<T>& x) +{ + s << orawstream::as_size (x.size ()); + + for (typename xml_schema::var_seq<T>::const_iterator i = x.begin (); + i != x.end (); ++i) + { + s << *i; + } +} diff --git a/examples/cxx/hybrid/binary/makefile b/examples/cxx/hybrid/binary/makefile new file mode 100644 index 0000000..89fb738 --- /dev/null +++ b/examples/cxx/hybrid/binary/makefile @@ -0,0 +1,53 @@ +# file : examples/cxx/hybrid/binary/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make + +all_examples := cdr xdr custom +build_examples := + +ifeq ($(xsde_iostream),y) +ifeq ($(xsde_exceptions),y) + +build_examples += custom + +ifeq ($(xsde_cdr),y) +build_examples += cdr +endif + +ifeq ($(xsde_cdr),y) +build_examples += xdr +endif + +endif +endif + +default := $(out_base)/ +dist := $(out_base)/.dist +dist-win := $(out_base)/.dist-win +clean := $(out_base)/.clean + +.PHONY: $(default) $(dist) $(dist-win) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(build_examples))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(build_examples))) + +# Dist. +# +$(dist) $(dist-win): path := $(subst $(src_root)/,,$(src_base)) + +$(dist): $(addprefix $(out_base)/,$(addsuffix /.dist,$(all_examples))) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README) + +$(dist-win): $(addprefix $(out_base)/,$(addsuffix /.dist-win,$(all_examples))) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README.txt) + $(call message,,unix2dos $(dist_prefix)/$(path)/README.txt) + + +ifneq ($(filter $(MAKECMDGOALS),dist dist-win),) +$(foreach e,$(all_examples),$(call import,$(src_base)/$e/makefile)) +else +$(foreach e,$(build_examples),$(call import,$(src_base)/$e/makefile)) +endif diff --git a/examples/cxx/hybrid/binary/xdr/README b/examples/cxx/hybrid/binary/xdr/README new file mode 100644 index 0000000..e81a149 --- /dev/null +++ b/examples/cxx/hybrid/binary/xdr/README @@ -0,0 +1,50 @@ +This example shows how to save/load the C++/Hybrid object model to/from +XDR (eXternal Data Representation) binary format using XDR streams. The +XDR API is available out of the box on most POSIX systems as part of Sun +RPC. On other platforms you may need to install a third-party library +which provides the XDR API. + +The example consists of the following files: + +library.xsd + XML Schema which describes a library of books. + +library.xml + Sample XML instance document. + +library.hxx +library.cxx + +library-pskel.hxx +library-pskel.cxx +library-pimpl.hxx +library-pimpl.cxx + +library-pskel.hxx +library-pskel.cxx +library-pimpl.hxx +library-pimpl.cxx + Object model (the first pair of files), parser skeletons (the + second pair), parser implementations (the third pair), serializer + skeletons (the fourth pair), and serializer implementations (the + fifth pair). These files are generated by the XSD/e compiler from + library.xsd. The --generate-parser, --generate-serializer, and + --generate-aggregate options were used to request the generation + of the parsing and serialization code. The --generate-insertion and + --generate-extraction options were used to generate the insertion + and extraction operations for the XDR streams. + +driver.cxx + Driver for the example. It first calls the parser that constructs + the object model from the input XML file. It then saves the object + model to the XDR representation and loads it back. Finally, the + driver calls the serializer to serialize the loaded object model + back to XML. + +To run the example on the sample XML instance document simply execute: + +$ ./driver library.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver <library.xml diff --git a/examples/cxx/hybrid/binary/xdr/driver.cxx b/examples/cxx/hybrid/binary/xdr/driver.cxx new file mode 100644 index 0000000..e629849 --- /dev/null +++ b/examples/cxx/hybrid/binary/xdr/driver.cxx @@ -0,0 +1,196 @@ +// file : examples/cxx/hybrid/binary/xdr/driver.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include <stddef.h> // size_t +#include <string.h> // memcpy +#include <rpc/xdr.h> + +#include <memory> // std::auto_ptr +#include <iostream> + +#include "library.hxx" + +#include "library-pimpl.hxx" +#include "library-simpl.hxx" + +using std::cerr; +using std::endl; + +// XDR output functions. Their implementations are provided after main(). +// +struct underflow_info +{ + xml_schema::buffer* buf; + size_t pos; +}; + +extern "C" int +overflow (void* user_data, char* buf, int n); + +extern "C" int +underflow (void* user_data, char* buf, int n); + +// The xdrrec_create function (used below) has slightly different +// prototypes on different platforms. To make this example portable +// we will need to cast the actual function to the following common +// prototype. +// +extern "C" +typedef void (*xdrrec_create_p) ( + XDR*, + unsigned int write_size, + unsigned int read_size, + void* user_data, + int (*read) (void* user_data, char* buf, int n), + int (*write) (void* user_data, char* buf, int n)); + +int +main (int argc, char* argv[]) +{ + const char* input; + + if (argc < 2) + { + input = "STDIN"; + cerr << "XML file not specified, reading from STDIN" << endl; + } + else + input = argv[1]; + + try + { + using namespace library; + + // Parse. + // + catalog_paggr catalog_p; + + xml_schema::document_pimpl doc_p ( + catalog_p.root_parser (), + catalog_p.root_namespace (), + catalog_p.root_name ()); + + catalog_p.pre (); + + if (argc < 2) + doc_p.parse (std::cin); + else + doc_p.parse (argv[1]); + + std::auto_ptr<catalog> c (catalog_p.post ()); + + // Save the object model to an XDR stream. + // + xdrrec_create_p xdrrec_create_ = + reinterpret_cast<xdrrec_create_p> (::xdrrec_create); + + XDR xdr; + xml_schema::buffer buf; + + xdrrec_create_ (&xdr, 0, 0, reinterpret_cast<char*> (&buf), 0, &overflow); + xdr.x_op = XDR_ENCODE; + xml_schema::oxdrstream oxdr (xdr); + + oxdr << *c; + + xdrrec_endofrecord (&xdr, true); // Flush the data. + xdr_destroy (&xdr); + + // The binary representation is now in the memory buffer 'buf'. + // To get to the raw data use buf.data() and buf.size(). + // + cerr << "binary representation size: " << buf.size () << endl + << endl; + + // Load the object model from an XDR stream. + // + underflow_info ui; + ui.buf = &buf; + ui.pos = 0; + + xdrrec_create_ (&xdr, 0, 0, reinterpret_cast<char*> (&ui), &underflow, 0); + xdr.x_op = XDR_DECODE; + xdrrec_skiprecord (&xdr); + xml_schema::ixdrstream ixdr (xdr); + + std::auto_ptr<catalog> copy (new catalog); + ixdr >> *copy; + + xdr_destroy (&xdr); + + // Serialize the copy back to XML. + // + catalog_saggr catalog_s; + + xml_schema::document_simpl doc_s ( + catalog_s.root_serializer (), + catalog_s.root_namespace (), + catalog_s.root_name ()); + + doc_s.add_prefix ("lib", "http://www.codesynthesis.com/library"); + doc_s.add_schema ("http://www.codesynthesis.com/library", "library.xsd"); + + catalog_s.pre (*c); + doc_s.serialize (std::cout); + catalog_s.post (); + } + catch (const xml_schema::xdr_exception&) + { + cerr << "XDR operation failed" << endl; + return 1; + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const xml_schema::serializer_exception& e) + { + cerr << "error: " << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read/write failure" << endl; + return 1; + } + + return 0; +} + +extern "C" int +overflow (void* p, char* buf, int n_) +{ + xml_schema::buffer* dst (reinterpret_cast<xml_schema::buffer*> (p)); + size_t n (static_cast<size_t> (n_)); + + size_t size (dst->size ()); + size_t capacity (dst->capacity ()); + + // Implement exponential growth. + // + if (size + n > capacity && size + n < capacity * 2) + dst->capacity (capacity * 2); + + dst->size (size + n); + memcpy (dst->data () + size, buf, n); + + return n; +} + +extern "C" int +underflow (void* p, char* buf, int n_) +{ + underflow_info* ui (reinterpret_cast<underflow_info*> (p)); + size_t n (static_cast<size_t> (n_)); + + size_t size (ui->buf->size () - ui->pos); + n = size > n ? n : size; + + memcpy (buf, ui->buf->data () + ui->pos, n); + ui->pos += n; + + return n; +} diff --git a/examples/cxx/hybrid/binary/xdr/library.xml b/examples/cxx/hybrid/binary/xdr/library.xml new file mode 100644 index 0000000..ee5f771 --- /dev/null +++ b/examples/cxx/hybrid/binary/xdr/library.xml @@ -0,0 +1,53 @@ +<?xml version="1.0"?> + +<!-- + +file : examples/cxx/hybrid/binary/xdr/library.xml +author : Boris Kolpackov <boris@codesynthesis.com> +copyright : not copyrighted - public domain + +--> + +<lib:catalog xmlns:lib="http://www.codesynthesis.com/library" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.codesynthesis.com/library library.xsd"> + + <book available="false"> + <isbn>0679760806</isbn> + <title>The Master and Margarita</title> + <genre>fiction</genre> + + <author> + <name>Mikhail Bulgakov</name> + <born>1891-05-15</born> + <died>1940-03-10</died> + </author> + </book> + + + <book available="true" > + <isbn>0679600841</isbn> + <title>War and Peace</title> + <genre>history</genre> + + <author> + <name>Leo Tolstoy</name> + <born>1828-09-09</born> + <died>1910-11-20</died> + </author> + </book> + + + <book available="false"> + <isbn>0679420290</isbn> + <title>Crime and Punishment</title> + <genre>philosophy</genre> + + <author> + <name>Fyodor Dostoevsky</name> + <born>1821-11-11</born> + <died>1881-02-09</died> + </author> + </book> + +</lib:catalog> diff --git a/examples/cxx/hybrid/binary/xdr/library.xsd b/examples/cxx/hybrid/binary/xdr/library.xsd new file mode 100644 index 0000000..5e411d9 --- /dev/null +++ b/examples/cxx/hybrid/binary/xdr/library.xsd @@ -0,0 +1,69 @@ +<?xml version="1.0"?> + +<!-- + +file : examples/cxx/hybrid/binary/xdr/library.xsd +author : Boris Kolpackov <boris@codesynthesis.com> +copyright : not copyrighted - public domain + +--> + +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:lib="http://www.codesynthesis.com/library" + targetNamespace="http://www.codesynthesis.com/library"> + + <xsd:simpleType name="isbn"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + + + <xsd:complexType name="title"> + <xsd:simpleContent> + <xsd:extension base="xsd:string"> + <xsd:attribute name="lang" type="xsd:string"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + + + <xsd:simpleType name="genre"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="romance"/> + <xsd:enumeration value="fiction"/> + <xsd:enumeration value="horror"/> + <xsd:enumeration value="history"/> + <xsd:enumeration value="philosophy"/> + </xsd:restriction> + </xsd:simpleType> + + + <xsd:complexType name="author"> + <xsd:sequence> + <xsd:element name="name" type="xsd:string"/> + <xsd:element name="born" type="xsd:date"/> + <xsd:element name="died" type="xsd:date" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + + + <xsd:complexType name="book"> + <xsd:sequence> + <xsd:element name="isbn" type="lib:isbn"/> + <xsd:element name="title" type="lib:title"/> + <xsd:element name="genre" type="lib:genre"/> + <xsd:element name="author" type="lib:author" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="available" type="xsd:boolean" use="required"/> + </xsd:complexType> + + + <xsd:complexType name="catalog"> + <xsd:sequence> + <xsd:element name="book" type="lib:book" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + + + <xsd:element name="catalog" type="lib:catalog"/> + +</xsd:schema> diff --git a/examples/cxx/hybrid/binary/xdr/makefile b/examples/cxx/hybrid/binary/xdr/makefile new file mode 100644 index 0000000..0cff972 --- /dev/null +++ b/examples/cxx/hybrid/binary/xdr/makefile @@ -0,0 +1,112 @@ +# file : examples/cxx/hybrid/binary/xdr/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../../build/bootstrap.make + +xsd := library.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,\ +$(cxx:.cxx=.o) \ +$(xsd:.xsd=.o) \ +$(xsd:.xsd=-pskel.o) \ +$(xsd:.xsd=-pimpl.o) \ +$(xsd:.xsd=-sskel.o) \ +$(xsd:.xsd=-simpl.o)) + +dep := $(obj:.o=.o.d) + +xsde.l := $(out_root)/libxsde/xsde/xsde.l +xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options + +driver := $(out_base)/driver +dist := $(out_base)/.dist +dist-win := $(out_base)/.dist-win +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.cxx) \ + $(xsd:.xsd=-pskel.hxx) $(xsd:.xsd=-pskel.cxx) \ + $(xsd:.xsd=-pimpl.hxx) $(xsd:.xsd=-pimpl.cxx) \ + $(xsd:.xsd=-sskel.hxx) $(xsd:.xsd=-sskel.cxx) \ + $(xsd:.xsd=-simpl.hxx) $(xsd:.xsd=-simpl.cxx) + +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-serializer \ +--generate-aggregate --generate-insertion XDR --generate-extraction XDR + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Dist. +# +dist-common := $(out_base)/.dist-common + +.PHONY: $(dist) $(dist-win) $(dist-common) + +$(dist) $(dist-win) $(dist-common): path := $(subst $(src_root)/,,$(src_base)) + +$(dist-common): + $(call install-data,$(src_base)/driver.cxx,$(dist_prefix)/$(path)/driver.cxx) + $(call install-data,$(src_base)/library.xsd,$(dist_prefix)/$(path)/library.xsd) + $(call install-data,$(src_base)/library.xml,$(dist_prefix)/$(path)/library.xml) + +$(dist): $(dist-common) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README) + +$(dist-win): $(dist-common) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README.txt) + $(call message,,unix2dos $(dist_prefix)/$(path)/README.txt) + + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean)) + + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(gen): | $(out_base)/.gitignore +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(genf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/install.make) +$(call include,$(scf_root)/xsde/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) |