aboutsummaryrefslogtreecommitdiff
path: root/examples/persistence/position.cxx
blob: 9f4f70187dbd871f36d3740e910be099f1410642 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// file      : examples/persistence/position.cxx
// copyright : not copyrighted - public domain

#include <iostream>

#include <xml/parser.hxx>
#include <xml/serializer.hxx>

#include "position.hxx"

using namespace std;
using namespace xml;

// position
//
position::
position (parser& p)
    : lat_ (p.attribute<float> ("lat")),
      lon_ (p.attribute<float> ("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<object_type> ("type");
  id_ = p.attribute<unsigned int> ("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;
}