diff options
Diffstat (limited to 'xsd/examples/cxx/tree/compression')
-rw-r--r-- | xsd/examples/cxx/tree/compression/README | 48 | ||||
-rw-r--r-- | xsd/examples/cxx/tree/compression/compressed-format-target.cxx | 157 | ||||
-rw-r--r-- | xsd/examples/cxx/tree/compression/compressed-format-target.hxx | 96 | ||||
-rw-r--r-- | xsd/examples/cxx/tree/compression/compressed-input-source.cxx | 215 | ||||
-rw-r--r-- | xsd/examples/cxx/tree/compression/compressed-input-source.hxx | 132 | ||||
-rw-r--r-- | xsd/examples/cxx/tree/compression/driver.cxx | 125 | ||||
-rw-r--r-- | xsd/examples/cxx/tree/compression/library.xml.gz | bin | 0 -> 486 bytes | |||
-rw-r--r-- | xsd/examples/cxx/tree/compression/library.xsd | 73 | ||||
-rw-r--r-- | xsd/examples/cxx/tree/compression/makefile | 117 |
9 files changed, 963 insertions, 0 deletions
diff --git a/xsd/examples/cxx/tree/compression/README b/xsd/examples/cxx/tree/compression/README new file mode 100644 index 0000000..f163970 --- /dev/null +++ b/xsd/examples/cxx/tree/compression/README @@ -0,0 +1,48 @@ +This example shows how to compress an XML document during serialization +and decompress it during parsing. The example uses the compression +functionality provided by the zlib library[1] which needs to be installed +in order to build and run this example. It should also be fairly straight- +forward to modify the code in this example to use other compression +libraries. + +[1] http://www.zlib.net + +The example consists of the following files: + +library.xsd + XML Schema which describes a library of books. + +library.xml.gz + Sample XML instance document compressed using the gzip format. + +compressed-format-target.hxx +compressed-format-target.cxx + Implementation of the Xerces-C++ XMLFormatTarget interface with the on- + the-fly compression support. You can use it in your application to add + XML compression. + +compressed-input-source.hxx +compressed-input-source.cxx + Implementation of the Xerces-C++ InputSource interface with the on-the- + fly decompression support. You can use it in your application to add + XML decompression. + +library.hxx +library.cxx + C++ types that represent the given vocabulary and a set of parsing + functions that convert XML instance documents to a tree-like in-memory + object model. These are generated by XSD from library.xsd. + +driver.cxx + Driver for the example. It first creates the compressed_input_source + object and passes it to one of the parsing functions that constructs + the object model from the compressed input file. It then prints the + content of the object model to STDERR. Finally, the driver creates the + compressed_format_target object and passes it to one of the serialization + functions which converts the object model back to the compressed XML. + +To run the example on the sample XML document simply execute: + +$ ./driver library.xml.gz + +The serialization output is written to the out.xml.gz file. diff --git a/xsd/examples/cxx/tree/compression/compressed-format-target.cxx b/xsd/examples/cxx/tree/compression/compressed-format-target.cxx new file mode 100644 index 0000000..b4a8a85 --- /dev/null +++ b/xsd/examples/cxx/tree/compression/compressed-format-target.cxx @@ -0,0 +1,157 @@ +// file : examples/cxx/tree/compression/compressed-format-target.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include <ostream> +#include <cstring> // std::memcpy + +#include "compressed-format-target.hxx" + +using namespace std; + +// +// compression_failure +// + +const char* compression_failure:: +what () const throw () +{ + return "compression failure"; +} + +// +// compressed_format_target +// + +compressed_format_target:: +compressed_format_target (ostream& os, compression_type t) + : os_ (os), closed_ (false), n_ (0) + { + zs_.zalloc = Z_NULL; + zs_.zfree = Z_NULL; + zs_.opaque = Z_NULL; + + int window = 0; + + switch (t) + { + case raw: + { + window = -15; + break; + } + case zlib: + { + window = 15; + break; + } + case gzip: + { + window = 16 + 15; + break; + } + } + + int r (deflateInit2 (&zs_, + Z_DEFAULT_COMPRESSION, + Z_DEFLATED, + window, + 8, + Z_DEFAULT_STRATEGY)); + if (r != Z_OK) + throw compression_failure (r); + } + +compressed_format_target:: +~compressed_format_target () +{ + try + { + // Close the free the compression stream. + // + if (!closed_) + close (); + } + catch (...) + { + } + + deflateEnd (&zs_); +} + +void compressed_format_target:: +writeChars (const XMLByte* const buf, +#if _XERCES_VERSION >= 30000 + const XMLSize_t size, +#else + const unsigned int size, +#endif + xercesc::XMLFormatter* const) +{ + // Flush the buffer if the block is too large or if we don't have + // any space left. + // + if ((size >= buf_size_ / 8 || n_ + size > buf_size_) && n_ != 0) + { + write (in_, n_); + n_ = 0; + } + + if (size < buf_size_ / 8) + { + memcpy (in_ + n_, reinterpret_cast<const char*> (buf), size); + n_ += size; + } + else + write (reinterpret_cast<const char*> (buf), size); +} + + +void compressed_format_target:: +flush () +{ + if (n_ != 0) + { + write (in_, n_); + n_ = 0; + } + + if (!os_.fail ()) + os_.flush (); +} + +void compressed_format_target:: +close () +{ + write (in_, n_, true); + n_ = 0; + + if (!os_.fail ()) + os_.flush (); + + closed_ = true; +} + +void compressed_format_target:: +write (const char* buf, size_t size, bool flush) +{ + zs_.next_in = reinterpret_cast<Bytef*> (const_cast<char*> (buf)); + zs_.avail_in = static_cast<uInt> (size); + + do + { + zs_.next_out = reinterpret_cast<Bytef*> (out_); + zs_.avail_out = buf_size_; + + int r (deflate (&zs_, flush ? Z_FINISH : Z_NO_FLUSH)); + + if (r != Z_OK && r != Z_BUF_ERROR && r != Z_STREAM_END) + throw compression_failure (r); + + size_t n (buf_size_ - zs_.avail_out); + + if (!os_.fail () && n > 0) + os_.write (out_, static_cast<streamsize> (n)); + + } while (zs_.avail_out == 0); +} diff --git a/xsd/examples/cxx/tree/compression/compressed-format-target.hxx b/xsd/examples/cxx/tree/compression/compressed-format-target.hxx new file mode 100644 index 0000000..5d12e81 --- /dev/null +++ b/xsd/examples/cxx/tree/compression/compressed-format-target.hxx @@ -0,0 +1,96 @@ +// file : examples/cxx/tree/compression/compressed-format-target.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#ifndef COMPRESSED_FORMAT_TARGET_HXX +#define COMPRESSED_FORMAT_TARGET_HXX + +#include <zlib.h> + +#include <iosfwd> +#include <cstddef> // std::size_t +#include <exception> + +#include <xercesc/framework/XMLFormatter.hpp> + +struct compression_failure: std::exception +{ + explicit + compression_failure (int code) + : code_ (code) + { + } + + int + code () const + { + return code_; + } + + const char* + message () const + { + return zError (code_); + } + + virtual const char* + what () const throw (); + +private: + int code_; +}; + +// Xerces-C++ XMLFormatTarget interface implementation with on-the-fly, +// zlib-based compression. +// +class compressed_format_target: public xercesc::XMLFormatTarget +{ +public: + enum compression_type + { + raw, + zlib, + gzip + }; + + compressed_format_target (std::ostream&, compression_type); + + virtual + ~compressed_format_target (); + + virtual void + writeChars (const XMLByte* const buf, +#if _XERCES_VERSION >= 30000 + const XMLSize_t size, +#else + const unsigned int size, +#endif + xercesc::XMLFormatter* const); + + virtual void + flush (); + + // Close the compressed stream by writing out the zlib or gzip trailer. + // This function is automatically called from the destructor but you + // may want to call it explicitly to be able to catch any exceptions + // that it might throw. + // + void + close (); + +private: + void + write (const char* buf, std::size_t size, bool flush = false); + +private: + std::ostream& os_; + z_stream zs_; + bool closed_; + + static const std::size_t buf_size_ = 65536; + char in_[buf_size_]; + char out_[buf_size_]; + size_t n_; +}; + +#endif // COMPRESSED_FORMAT_TARGET_HXX diff --git a/xsd/examples/cxx/tree/compression/compressed-input-source.cxx b/xsd/examples/cxx/tree/compression/compressed-input-source.cxx new file mode 100644 index 0000000..22d09ff --- /dev/null +++ b/xsd/examples/cxx/tree/compression/compressed-input-source.cxx @@ -0,0 +1,215 @@ +// file : examples/cxx/tree/compression/compressed-input-source.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include <istream> + +#include <xsd/cxx/xml/string.hxx> + +#include "compressed-input-source.hxx" + +using namespace std; +using namespace xercesc; +namespace xml = xsd::cxx::xml; + +// +// decompression_failure +// + +const char* decompression_failure:: +what () const throw () +{ + return "decompression failure"; +} + +// +// compressed_input_source +// + +compressed_input_source:: +compressed_input_source (istream& is, compression_type t) + : is_ (&is), type_ (t) +{ +} + +compressed_input_source:: +compressed_input_source (istream& is, + compression_type t, + const string& sysid) + : InputSource (xml::string (sysid).c_str ()), is_ (&is), type_ (t) +{ +} + +compressed_input_source:: +compressed_input_source (istream& is, + compression_type t, + const string& sysid, + const string& pubid) + : xercesc::InputSource (xml::string (sysid).c_str (), + xml::string (pubid).c_str ()), + is_ (&is), + type_ (t) +{ +} + +BinInputStream* compressed_input_source:: +makeStream () const +{ + if (is_ == 0) + throw copy (); + + istream& is (*is_); + is_ = 0; + return new compressed_input_stream ( + is, static_cast<compressed_input_stream::compression_type> (type_)); +} + +// +// compressed_input_stream +// + +compressed_input_stream:: +compressed_input_stream (istream& is, compression_type t) + : is_ (is), end_ (false), pos_ (0) +{ + zs_.zalloc = Z_NULL; + zs_.zfree = Z_NULL; + zs_.opaque = Z_NULL; + zs_.next_in = Z_NULL; + zs_.avail_in = 0; + + int window = 0; + + switch (t) + { + case raw: + { + window = -15; + break; + } + case zlib: + { + window = 15; + break; + } + case gzip: + { + window = 16 + 15; + break; + } + } + + int r (inflateInit2 (&zs_, window)); + + if (r != Z_OK) + throw decompression_failure (r); +} + +compressed_input_stream:: +~compressed_input_stream () +{ + inflateEnd (&zs_); +} + +#if _XERCES_VERSION >= 30000 +XMLFilePos compressed_input_stream:: +curPos () const +{ + return static_cast<XMLFilePos> (pos_); +} +#else +unsigned int compressed_input_stream:: +curPos () const +{ + return static_cast<unsigned int> (pos_); +} +#endif + +#if _XERCES_VERSION >= 30000 +XMLSize_t compressed_input_stream:: +readBytes (XMLByte* const buf, const XMLSize_t size) +#else +unsigned int compressed_input_stream:: +readBytes (XMLByte* const buf, const unsigned int size) +#endif +{ + if (end_) + return 0; + + // Keep calling inflate() until we fill up the buffer or reach the + // end of stream. If we run out of input data, call the underlying + // stream for more. + // + zs_.next_out = reinterpret_cast<Bytef*> (buf); + zs_.avail_out = static_cast<uInt> (size); + + int r; + + do + { + if (zs_.avail_in == 0) + { + zs_.avail_in = static_cast<uInt> (read ()); + zs_.next_in = reinterpret_cast<Bytef*> (const_cast<char*> (in_)); + + if (zs_.avail_in == 0) + throw decompression_failure (Z_DATA_ERROR); + } + + r = inflate (&zs_, Z_NO_FLUSH); + + if (r != Z_OK && r != Z_STREAM_END) + throw decompression_failure (r); + + } while (r != Z_STREAM_END && zs_.avail_out != 0); + + if (r == Z_STREAM_END) + end_ = true; + + size_t n (size - zs_.avail_out); + pos_ += n; + +#if _XERCES_VERSION >= 30000 + return static_cast<XMLSize_t> (n); +#else + return static_cast<unsigned int> (n); +#endif +} + +#if _XERCES_VERSION >= 30000 +const XMLCh* compressed_input_stream:: +getContentType () const +{ + return 0; +} +#endif + +size_t compressed_input_stream:: +read () +{ + // Some implementations don't clear gcount if you call read() on a + // stream that is in the eof state. + // + if (is_.eof ()) + return 0; + + // Unset the exception failbit while we are working with the stream. + // + ios_base::iostate old (is_.exceptions ()); + is_.exceptions (old & ~ios_base::failbit); + + is_.read (in_, static_cast<streamsize> (buf_size_)); + + // Clear the fail bit if it was caused by eof and restore the original + // exception state. If there are any pending errors then the exception + // will be thrown now. + // + if (is_.fail () && is_.eof ()) + is_.clear (is_.rdstate () & ~ios_base::failbit); + + is_.exceptions (old); + + // Make sure that if we failed, we won't be called again. + // + return !is_.fail () ? static_cast<size_t> (is_.gcount ()) : 0; +} diff --git a/xsd/examples/cxx/tree/compression/compressed-input-source.hxx b/xsd/examples/cxx/tree/compression/compressed-input-source.hxx new file mode 100644 index 0000000..680d39f --- /dev/null +++ b/xsd/examples/cxx/tree/compression/compressed-input-source.hxx @@ -0,0 +1,132 @@ +// file : examples/cxx/tree/compression/compressed-input-source.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#ifndef COMPRESSED_INPUT_SOURCE_HXX +#define COMPRESSED_INPUT_SOURCE_HXX + +#include <zlib.h> + +#include <iosfwd> +#include <string> +#include <cstddef> // std::size_t +#include <exception> + +#include <xercesc/sax/InputSource.hpp> +#include <xercesc/util/BinInputStream.hpp> + +struct decompression_failure: std::exception +{ + explicit + decompression_failure (int code) + : code_ (code) + { + } + + int + code () const + { + return code_; + } + + const char* + message () const + { + return zError (code_); + } + + virtual const char* + what () const throw (); + +private: + int code_; +}; + +// Xerces-C++ InputSource interface implementation with on-the-fly, zlib- +// based decompression. +// +class compressed_input_source: public xercesc::InputSource +{ +public: + enum compression_type + { + raw, + zlib, + gzip + }; + + compressed_input_source (std::istream&, compression_type); + + compressed_input_source (std::istream&, + compression_type, + const std::string& system_id); + + compressed_input_source (std::istream&, + compression_type, + const std::string& system_id, + const std::string& public_id); + + struct copy {}; + + // Throws the copy exception if this function is called more than once. + // + virtual xercesc::BinInputStream* + makeStream () const; + +private: + mutable std::istream* is_; + compression_type type_; +}; + +// Xerces-C++ BinInputStream interface implementation with on-the-fly, zlib- +// based decompression. +// +class compressed_input_stream: public xercesc::BinInputStream +{ +public: + enum compression_type + { + raw, + zlib, + gzip + }; + + compressed_input_stream (std::istream&, compression_type); + + virtual + ~compressed_input_stream (); + +#if _XERCES_VERSION >= 30000 + virtual XMLFilePos + curPos () const; + + virtual XMLSize_t + readBytes (XMLByte* const buf, const XMLSize_t size); + + virtual const XMLCh* + getContentType () const; + +#else + + virtual unsigned int + readBytes (XMLByte* const buf, const unsigned int size); + + virtual unsigned int + curPos () const; +#endif + +private: + std::size_t + read (); + +private: + std::istream& is_; + z_stream zs_; + bool end_; + + static const std::size_t buf_size_ = 65536; + char in_[buf_size_]; + std::size_t pos_; // Current decompressed stream position. +}; + +#endif // COMPRESSED_INPUT_SOURCE_HXX diff --git a/xsd/examples/cxx/tree/compression/driver.cxx b/xsd/examples/cxx/tree/compression/driver.cxx new file mode 100644 index 0000000..db285cf --- /dev/null +++ b/xsd/examples/cxx/tree/compression/driver.cxx @@ -0,0 +1,125 @@ +// file : examples/cxx/tree/compression/driver.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include <memory> // std::auto_ptr +#include <fstream> +#include <iostream> + +#include <xercesc/util/PlatformUtils.hpp> + +#include "library.hxx" + +#include "compressed-input-source.hxx" +#include "compressed-format-target.hxx" + +using namespace std; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " library.xml" << endl; + return 1; + } + + int r (0); + + // We need to initialize the Xerces-C++ runtime because we are + // using the Xerces-C++ input/output interfaces. + // + xercesc::XMLPlatformUtils::Initialize (); + + try + { + using namespace library; + + // Read in the XML file and obtain its object model. + // + ifstream ifs; + ifs.exceptions (ifstream::badbit | ifstream::failbit); + ifs.open (argv[1], ifstream::in | ifstream::binary); + + compressed_input_source cis (ifs, compressed_input_source::gzip, argv[1]); + + std::auto_ptr<catalog> c ( + catalog_ (cis, xml_schema::flags::dont_initialize)); + + + // Let's print what we've got. + // + for (catalog::book_const_iterator bi (c->book ().begin ()); + bi != c->book ().end (); + ++bi) + { + cerr << endl + << "ID : " << bi->id () << endl + << "ISBN : " << bi->isbn () << endl + << "Title : " << bi->title () << endl + << "Genre : " << bi->genre () << endl; + + for (book::author_const_iterator ai (bi->author ().begin ()); + ai != bi->author ().end (); + ++ai) + { + cerr << "Author : " << ai->name () << endl; + cerr << " Born : " << ai->born () << endl; + + if (ai->died ()) + cerr << " Died : " << *ai->died () << endl; + + if (ai->recommends ()) + cerr << " Recommends : " << (*ai->recommends ())->title () << endl; + } + + cerr << "Available : " << std::boolalpha << bi->available () << endl; + } + + // Prepare namespace mapping and schema location information. + // + xml_schema::namespace_infomap map; + + map["lib"].name = "http://www.codesynthesis.com/library"; + map["lib"].schema = "library.xsd"; + + ofstream ofs; + ofs.exceptions (ofstream::badbit | ofstream::failbit | ofstream::eofbit); + ofs.open ("out.xml.gz", ofstream::out | ofstream::binary); + + compressed_format_target cft (ofs, compressed_format_target::gzip); + + // Write it out. + // + catalog_ (cft, *c, map, "UTF-8", xml_schema::flags::dont_initialize); + + // Write out the compression stream trailer. If we don't do this + // explicitly, it will be done automatically in the cft's destructor + // but then any exceptions that might be throws will be ignored. + // + cft.close(); + } + catch (const xml_schema::exception& e) + { + cerr << e << endl; + r = 1; + } + catch (const compression_failure& e) + { + cerr << "compression failure: " << e.message () << endl; + r = 1; + } + catch (const decompression_failure& e) + { + cerr << "decompression failure: " << e.message () << endl; + r = 1; + } + catch (const ios_base::failure&) + { + cerr << "file open or read/write failure" << endl; + r = 1; + } + + xercesc::XMLPlatformUtils::Terminate (); + return r; +} diff --git a/xsd/examples/cxx/tree/compression/library.xml.gz b/xsd/examples/cxx/tree/compression/library.xml.gz Binary files differnew file mode 100644 index 0000000..dd71159 --- /dev/null +++ b/xsd/examples/cxx/tree/compression/library.xml.gz diff --git a/xsd/examples/cxx/tree/compression/library.xsd b/xsd/examples/cxx/tree/compression/library.xsd new file mode 100644 index 0000000..0451b36 --- /dev/null +++ b/xsd/examples/cxx/tree/compression/library.xsd @@ -0,0 +1,73 @@ +<?xml version="1.0"?> + +<!-- + +file : examples/cxx/tree/compression/library.xsd +author : Boris Kolpackov <boris@codesynthesis.com> +copyright : not copyrighted - public domain + +--> + +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xse="http://www.codesynthesis.com/xmlns/xml-schema-extension" + 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:language"/> + </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="person"> + <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="author"> + <xsd:complexContent> + <xsd:extension base="lib:person"> + <xsd:attribute name="recommends" type="xsd:IDREF" xse:refType="lib:book"/> + </xsd:extension> + </xsd:complexContent> + </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" default="true"/> + <xsd:attribute name="id" type="xsd:ID" 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/xsd/examples/cxx/tree/compression/makefile b/xsd/examples/cxx/tree/compression/makefile new file mode 100644 index 0000000..30188c1 --- /dev/null +++ b/xsd/examples/cxx/tree/compression/makefile @@ -0,0 +1,117 @@ +# file : examples/cxx/tree/compression/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2010 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 compressed-input-source.cxx compressed-format-target.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=.o)) +dep := $(obj:.o=.o.d) + +driver := $(out_base)/driver +install := $(out_base)/.install +dist := $(out_base)/.dist +dist-win := $(out_base)/.dist-win +clean := $(out_base)/.clean + + +# Import. +# +$(call import,\ + $(scf_root)/import/libxerces-c/stub.make,\ + l: xerces_c.l,cpp-options: xerces_c.l.cpp-options) + +ifeq ($(filter $(MAKECMDGOALS),dist dist-win install),) +$(call import,\ + $(scf_root)/import/libz/stub.make,\ + l: z.l,cpp-options: z.l.cpp-options) +endif + +# Build. +# +$(driver): $(obj) $(xerces_c.l) $(z.l) + +$(obj) $(dep): cpp_options := -I$(src_root)/libxsd +$(obj) $(dep): $(xerces_c.l.cpp-options) $(z.l.cpp-options) + +genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.ixx) $(xsd:.xsd=.cxx) +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): xsd := $(out_root)/xsd/xsd +$(gen): xsd_options := --generate-ostream --generate-serialization +$(gen): $(out_root)/xsd/xsd + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + + +# Install & Dist. +# +dist-common := $(out_base)/.dist-common + +$(install) $(dist) $(dist-win) $(dist-common): path := $(subst $(src_root)/,,$(src_base)) + +$(install): + $(call install-data,$(src_base)/README,$(install_doc_dir)/xsd/$(path)/README) + $(call install-data,$(src_base)/driver.cxx,$(install_doc_dir)/xsd/$(path)/driver.cxx) + $(call install-data,$(src_base)/compressed-format-target.hxx,$(install_doc_dir)/xsd/$(path)/compressed-format-target.hxx) + $(call install-data,$(src_base)/compressed-format-target.cxx,$(install_doc_dir)/xsd/$(path)/compressed-format-target.cxx) + $(call install-data,$(src_base)/compressed-input-source.hxx,$(install_doc_dir)/xsd/$(path)/compressed-input-source.hxx) + $(call install-data,$(src_base)/compressed-input-source.cxx,$(install_doc_dir)/xsd/$(path)/compressed-input-source.cxx) + $(call install-data,$(src_base)/library.xsd,$(install_doc_dir)/xsd/$(path)/library.xsd) + $(call install-data,$(src_base)/library.xml.gz,$(install_doc_dir)/xsd/$(path)/library.xml.gz) + +$(dist-common): + $(call install-data,$(src_base)/driver.cxx,$(dist_prefix)/$(path)/driver.cxx) + $(call install-data,$(src_base)/compressed-format-target.hxx,$(dist_prefix)/$(path)/compressed-format-target.hxx) + $(call install-data,$(src_base)/compressed-format-target.cxx,$(dist_prefix)/$(path)/compressed-format-target.cxx) + $(call install-data,$(src_base)/compressed-input-source.hxx,$(dist_prefix)/$(path)/compressed-input-source.hxx) + $(call install-data,$(src_base)/compressed-input-source.cxx,$(dist_prefix)/$(path)/compressed-input-source.cxx) + $(call install-data,$(src_base)/library.xsd,$(dist_prefix)/$(path)/library.xsd) + $(call install-data,$(src_base)/library.xml.gz,$(dist_prefix)/$(path)/library.xml.gz) + +$(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. +# +$(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)/out.xml.gz) + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(gen): | $(out_base)/.gitignore +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver out.xml.gz $(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)/xsd/tree/xsd-cxx.make) + +# Dependencies. +# +$(call import,$(src_root)/xsd/makefile) |