From 40172c8a4c903acba24b236be7c3683b373f0bea Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 10 May 2014 18:41:25 -0700 Subject: Add 'persistence' example --- examples/makefile | 2 +- examples/persistence/README | 0 examples/persistence/driver.cxx | 46 +++++++++++++++ examples/persistence/makefile | 89 +++++++++++++++++++++++++++++ examples/persistence/position.cxx | 114 ++++++++++++++++++++++++++++++++++++++ examples/persistence/position.hxx | 87 +++++++++++++++++++++++++++++ examples/persistence/position.xml | 5 ++ 7 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 examples/persistence/README create mode 100644 examples/persistence/driver.cxx create mode 100644 examples/persistence/makefile create mode 100644 examples/persistence/position.cxx create mode 100644 examples/persistence/position.hxx create mode 100644 examples/persistence/position.xml (limited to 'examples') diff --git a/examples/makefile b/examples/makefile index 52808d4..00ed338 100644 --- a/examples/makefile +++ b/examples/makefile @@ -4,7 +4,7 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make -examples := roundtrip processing performance +examples := roundtrip processing persistence performance default := $(out_base)/ test := $(out_base)/.test diff --git a/examples/persistence/README b/examples/persistence/README new file mode 100644 index 0000000..e69de29 diff --git a/examples/persistence/driver.cxx b/examples/persistence/driver.cxx new file mode 100644 index 0000000..d62dd3b --- /dev/null +++ b/examples/persistence/driver.cxx @@ -0,0 +1,46 @@ +// file : examples/persistence/driver.cxx +// copyright : not copyrighted - public domain + +#include +#include + +#include +#include + +#include "position.hxx" + +using namespace std; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " " << endl; + return 1; + } + + try + { + // Load the object model state from XML. + // + ifstream ifs (argv[1]); + xml::parser p (ifs, argv[1]); + + object o (p); + + // Save the object model state back to XML. + // + xml::serializer s (cout, "output"); + + o.serialize (s); + } + // This handler will handle both parsing (xml::parsing) and serialization + // (xml::serialization) exceptions. + // + catch (const xml::exception& e) + { + cerr << e.what () << endl; + return 1; + } +} diff --git a/examples/persistence/makefile b/examples/persistence/makefile new file mode 100644 index 0000000..be54989 --- /dev/null +++ b/examples/persistence/makefile @@ -0,0 +1,89 @@ +# file : examples/persistence/makefile +# copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC +# license : MIT; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make + +cxx_tun := driver.cxx position.cxx + +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +studxml.l := $(out_root)/xml/studxml.l +studxml.l.cpp-options := $(out_root)/xml/studxml.l.cpp-options + +driver := $(out_base)/driver +test := $(out_base)/.test +dist := $(out_base)/.dist +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(cxx_obj) $(studxml.l) +$(cxx_obj) $(cxx_od): $(studxml.l.cpp-options) + +$(call include-dep,$(cxx_od)) + +# Alias for default target. +# +$(out_base)/: $(driver) + +# Dist +# +$(dist): name := $(subst $(src_root)/examples/,,$(src_base)) +$(dist): sources := $(cxx_tun) +$(dist): extras := README position.xml +$(dist): export extra_headers := position.hxx +$(dist): export extra_dist := $(extras) $(name)-vc9.vcproj \ +$(name)-vc10.vcxproj $(name)-vc10.vcxproj.filters \ +$(name)-vc11.vcxproj $(name)-vc11.vcxproj.filters \ +$(name)-vc12.vcxproj $(name)-vc12.vcxproj.filters +$(dist): + $(call dist-data,$(sources) $(extra_headers) $(extras)) + $(call meta-automake,../template/Makefile.am) + $(call meta-vc9proj,../template/template-vc9.vcproj,$(name)-vc9.vcproj) + $(call meta-vc10proj,../template/template-vc10.vcxproj,$(name)-vc10.vcxproj) + $(call meta-vc11proj,../template/template-vc11.vcxproj,$(name)-vc11.vcxproj) + $(call meta-vc12proj,../template/template-vc12.vcxproj,$(name)-vc12.vcxproj) + +# Test. +# +$(test): $(driver) + $(call message,test $<,$< $(src_base)/position.xml) + +# Clean. +# +$(clean): \ + $(driver).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + + +# How to. +# +$(call include,$(bld_root)/dist.make) +$(call include,$(bld_root)/meta/vc9proj.make) +$(call include,$(bld_root)/meta/vc10proj.make) +$(call include,$(bld_root)/meta/vc11proj.make) +$(call include,$(bld_root)/meta/vc12proj.make) +$(call include,$(bld_root)/meta/automake.make) + +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + +# Dependencies. +# +$(call import,$(src_root)/xml/makefile) diff --git a/examples/persistence/position.cxx b/examples/persistence/position.cxx new file mode 100644 index 0000000..9f4f701 --- /dev/null +++ b/examples/persistence/position.cxx @@ -0,0 +1,114 @@ +// file : examples/persistence/position.cxx +// copyright : not copyrighted - public domain + +#include + +#include +#include + +#include "position.hxx" + +using namespace std; +using namespace xml; + +// position +// +position:: +position (parser& p) + : lat_ (p.attribute ("lat")), + lon_ (p.attribute ("lon")) +{ + p.content (content::empty); +} + +void position:: +serialize (serializer& s) const +{ + s.attribute ("lat", lat_); + s.attribute ("lon", lon_); +} + +// object +// +object:: +object (parser& p) +{ + // Note that for the root of the object model we parse the start/end + // element ourselves instead of expecting the caller to do so. This + // makes the client code nice and simple. + // + p.next_expect (parser::start_element, "object", content::complex); + + // Because of the above special case, this constructor is called + // without start_element yet being parsed. As a result, we cannot + // parse attributes or nested elements in the initializer list. + // + name_ = p.attribute ("name"); + type_ = p.attribute ("type"); + id_ = p.attribute ("id"); + + do + { + p.next_expect (parser::start_element, "position"); + positions_.push_back (position (p)); + p.next_expect (parser::end_element); + + } while (p.peek () == parser::start_element); + + p.next_expect (xml::parser::end_element); // object +} + +void object:: +serialize (serializer& s) const +{ + // Note that for the root of the object model we serialize the + // start/end element ourselves instead of expecting the caller + // to do so. This makes the client code nice and simple. + // + s.start_element ("object"); + + s.attribute ("name", name_); + s.attribute ("type", type_); + s.attribute ("id", id_); + + for (positions_type::const_iterator i (positions_.begin ()); + i != positions_.end (); + ++i) + { + s.start_element ("position"); + i->serialize (s); + s.end_element (); + } + + s.end_element (); // object +} + +// object_type +// +ostream& +operator<< (ostream& os, object_type x) +{ + if (x == building) + os << "building"; + else + os << "mountain"; + + return os; +} + +istream& +operator>> (istream& is, object_type& x) +{ + string s; + if (is >> s) + { + if (s == "building") + x = building; + else if (s == "mountain") + x = mountain; + else + is.setstate (istream::failbit); + } + + return is; +} diff --git a/examples/persistence/position.hxx b/examples/persistence/position.hxx new file mode 100644 index 0000000..3025a29 --- /dev/null +++ b/examples/persistence/position.hxx @@ -0,0 +1,87 @@ +// file : examples/persistence/position.hxx +// copyright : not copyrighted - public domain + +#ifndef POSITION_HXX +#define POSITION_HXX + +#include +#include +#include + +#include // xml::{parser,serializer} forward declarations. + +enum object_type {building, mountain}; + +// XML parser and serializer will use these operators to convert +// object_type to/from a string representation unless we provide +// an xml::value_traits specialization. +// +std::ostream& +operator<< (std::ostream&, object_type); + +std::istream& +operator>> (std::istream&, object_type&); + +class position +{ +public: + position (float lat = 0, float lon = 0): lat_ (lat), lon_ (lon) {} + + float + lat () const {return lat_;} + + float + lon () const {return lon_;} + + // XML persistence. + // +public: + position (xml::parser&); + + void + serialize (xml::serializer&) const; + +private: + float lat_; + float lon_; +}; + +class object +{ +public: + object (const std::string& name, object_type type, unsigned int id) + : name_ (name), type_ (type), id_ (id) {} + + const std::string& + name () const {return name_;} + + object_type + type () const {return type_;} + + unsigned int + id () const {return id_;} + + typedef std::vector positions_type; + + positions_type& + positions () {return positions_;} + + const positions_type& + positions () const {return positions_;} + + // XML persistence. + // +public: + object (xml::parser&); + + void + serialize (xml::serializer&) const; + +private: + std::string name_; + object_type type_; + unsigned int id_; + positions_type positions_; +}; + +#endif // POSITION_HXX diff --git a/examples/persistence/position.xml b/examples/persistence/position.xml new file mode 100644 index 0000000..0dc5afa --- /dev/null +++ b/examples/persistence/position.xml @@ -0,0 +1,5 @@ + + + + + -- cgit v1.1