libhomegear-base  0.7
Base library for Homegear and Homegear family modules.
rapidxml.h
Go to the documentation of this file.
1 #ifndef RAPIDXML_HPP_INCLUDED
2 #define RAPIDXML_HPP_INCLUDED
3 
4 // Copyright (C) 2006, 2009 Marcin Kalicinski
5 // Version 1.13
6 // Revision $DateTime: 2009/05/13 01:46:17 $
8 
9 #include <cstdlib> // For std::size_t
10 #include <cassert> // For assert
11 #include <new> // For placement new
12 
13 #include <exception> // For std::exception
14 #include <ostream>
15 #include <iterator>
16 
17 namespace rapidxml
18 {
19 
31  class parse_error: public std::exception
32  {
33 
34  public:
35 
37  parse_error(const char *what, void *where);
38 
41  const char *what() const noexcept override;
42 
46  char *where() const;
47 
48  private:
49 
50  const char *m_what;
51  void *m_where;
52 
53  };
54 }
55 
57 // Pool sizes
58 
59 #ifndef RAPIDXML_STATIC_POOL_SIZE
60  // Size of static memory block of memory_pool.
61  // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
62  // No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
63  #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
64 #endif
65 
66 #ifndef RAPIDXML_DYNAMIC_POOL_SIZE
67  // Size of dynamic memory block of memory_pool.
68  // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
69  // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
70  #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
71 #endif
72 
73 #ifndef RAPIDXML_ALIGNMENT
74  // Memory allocation alignment.
75  // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
76  // All memory allocations for nodes, attributes and strings will be aligned to this value.
77  // This must be a power of 2 and at least 1, otherwise memory_pool will not work.
78  #define RAPIDXML_ALIGNMENT sizeof(void *)
79 #endif
80 
81 namespace rapidxml
82 {
83  class xml_node;
84  class xml_attribute;
85  class xml_document;
86 
89  enum node_type
90  {
99  };
100 
102  // Parsing flags
103 
109  const int parse_no_data_nodes = 0x1;
110 
118  const int parse_no_element_values = 0x2;
119 
126 
133 
139  const int parse_no_utf8 = 0x10;
140 
146  const int parse_declaration_node = 0x20;
147 
153  const int parse_comment_nodes = 0x40;
154 
161  const int parse_doctype_node = 0x80;
162 
168  const int parse_pi_nodes = 0x100;
169 
176  const int parse_validate_closing_tags = 0x200;
177 
184  const int parse_trim_whitespace = 0x400;
185 
193  const int parse_normalize_whitespace = 0x800;
194 
195  // Compound flags
196 
205  const int parse_default = 0;
206 
215  const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
216 
220  const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
221 
226  const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
227 
229  // Memory pool
230 
266  {
267 
268  public:
269 
271  typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory
272  typedef void (free_func)(void *); // Type of user-defined function used to free memory
274 
276  memory_pool();
277 
281  ~memory_pool();
282 
293  xml_node* allocate_node(node_type type, const char *name = nullptr, const char *value = nullptr, std::size_t name_size = 0, std::size_t value_size = 0);
294 
304  xml_attribute *allocate_attribute(const char *name = nullptr, const char *value = nullptr, std::size_t name_size = 0, std::size_t value_size = 0);
305 
313  char *allocate_string(const char *source = nullptr, std::size_t size = 0);
314 
324  xml_node *clone_node(const xml_node *source, xml_node *result = nullptr);
325 
329  void clear();
330 
344  void set_allocator(alloc_func *af, free_func *ff);
345 
346  private:
347 
348  struct header
349  {
350  char *previous_begin;
351  };
352 
353  void init();
354 
355  char *align(char *ptr);
356 
357  char *allocate_raw(std::size_t size);
358 
359  void *allocate_aligned(std::size_t size);
360 
361  char *m_begin; // Start of raw memory making up current pool
362  char *m_ptr; // First free byte in current pool
363  char *m_end; // One past last available byte in current pool
364  char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory
365  alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used
366  free_func *m_free_func; // Free function, or 0 if default is to be used
367  };
368 
370  // XML base
371 
375  class xml_base
376  {
377 
378  public:
379 
381  // Construction & destruction
382 
383  // Construct a base with empty name, value and parent
384  xml_base();
385 
387  // Node data access
388 
395  char *name() const;
396 
400  std::size_t name_size() const;
401 
408  char *value() const;
409 
413  std::size_t value_size() const;
414 
416  // Node modification
417 
431  void name(const char *name, std::size_t size);
432 
436  void name(const char *name);
437 
454  void value(const char *value, std::size_t size);
455 
459  void value(const char *value);
460 
462  // Related nodes access
463 
466  xml_node *parent() const;
467 
468  protected:
469 
470  // Return empty string
471  static char *nullstr();
472 
473  char *m_name; // Name of node, or 0 if no name
474  char *m_value; // Value of node, or 0 if no value
475  std::size_t m_name_size; // Length of node name, or undefined of no name
476  std::size_t m_value_size; // Length of node value, or undefined if no value
477  xml_node *m_parent; // Pointer to parent node, or 0 if none
478 
479  };
480 
486  class xml_attribute: public xml_base
487  {
488 
489  friend class xml_node;
490 
491  public:
492 
494  // Construction & destruction
495 
498  xml_attribute() = default;
499 
501  // Related nodes access
502 
505  xml_document *document() const;
506 
512  xml_attribute *previous_attribute(const char *name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const;
513 
519  xml_attribute *next_attribute(const char *name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const;
520 
521  private:
522 
523  xml_attribute *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
524  xml_attribute *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
525 
526  };
527 
529  // XML node
530 
539  class xml_node : public xml_base
540  {
541 
542  public:
543 
545  // Construction & destruction
546 
550  xml_node(node_type type);
551 
553  // Node data access
554 
557  node_type type() const;
558 
560  // Related nodes access
561 
564  xml_document *document() const;
565 
571  xml_node *first_node(const char *name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const;
572 
580  xml_node *last_node(const char *name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const;
581 
589  xml_node *previous_sibling(const char *name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const;
590 
598  xml_node *next_sibling(const char *name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const;
599 
605  xml_attribute *first_attribute(const char *name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const;
606 
612  xml_attribute *last_attribute(const char *name = nullptr, std::size_t name_size = 0, bool case_sensitive = true) const;
613 
615  // Node modification
616 
619  void type(node_type type);
620 
622  // Node manipulation
623 
627  void prepend_node(xml_node *child);
628 
632  void append_node(xml_node *child);
633 
638  void insert_node(xml_node *where, xml_node *child);
639 
643  void remove_first_node();
644 
648  void remove_last_node();
649 
651  // \param where Pointer to child to be removed.
652  void remove_node(xml_node *where);
653 
655  void remove_all_nodes();
656 
659  void prepend_attribute(xml_attribute *attribute);
660 
663  void append_attribute(xml_attribute *attribute);
664 
669  void insert_attribute(xml_attribute *where, xml_attribute *attribute);
670 
674  void remove_first_attribute();
675 
679  void remove_last_attribute();
680 
683  void remove_attribute(xml_attribute *where);
684 
686  void remove_all_attributes();
687 
688  private:
689 
691  // Restrictions
692 
693  // No copying
694  xml_node(const xml_node &);
695  void operator =(const xml_node &);
696 
698  // Data members
699 
700  // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.
701  // This is required for maximum performance, as it allows the parser to omit initialization of
702  // unneded/redundant values.
703  //
704  // The rules are as follows:
705  // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively
706  // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage
707  // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage
708 
709  node_type m_type; // Type of node; always valid
710  xml_node *m_first_node; // Pointer to first child node, or 0 if none; always valid
711  xml_node *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero
712  xml_attribute *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid
713  xml_attribute *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero
714  xml_node *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
715  xml_node *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
716 
717  };
718 
720  // XML document
721 
729  class xml_document: public xml_node, public memory_pool
730  {
731 
732  public:
733 
735  xml_document();
736 
748  template<int Flags>
749  void parse(char *text);
750 
753  void clear();
754 
755  private:
756 
758  // Internal character utility functions
759 
760  // Detect whitespace character
761  struct whitespace_pred
762  {
763  static unsigned char test(char ch);
764  };
765 
766  // Detect node name character
767  struct node_name_pred
768  {
769  static unsigned char test(char ch);
770  };
771 
772  // Detect attribute name character
773  struct attribute_name_pred
774  {
775  static unsigned char test(char ch);
776  };
777 
778  // Detect text character (PCDATA)
779  struct text_pred
780  {
781  static unsigned char test(char ch);
782  };
783 
784  // Detect text character (PCDATA) that does not require processing
785  struct text_pure_no_ws_pred
786  {
787  static unsigned char test(char ch);
788  };
789 
790  // Detect text character (PCDATA) that does not require processing
791  struct text_pure_with_ws_pred
792  {
793  static unsigned char test(char ch);
794  };
795 
796  // Detect attribute value character
797  template<char Quote>
798  struct attribute_value_pred
799  {
800  static unsigned char test(char ch);
801  };
802 
803  // Detect attribute value character
804  template<char Quote>
805  struct attribute_value_pure_pred
806  {
807  static unsigned char test(char ch);
808  };
809 
810  // Insert coded character, using UTF8 or 8-bit ASCII
811  template<int Flags>
812  static void insert_coded_character(char *&text, unsigned long code);
813 
814  // Skip characters until predicate evaluates to true
815  template<class StopPred, int Flags>
816  static void skip(char *&text);
817 
818  // Skip characters until predicate evaluates to true while doing the following:
819  // - replacing XML character entity references with proper characters (&apos; &amp; &quot; &lt; &gt; &#...;)
820  // - condensing whitespace sequences to single space character
821  template<class StopPred, class StopPredPure, int Flags>
822  static char *skip_and_expand_character_refs(char *&text);
823 
825  // Internal parsing functions
826 
827  // Parse BOM, if any
828  template<int Flags>
829  void parse_bom(char *&text);
830 
831  // Parse XML declaration (<?xml...)
832  template<int Flags>
833  xml_node *parse_xml_declaration(char *&text);
834 
835  // Parse XML comment (<!--...)
836  template<int Flags>
837  xml_node *parse_comment(char *&text);
838 
839  // Parse DOCTYPE
840  template<int Flags>
841  xml_node *parse_doctype(char *&text);
842 
843  // Parse PI
844  template<int Flags>
845  xml_node *parse_pi(char *&text);
846 
847  // Parse and append data
848  // Return character that ends data.
849  // This is necessary because this character might have been overwritten by a terminating 0
850  template<int Flags>
851  char parse_and_append_data(xml_node *node, char *&text, char *contents_start);
852 
853  // Parse CDATA
854  template<int Flags>
855  xml_node *parse_cdata(char *&text);
856 
857  // Parse element node
858  template<int Flags>
859  xml_node *parse_element(char *&text);
860 
861  // Determine node type, and parse it
862  template<int Flags>
863  xml_node *parse_node(char *&text);
864 
865  // Parse contents of the node - children, data etc.
866  template<int Flags>
867  void parse_node_contents(char *&text, xml_node *node);
868 
869  // Parse XML attributes of the node
870  template<int Flags>
871  void parse_node_attributes(char *&text, xml_node *node);
872 
873  };
874 }
875 
876 #endif
node_type
Enumeration listing all node types produced by the parser.
Definition: rapidxml.h:89
xml_node * m_parent
Definition: rapidxml.h:477
A comment node. Name is empty. Value contains comment text.
Definition: rapidxml.h:95
const int parse_full
A combination of parse flags resulting in largest amount of data being extracted. ...
Definition: rapidxml.h:226
Base class for xml_node and xml_attribute implementing common functions: name(), name_size(), value(), value_size() and parent().
Definition: rapidxml.h:375
const int parse_no_element_values
Parse flag instructing the parser to not use text of first data node as a value of parent element...
Definition: rapidxml.h:118
const int parse_no_entity_translation
Parse flag instructing the parser to not translate entities in the source text.
Definition: rapidxml.h:132
const int parse_no_data_nodes
Parse flag instructing the parser to not create data nodes.
Definition: rapidxml.h:109
const int parse_default
Parse flags which represent default behaviour of the parser.
Definition: rapidxml.h:205
A CDATA node. Name is empty. Value contains data text.
Definition: rapidxml.h:94
An element node. Name contains element name. Value contains text of first data node.
Definition: rapidxml.h:92
This class is used by the parser to create new nodes and attributes, without overheads of dynamic mem...
Definition: rapidxml.h:265
const int parse_validate_closing_tags
Parse flag instructing the parser to validate closing tag names.
Definition: rapidxml.h:176
const int parse_no_utf8
Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters...
Definition: rapidxml.h:139
A document node. Name and value are empty.
Definition: rapidxml.h:91
char * m_name
Definition: rapidxml.h:473
char * where() const
Gets pointer to character data where error happened.
Definition: rapidxml.cpp:347
std::size_t m_name_size
Definition: rapidxml.h:475
const int parse_comment_nodes
Parse flag instructing the parser to create comments nodes.
Definition: rapidxml.h:153
const int parse_pi_nodes
Parse flag instructing the parser to create PI nodes.
Definition: rapidxml.h:168
Parse error exception.
Definition: rapidxml.h:31
PVariable value
Definition: UiElements.h:217
const int parse_non_destructive
A combination of parse flags that forbids any modifications of the source text.
Definition: rapidxml.h:215
const int parse_declaration_node
Parse flag instructing the parser to create XML declaration node.
Definition: rapidxml.h:146
const int parse_trim_whitespace
Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes...
Definition: rapidxml.h:184
Class representing attribute node of XML document.
Definition: rapidxml.h:486
char * m_value
Definition: rapidxml.h:474
A data node. Name is empty. Value contains data text.
Definition: rapidxml.h:93
A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
Definition: rapidxml.h:97
A PI node. Name contains target. Value contains instructions.
Definition: rapidxml.h:98
A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalon...
Definition: rapidxml.h:96
std::size_t m_value_size
Definition: rapidxml.h:476
const int parse_normalize_whitespace
Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space cha...
Definition: rapidxml.h:193
const int parse_no_string_terminators
Parse flag instructing the parser to not place zero terminators after strings in the source text...
Definition: rapidxml.h:125
std::string name
Definition: UiElements.h:216
This class represents root of the DOM hierarchy.
Definition: rapidxml.h:729
Class representing a node of XML document.
Definition: rapidxml.h:539
Definition: BinaryPayload.h:38
const char * what() const noexcept override
Gets human readable description of error.
Definition: rapidxml.cpp:342
const int parse_fastest
A combination of parse flags resulting in fastest possible parsing, without sacrificing important dat...
Definition: rapidxml.h:220
parse_error(const char *what, void *where)
Constructs parse error.
Definition: rapidxml.cpp:338
#define RAPIDXML_STATIC_POOL_SIZE
Definition: rapidxml.h:63
const int parse_doctype_node
Parse flag instructing the parser to create DOCTYPE node.
Definition: rapidxml.h:161