aboutsummaryrefslogtreecommitdiff
path: root/examples/processing/driver.cxx
blob: e0f939d1cc08606fec02197920f9c23f61b75ad9 (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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// file      : examples/processing/driver.cxx
// copyright : not copyrighted - public domain

#include <string>
#include <fstream>
#include <iostream>

#include <xml/parser.hxx>
#include <xml/serializer.hxx>
#include <xml/value-traits.hxx>

using namespace std;
using namespace xml;

enum object_type {building, mountain};

// Specialization of xml::value_traits for object_type. This mechanism is
// used to implements XML-specific value type parsing and serialization.
// By default the parser and serializer fall back onto iostream insertion
// and extraction operators.
//
// This code also shows how we can reuse the parsing exception to implement
// our own diagnostics.
//
namespace xml
{
  template <>
  struct value_traits<object_type>
  {
    static object_type
    parse (string s, const parser& p)
    {
      if (s == "building")
        return building;
      else if (s == "mountain")
        return mountain;
      else
        throw parsing (p, "invalid object type '" + s + "'");
    }

    static string
    serialize (object_type x, const serializer&)
    {
      if (x == building)
        return "building";
      else
        return "mountain";
    }
  };
}

int
main (int argc, char* argv[])
{
  if (argc != 2)
  {
    cerr << "usage: " << argv[0] << " <xml-file>" << endl;
    return 1;
  }

  try
  {
    // Parse the input document and compute the average object position.
    //
    ifstream ifs (argv[1]);
    parser p (ifs, argv[1]);

    p.next_expect (parser::start_element, "object", content::complex);

    unsigned int id (p.attribute<unsigned int> ("id"));
    string name (p.element ("name"));
    object_type type (p.element<object_type> ("type"));

    float alat (0), alon (0);
    unsigned int count (0);

    do
    {
      p.next_expect (parser::start_element, "position", content::empty);

      float lat (p.attribute<float> ("lat"));
      float lon (p.attribute<float> ("lon"));

      p.next_expect (parser::end_element); // position

      alat += lat;
      alon += lon;
      count++;

    } while (p.peek () == parser::start_element);

    // Here is another example of re-using the parsing exception to
    // implement application-level diagnostics. Every object in our
    // vocabulary should have at least two position samples.
    //
    if (count < 2)
      throw parsing (p, "at least two position samples required");

    alat /= count;
    alon /= count;

    p.next_expect (parser::end_element); // object

    // Serialize an XML document with simulated positions based on the
    // average we just calculated.
    //
    serializer s (cout, "output");
    s.start_element ("object");

    s.attribute ("id", id);
    s.element ("name", name);
    s.element ("type", type);

    for (unsigned int i (0); i < 2; ++i)
    {
      for (unsigned int j (0); j < 2; ++j)
      {
        s.start_element ("position");

        float lat (alat + (i % 2 ? 0.0001F : -0.0001F));
        float lon (alon + (j % 2 ? -0.0001F : 0.0001F));

        s.attribute ("lat", lat);
        s.attribute ("lon", lon);

        s.end_element (); // position
      }
    }

    s.end_element (); // object
  }
  catch (const ios_base::failure&)
  {
    cerr << "io failure" << endl;
    return 1;
  }
  // This handler will handle both parsing (xml::parsing) and serialization
  // (xml::serialization) exceptions.
  //
  catch (const xml::exception& e)
  {
    cerr << e.what () << endl;
    return 1;
  }
}