File: mxml_document.h

package info (click to toggle)
falconpl 0.9.6.9-git20120606-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 46,176 kB
  • sloc: cpp: 181,389; ansic: 109,025; yacc: 2,310; xml: 1,218; sh: 403; objc: 245; makefile: 82; sql: 20
file content (234 lines) | stat: -rw-r--r-- 6,508 bytes parent folder | download | duplicates (2)
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/*
   Mini XML lib PLUS for C++

   Document class

   Author: Giancarlo Niccolai <gian@niccolai.ws>

*/

/** \file
   Document class implementation.
   This file contains the implementation of the xml document class.
   \see MXML::Document
*/

#ifndef MXML_DOCUMENT_H
#define MXML_DOCUMENT_H

#include <mxml_node.h>
#include <mxml_element.h>

namespace Falcon {
   class VMachine;
}

namespace MXML {

/** Class containing a logical XML file representation.

   To work with MXML, you need to instantiate at least one object from this class;
   this represents the logic of a document. It is derived for an element, as
   an XML document must still be valid as an XML element of another document,
   but it implements some data specific for handling documents.

   The class has the ability to parse a document into a node tree, deserializing
   it from a std::stream, and to output the document via the >> operator;
   virtual write() and read() functions overloading the element ones are
   also provided.

   The document has an (optional) style that is used on load and eventually on
   write. \see stylemacros
*/

class Document: public Element
{
private:
   Node *m_root;
   int m_style;
   Falcon::String m_encoding;

   // Useful just from find.
   Node::find_iterator m_finditer;
   Node::path_iterator m_pathiter;

public:

   /** Creates the document object.
      This constructor does not load any document, and sets the style parameter to
      nothing (all defaults). Style may be changed later on with the style(int)
      method, but you need to do it before the document si read() if you want to
      set some style affects document parsing.
      \param encoding Uses the given encoding
      \param style the mode in which the document is read/written
      \see stylemacros
      \see read
   */
   Document( const Falcon::String &encoding, const int style = 0 );

   /** Creates a deep copy of the document.
      Each node of the original document is replicated into another separated tree.
   */
   Document( Document &doc );

   /** Creates the document object and reads it.
      The parsing may be unsuccesful, or the reading may be faulty for a
      defective device; if this happens, a MalformedError is thrown.

      \param in the stream in which the data is read.
      \param style the mode in which the document is read/written
      \see stylemacros
   */
   Document( Falcon::Stream &in, const int style = 0 ) throw( MalformedError );

   /** Destroys the document.
      If you provided a stream at document creation, the stream is NOT colsed.
      It's up to the caller to destroy the stream and dispose of it cleanly.
   */
   ~Document();

   /** Returns the root node.
      The root node is \e always a root node type; this means that it has no name,
      attributes nor data: it's just a container for the other top level nodes.
   */
   Node *root() const { return m_root; }
   int style() const { return m_style; }
   void style( const int style ) { m_style = style; }

   /** Returns the currently used encoding.
      \note Default encoding is "C"
   */
   const Falcon::String encoding() const { return m_encoding; }

   /** Sets the preferred encoding.
      \note Used to create the main xml node; the actual encoder depends on the stream being used.
      \param enc an encoding ISO code.
   */
   void encoding( const Falcon::String &enc ) { m_encoding = enc; }

   /** Returns the main node, if it exists.
      Finds the main node, that is, the first (and one) tag type node at toplevel.
      If this node does not exists, it returns NULL.
      \return the main node or null
   */
   Node *main() const;

   /** Writes the document.
      \todo throw an exception on error, or return a value.
      Writes the document to the stream; in case of error the
      status of the document will be faulty.
      \see Node::write()
   */
   virtual void write( Falcon::Stream &stream, const int style ) const;

   virtual void write( Falcon::Stream &stream ) const
   {
      write( stream, style() );
   }

   /** Reads and parse the document.
      \todo throw an exception on error, or return a value.
      Reads the document from the stream; in case of error the
      status of the document will be faulty.

      Example:
      \code
      #include <mxml.h>
      #include <iostream>
      #include <fstream>
      ...
      MXML::Document *readXml()
      {
         ...
         ifstream test_file("test.xml");

         if (! test_file.is_open())
         {
            cout << "Error opening file" << endl;
            exit (1);
         }

         MXML::Document *xml_doc = new MXML::Document();
         try {
            xml_doc->read( test_file );
         }
         catch( MXML::Error &er )
         {
            std::cout << std::endl << er << std::endl;
            delete xml_doc;
            xml_doc = 0;
         }
         return xml_doc;
      }
      \endcode

      \param stream the input stream used for reading the data.
      \see Node::read()
   */
   virtual void read( Falcon::Stream &stream ) throw(MalformedError);

   /** Falcon MXML extension. */
   Node *find( const Falcon::String &name, const Falcon::String &attr,
               const Falcon::String &va, const Falcon::String &data )
   {
      m_finditer = m_root->find( name, attr, va, data );
      if( m_finditer != m_root->end() )
         return & (*m_finditer);
      return 0;
   }

   /** Falcon MXML extension. */
   Node *findNext() {
      if ( m_finditer == m_root->end() )
         return 0;

      if ( ++m_finditer != m_root->end() )
         return &(*m_finditer);
      return 0;
   }

   /** Falcon MXML extension. */
   Node *findPath( const Falcon::String &path )
   {
      m_pathiter = m_root->find_path( path );
      if( m_pathiter != m_root->end() )
         return & (*m_pathiter);
      return 0;
   }

   /** Falcon MXML extension. */
   Node *findNextPath() {
      if ( m_pathiter == m_root->end() )
         return 0;

      if ( ++m_pathiter != m_root->end() )
         return &(*m_pathiter);
      return 0;
   }
};

class DocumentCarrier: public Falcon::FalconData
{
   Document *m_doc;
public:

   DocumentCarrier( Document *doc ):
      m_doc( doc )
   {
   }

   virtual ~DocumentCarrier()
   {
      delete m_doc;
   }

   virtual void gcMark( Falcon::uint32 mk )  {};
   virtual Falcon::FalconData *clone() const { return 0; }

   Document *document() const { return m_doc; }
};

}
#endif

/* end of mxml_document.cpp */