Switch to unified view

a/libupnpp/expatmm.hxx b/libupnpp/expatmm.hxx
...
...
25
25
26
#include <string.h>
26
#include <string.h>
27
#include <expat.h>
27
#include <expat.h>
28
28
29
namespace expatmm {
29
namespace expatmm {
30
  class ExpatXMLParser {
30
class ExpatXMLParser {
31
  public:
31
public:
32
32
33
  /* Create a new parser, using the default Chunk Size */
33
    /* Create a new parser, using the default Chunk Size */
34
  ExpatXMLParser(void)
34
    ExpatXMLParser(void)
35
  {
35
        {
36
      init();
36
            init();
37
  }
37
        }
38
38
39
  /* Create a new parser, using a user-supplied chunk size */
39
    /* Create a new parser, using a user-supplied chunk size */
40
  ExpatXMLParser(size_t chunk_size)
40
    ExpatXMLParser(size_t chunk_size)
41
  {
41
        {
42
      init(chunk_size);
42
            init(chunk_size);
43
  }
43
        }
44
44
45
  /* Destructor that cleans up xml_buffer and parser */
45
    /* Destructor that cleans up xml_buffer and parser */
46
  virtual ~ExpatXMLParser(void)
46
    virtual ~ExpatXMLParser(void)
47
  {
47
        {
48
      valid_parser = false;
48
            valid_parser = false;
49
      if(expat_parser != NULL) {
49
            if(expat_parser != NULL) {
50
          XML_ParserFree(expat_parser);
50
                XML_ParserFree(expat_parser);
51
          expat_parser = NULL;
51
                expat_parser = NULL;
52
      }
52
            }
53
      if(xml_buffer != NULL) {
53
            if(xml_buffer != NULL) {
54
          delete xml_buffer;
54
                delete xml_buffer;
55
          xml_buffer = NULL;
55
                xml_buffer = NULL;
56
      }
56
            }
57
  }
57
        }
58
58
59
      /*
59
    /*
60
    Generic Parser. Most derivations will simply call this, rather
60
      Generic Parser. Most derivations will simply call this, rather
61
    than implement their own. This will loop, processing XML data
61
      than implement their own. This will loop, processing XML data
62
    and calling the necessary handler code until an error is encountered.
62
      and calling the necessary handler code until an error is encountered.
63
  */
63
    */
64
  virtual bool Parse(void)
64
    virtual bool Parse(void)
65
  {
65
        {
66
      /* Ensure that the parser is ready */
66
            /* Ensure that the parser is ready */
67
      if(!Ready())
67
            if(!Ready())
68
          return false;
68
                return false;
69
69
70
      ssize_t bytes_read;
70
            ssize_t bytes_read;
71
      /* Loop, reading the XML source block by block */
71
            /* Loop, reading the XML source block by block */
72
      while((bytes_read = read_block()) >= 0) {
72
            while((bytes_read = read_block()) >= 0) {
73
          if(bytes_read > 0) {
73
                if(bytes_read > 0) {
74
              XML_Status local_status =
74
                    XML_Status local_status =
75
                  XML_Parse(expat_parser, getReadBuffer(), bytes_read,
75
                        XML_Parse(expat_parser, getReadBuffer(), bytes_read,
76
                            XML_FALSE);
76
                                  XML_FALSE);
77
77
78
              if(local_status != XML_STATUS_OK) {
78
                    if(local_status != XML_STATUS_OK) {
79
                  status = local_status;
79
                        status = local_status;
80
                  last_error = XML_GetErrorCode(expat_parser);
80
                        last_error = XML_GetErrorCode(expat_parser);
81
                  break;
81
                        break;
82
              }
82
                    }
83
83
84
              /* Break on successful "short read", in event of EOF */
84
                    /* Break on successful "short read", in event of EOF */
85
              if(getLastError() == XML_ERROR_FINISHED)
85
                    if(getLastError() == XML_ERROR_FINISHED)
86
                  break;
86
                        break;
87
          }
87
                }
88
      }
88
            }
89
89
90
      /* Finalize the parser */
90
            /* Finalize the parser */
91
      if((getStatus() == XML_STATUS_OK) ||
91
            if((getStatus() == XML_STATUS_OK) ||
92
         (getLastError() == XML_ERROR_FINISHED)) {
92
               (getLastError() == XML_ERROR_FINISHED)) {
93
          XML_Parse(expat_parser, getBuffer(), 0, XML_TRUE);
93
                XML_Parse(expat_parser, getBuffer(), 0, XML_TRUE);
94
          return true;
94
                return true;
95
      }
95
            }
96
96
97
      /* Return false in the event of an error. The parser is
97
            /* Return false in the event of an error. The parser is
98
         not finalized on error. */
98
               not finalized on error. */
99
      return false;
99
            return false;
100
  }
100
        }
101
101
102
  /* Expose status, error, and control codes to users */
102
    /* Expose status, error, and control codes to users */
103
  virtual bool Ready(void) { return valid_parser; };
103
    virtual bool Ready(void) { return valid_parser; };
104
  virtual XML_Error getLastError(void) { return last_error; };
104
    virtual XML_Error getLastError(void) { return last_error; };
105
  virtual XML_Status getStatus(void) { return status; };
105
    virtual XML_Status getStatus(void) { return status; };
106
106
107
  protected:
107
protected:
108
  virtual XML_Char *getBuffer(void) { return xml_buffer; };
108
    virtual XML_Char *getBuffer(void) { return xml_buffer; };
109
  virtual const char *getReadBuffer(void) { return xml_buffer; };
109
    virtual const char *getReadBuffer(void) { return xml_buffer; };
110
  virtual size_t getBlockSize(void) { return xml_buffer_size; };
110
    virtual size_t getBlockSize(void) { return xml_buffer_size; };
111
111
112
  /* Read XML data.
112
    /* Read XML data.
113
   *
113
     *
114
   * Override this to implement your container-specific parser.
114
     * Override this to implement your container-specific parser.
115
   *
115
     *
116
   * You must:
116
     * You must:
117
   * put new XML data into xml_buffer
117
     * put new XML data into xml_buffer
118
   * set status
118
     * set status
119
   * set last_error
119
     * set last_error
120
   * return the amount of XML_Char's written to xml_buffer
120
     * return the amount of XML_Char's written to xml_buffer
121
   *
121
     *
122
   * on error, return < 0. The contents of xml_buffer will be
122
     * on error, return < 0. The contents of xml_buffer will be
123
   * thrown away in this event, so it is the derived class's
123
     * thrown away in this event, so it is the derived class's
124
   * responsibility to reseek the "data cursor" to re-get any
124
     * responsibility to reseek the "data cursor" to re-get any
125
   * data in the buffer on an error condition.
125
     * data in the buffer on an error condition.
126
   *
126
     *
127
   * Use setReadiness, setStatus, and setLastError to handle
127
     * Use setReadiness, setStatus, and setLastError to handle
128
   * error, status, and control events and codes.
128
     * error, status, and control events and codes.
129
   *
129
     *
130
   * The default implementation returns "no elements" if it is
130
     * The default implementation returns "no elements" if it is
131
   * ever called. and should be overridden by the derived class.
131
     * ever called. and should be overridden by the derived class.
132
   *
132
     *
133
   * Note that, as the actual parser only uses
133
     * Note that, as the actual parser only uses
134
   * getBuffer()/getBlockSize()/read_block() (no direct access
134
     * getBuffer()/getBlockSize()/read_block() (no direct access
135
   * to the buffer), you are free to use an entirely different
135
     * to the buffer), you are free to use an entirely different
136
   * I/O mechanism, like what does the inputRefXMLParser below.
136
     * I/O mechanism, like what does the inputRefXMLParser below.
137
   */
137
     */
138
  virtual ssize_t read_block(void)
138
    virtual ssize_t read_block(void)
139
  {
139
        {
140
      last_error = XML_ERROR_NO_ELEMENTS;
140
            last_error = XML_ERROR_NO_ELEMENTS;
141
      status = XML_STATUS_ERROR;
141
            status = XML_STATUS_ERROR;
142
      return -1;
142
            return -1;
143
  }
143
        }
144
144
145
  virtual void setReadiness(bool ready)
145
    virtual void setReadiness(bool ready)
146
  {
146
        {
147
      valid_parser = ready;
147
            valid_parser = ready;
148
  }
148
        }
149
  virtual void setStatus(XML_Status new_status)
149
    virtual void setStatus(XML_Status new_status)
150
  {
150
        {
151
      status = new_status;
151
            status = new_status;
152
  }
152
        }
153
  virtual void setLastError(XML_Error new_last_error)
153
    virtual void setLastError(XML_Error new_last_error)
154
  {
154
        {
155
      last_error = new_last_error;
155
            last_error = new_last_error;
156
  };
156
        };
157
157
158
  /* Methods to be overriden */
158
    /* Methods to be overriden */
159
  virtual void StartElement(const XML_Char *,
159
    virtual void StartElement(const XML_Char *,
160
                const XML_Char **) {}
160
                              const XML_Char **) {}
161
  virtual void EndElement(const XML_Char *) {}
161
    virtual void EndElement(const XML_Char *) {}
162
  virtual void CharacterData(const XML_Char *, int) {}
162
    virtual void CharacterData(const XML_Char *, int) {}
163
  virtual void ProcessingInstruction(const XML_Char *,
163
    virtual void ProcessingInstruction(const XML_Char *,
164
                     const XML_Char *) {}
164
                                       const XML_Char *) {}
165
  virtual void CommentData(const XML_Char *) {}
165
    virtual void CommentData(const XML_Char *) {}
166
  virtual void DefaultHandler(const XML_Char *, int) {}
166
    virtual void DefaultHandler(const XML_Char *, int) {}
167
  virtual void CDataStart(void) {}
167
    virtual void CDataStart(void) {}
168
  virtual void CDataEnd(void) {}
168
    virtual void CDataEnd(void) {}
169
169
170
    /* The handle for the parser (expat) */
171
    XML_Parser expat_parser;
172
170
  private:
173
private:
171
  /* The handle for the parser (expat) */
172
  XML_Parser expat_parser;
173
174
174
  /* Temporary buffer where data is streamed in */
175
    /* Temporary buffer where data is streamed in */
175
  XML_Char *xml_buffer;
176
    XML_Char *xml_buffer;
176
  size_t xml_buffer_size;
177
    size_t xml_buffer_size;
177
178
178
  /* Tells if the parser is ready to accept data */
179
    /* Tells if the parser is ready to accept data */
179
  bool valid_parser;
180
    bool valid_parser;
180
181
181
  /* Status and Error codes in the event of unforseen events */
182
    /* Status and Error codes in the event of unforseen events */
182
  XML_Status status;
183
    XML_Status status;
183
  XML_Error last_error;
184
    XML_Error last_error;
184
185
185
  /* Expat callbacks.
186
    /* Expat callbacks.
186
   * The expatmm protocol is to pass (this) as the userData argument
187
     * The expatmm protocol is to pass (this) as the userData argument
187
   * in the XML_Parser structure. These static methods will convert
188
     * in the XML_Parser structure. These static methods will convert
188
   * handlers into upcalls to the instantiated class's virtual members
189
     * handlers into upcalls to the instantiated class's virtual members
189
   * to do the actual handling work. */
190
     * to do the actual handling work. */
190
  static void _element_start_handler(void *userData, const XML_Char *name,
191
    static void _element_start_handler(void *userData, const XML_Char *name,
191
                     const XML_Char **atts)
192
                                       const XML_Char **atts)
192
  {
193
        {
193
      ExpatXMLParser *me = (ExpatXMLParser*)userData;
194
            ExpatXMLParser *me = (ExpatXMLParser*)userData;
194
      if(me != NULL) me->StartElement(name, atts);
195
            if(me != NULL) me->StartElement(name, atts);
195
  }
196
        }
196
  static void _element_end_handler(void *userData, const XML_Char *name)
197
    static void _element_end_handler(void *userData, const XML_Char *name)
197
  {
198
        {
198
      ExpatXMLParser *me = (ExpatXMLParser*)userData;
199
            ExpatXMLParser *me = (ExpatXMLParser*)userData;
199
      if(me != NULL) me->EndElement(name);
200
            if(me != NULL) me->EndElement(name);
200
  }
201
        }
201
  static void _character_data_handler(void *userData,
202
    static void _character_data_handler(void *userData,
202
                      const XML_Char *s, int len)
203
                                        const XML_Char *s, int len)
203
  {
204
        {
204
      ExpatXMLParser *me = (ExpatXMLParser*)userData;
205
            ExpatXMLParser *me = (ExpatXMLParser*)userData;
205
      if(me != NULL) me->CharacterData(s, len);
206
            if(me != NULL) me->CharacterData(s, len);
206
  }
207
        }
207
  static void _processing_instr_handler(void *userData,
208
    static void _processing_instr_handler(void *userData,
208
                        const XML_Char *target,
209
                                          const XML_Char *target,
209
                        const XML_Char *data)
210
                                          const XML_Char *data)
210
  {
211
        {
211
      ExpatXMLParser *me = (ExpatXMLParser*)userData;
212
            ExpatXMLParser *me = (ExpatXMLParser*)userData;
212
      if(me != NULL) me->ProcessingInstruction(target, data);
213
            if(me != NULL) me->ProcessingInstruction(target, data);
213
  }
214
        }
214
  static void _comment_handler(void *userData, const XML_Char *data)
215
    static void _comment_handler(void *userData, const XML_Char *data)
215
  {
216
        {
216
      ExpatXMLParser *me = (ExpatXMLParser*)userData;
217
            ExpatXMLParser *me = (ExpatXMLParser*)userData;
217
      if(me != NULL) me->CommentData(data);
218
            if(me != NULL) me->CommentData(data);
218
  }
219
        }
219
  static void _default_handler(void *userData, const XML_Char *s, int len)
220
    static void _default_handler(void *userData, const XML_Char *s, int len)
220
  {
221
        {
221
      ExpatXMLParser *me = (ExpatXMLParser*)userData;
222
            ExpatXMLParser *me = (ExpatXMLParser*)userData;
222
      if(me != NULL) me->DefaultHandler(s, len);
223
            if(me != NULL) me->DefaultHandler(s, len);
223
  }
224
        }
224
  static void _cdata_start_handler(void *userData)
225
    static void _cdata_start_handler(void *userData)
225
  {
226
        {
226
      ExpatXMLParser *me = (ExpatXMLParser*)userData;
227
            ExpatXMLParser *me = (ExpatXMLParser*)userData;
227
      if(me != NULL) me->CDataStart();
228
            if(me != NULL) me->CDataStart();
228
  }
229
        }
229
  static void _cdata_end_handler(void *userData)
230
    static void _cdata_end_handler(void *userData)
230
  {
231
        {
231
      ExpatXMLParser *me = (ExpatXMLParser*)userData;
232
            ExpatXMLParser *me = (ExpatXMLParser*)userData;
232
      if(me != NULL) me->CDataEnd();
233
            if(me != NULL) me->CDataEnd();
233
  }
234
        }
234
      /* Register our static handlers with the Expat events. */
235
    /* Register our static handlers with the Expat events. */
235
  void register_default_handlers()
236
    void register_default_handlers()
236
  {
237
        {
237
      XML_SetElementHandler(expat_parser, &_element_start_handler,
238
            XML_SetElementHandler(expat_parser, &_element_start_handler,
238
                &_element_end_handler);
239
                                  &_element_end_handler);
239
      XML_SetCharacterDataHandler(expat_parser, &_character_data_handler);
240
            XML_SetCharacterDataHandler(expat_parser, &_character_data_handler);
240
      XML_SetProcessingInstructionHandler(expat_parser,
241
            XML_SetProcessingInstructionHandler(expat_parser,
241
                      &_processing_instr_handler);
242
                                                &_processing_instr_handler);
242
      XML_SetCommentHandler(expat_parser, &_comment_handler);
243
            XML_SetCommentHandler(expat_parser, &_comment_handler);
243
      XML_SetCdataSectionHandler(expat_parser, &_cdata_start_handler,
244
            XML_SetCdataSectionHandler(expat_parser, &_cdata_start_handler,
244
                     &_cdata_end_handler);
245
                                       &_cdata_end_handler);
245
      XML_SetDefaultHandler(expat_parser, &_default_handler);
246
            XML_SetDefaultHandler(expat_parser, &_default_handler);
246
  }
247
        }
247
  /* Constructor common code */
248
    /* Constructor common code */
248
  void init(size_t chunk_size = 0)
249
    void init(size_t chunk_size = 0)
249
  {
250
        {
250
      valid_parser = false;
251
            valid_parser = false;
251
      expat_parser = NULL;
252
            expat_parser = NULL;
252
      xml_buffer_size = chunk_size ? chunk_size : 10240;
253
            xml_buffer_size = chunk_size ? chunk_size : 10240;
253
      xml_buffer = new XML_Char[xml_buffer_size];
254
            xml_buffer = new XML_Char[xml_buffer_size];
254
      if(xml_buffer == NULL)
255
            if(xml_buffer == NULL)
255
          return;
256
                return;
256
      expat_parser = XML_ParserCreate(NULL);
257
            expat_parser = XML_ParserCreate(NULL);
257
258
258
      if(expat_parser == NULL) {
259
            if(expat_parser == NULL) {
259
          delete xml_buffer;
260
                delete xml_buffer;
260
          xml_buffer = NULL;
261
                xml_buffer = NULL;
261
          return;
262
                return;
262
      }
263
            }
263
      status = XML_STATUS_OK;
264
            status = XML_STATUS_OK;
264
      last_error = XML_ERROR_NONE;
265
            last_error = XML_ERROR_NONE;
265
266
266
      memset(xml_buffer, 0, chunk_size * sizeof(XML_Char));
267
            memset(xml_buffer, 0, chunk_size * sizeof(XML_Char));
267
268
268
      /* Set the "ready" flag on this parser */
269
            /* Set the "ready" flag on this parser */
269
      valid_parser = true;
270
            valid_parser = true;
270
      XML_SetUserData(expat_parser, (void*)this);
271
            XML_SetUserData(expat_parser, (void*)this);
271
      register_default_handlers();
272
            register_default_handlers();
272
  }
273
        }
273
  };
274
};
274
275
275
    /** A specialization of ExpatXMLParser that does not copy its input */
276
/** A specialization of ExpatXMLParser that does not copy its input */
276
  class inputRefXMLParser : public ExpatXMLParser {
277
class inputRefXMLParser : public ExpatXMLParser {
277
  public:
278
public:
278
      // Beware: we only use a ref to input to minimize copying. This means
279
    // Beware: we only use a ref to input to minimize copying. This means
279
      // that storage for the input parameter must persist until you are done
280
    // that storage for the input parameter must persist until you are done
280
      // with the parser object !
281
    // with the parser object !
281
      inputRefXMLParser(const std::string& input)
282
    inputRefXMLParser(const std::string& input)
282
          : ExpatXMLParser(1), // Have to allocate a small buf even if not used.
283
        : ExpatXMLParser(1), // Have to allocate a small buf even if not used.
283
            m_input(input)
284
          m_input(input)
284
          {}
285
        {}
285
286
286
  protected:
287
protected:
287
      ssize_t read_block(void)
288
    ssize_t read_block(void)
288
          {
289
        {
289
              if (getLastError() == XML_ERROR_FINISHED) {
290
            if (getLastError() == XML_ERROR_FINISHED) {
290
                  setStatus(XML_STATUS_OK);
291
                setStatus(XML_STATUS_OK);
291
                  return -1;
292
                return -1;
292
              }
293
            }
293
              setLastError(XML_ERROR_FINISHED);
294
            setLastError(XML_ERROR_FINISHED);
294
              return m_input.size();
295
            return m_input.size();
295
          }
296
        }
296
      const char *getReadBuffer()
297
    const char *getReadBuffer()
297
          {
298
        {
298
              return m_input.c_str();
299
            return m_input.c_str();
299
          }
300
        }
300
      virtual size_t getBlockSize(void)
301
    virtual size_t getBlockSize(void)
301
          {
302
        {
302
              return m_input.size();
303
            return m_input.size();
303
          }
304
        }
304
  private:
305
protected:
305
      const std::string& m_input;
306
    const std::string& m_input;
306
  };
307
};
307
308
308
}; // End namespace expatmm
309
}; // End namespace expatmm
309
310
310
#endif /* _EXPATMM_EXPATXMLPARSER_H */
311
#endif /* _EXPATMM_EXPATXMLPARSER_H */
311
/* Local Variables: */
312
/* mode: c++ */
313
/* c-basic-offset: 4 */
314
/* tab-width: 4 */
315
/* indent-tabs-mode: t */
316
/* End: */