PageRenderTime 149ms CodeModel.GetById 18ms app.highlight 102ms RepoModel.GetById 6ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/property_tree/detail/rapidxml.hpp

http://hadesmem.googlecode.com/
C++ Header | 2594 lines | 1892 code | 179 blank | 523 comment | 188 complexity | 0dc110ca680cb20ea449c6c86862993a MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1// ----------------------------------------------------------------------------
   2// Copyright (C) 2006, 2009 Marcin Kalicinski
   3//
   4// Distributed under the Boost Software License, Version 1.0. 
   5// (See accompanying file LICENSE_1_0.txt or copy at 
   6// http://www.boost.org/LICENSE_1_0.txt)
   7//
   8// For more information, see www.boost.org
   9// ----------------------------------------------------------------------------
  10#ifndef BOOST_PROPERTY_TREE_RAPIDXML_HPP_INCLUDED
  11#define BOOST_PROPERTY_TREE_RAPIDXML_HPP_INCLUDED
  12
  13//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation
  14
  15#include <boost/assert.hpp>
  16#include <cstdlib>      // For std::size_t
  17#include <new>          // For placement new
  18
  19// On MSVC, disable "conditional expression is constant" warning (level 4). 
  20// This warning is almost impossible to avoid with certain types of templated code
  21#ifdef _MSC_VER
  22    #pragma warning(push)
  23    #pragma warning(disable:4127)   // Conditional expression is constant
  24#endif
  25
  26///////////////////////////////////////////////////////////////////////////
  27// BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR
  28    
  29#include <exception>    // For std::exception
  30
  31#define BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where)
  32
  33namespace boost { namespace property_tree { namespace detail {namespace rapidxml
  34{
  35
  36    //! Parse error exception. 
  37    //! This exception is thrown by the parser when an error occurs. 
  38    //! Use what() function to get human-readable error message. 
  39    //! Use where() function to get a pointer to position within source text where error was detected.
  40    //! <br><br>
  41    //! If throwing exceptions by the parser is undesirable, 
  42    //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.
  43    //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.
  44    //! This function must be defined by the user.
  45    //! <br><br>
  46    //! This class derives from <code>std::exception</code> class.
  47    class parse_error: public std::exception
  48    {
  49    
  50    public:
  51    
  52        //! Constructs parse error
  53        parse_error(const char *wa, void *we)
  54            : m_what(wa)
  55            , m_where(we)
  56        {
  57        }
  58
  59        //! Gets human readable description of error.
  60        //! \return Pointer to null terminated description of the error.
  61        virtual const char *what() const throw()
  62        {
  63            return m_what;
  64        }
  65
  66        //! Gets pointer to character data where error happened.
  67        //! Ch should be the same as char type of xml_document that produced the error.
  68        //! \return Pointer to location within the parsed string where error occured.
  69        template<class Ch>
  70        Ch *where() const
  71        {
  72            return reinterpret_cast<Ch *>(m_where);
  73        }
  74
  75    private:  
  76
  77        const char *m_what;
  78        void *m_where;
  79
  80    };
  81}}}}
  82
  83///////////////////////////////////////////////////////////////////////////
  84// Pool sizes
  85
  86#ifndef BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE
  87    // Size of static memory block of memory_pool.
  88    // Define BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
  89    // No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
  90    #define BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
  91#endif
  92
  93#ifndef BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE
  94    // Size of dynamic memory block of memory_pool.
  95    // Define BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
  96    // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
  97    #define BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
  98#endif
  99
 100#ifndef BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT
 101    // Memory allocation alignment.
 102    // Define BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
 103    // All memory allocations for nodes, attributes and strings will be aligned to this value.
 104    // This must be a power of 2 and at least 1, otherwise memory_pool will not work.
 105    #define BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT sizeof(void *)
 106#endif
 107
 108namespace boost { namespace property_tree { namespace detail {namespace rapidxml
 109{
 110    // Forward declarations
 111    template<class Ch> class xml_node;
 112    template<class Ch> class xml_attribute;
 113    template<class Ch> class xml_document;
 114    
 115    //! Enumeration listing all node types produced by the parser.
 116    //! Use xml_node::type() function to query node type.
 117    enum node_type
 118    {
 119        node_document,      //!< A document node. Name and value are empty.
 120        node_element,       //!< An element node. Name contains element name. Value contains text of first data node.
 121        node_data,          //!< A data node. Name is empty. Value contains data text.
 122        node_cdata,         //!< A CDATA node. Name is empty. Value contains data text.
 123        node_comment,       //!< A comment node. Name is empty. Value contains comment text.
 124        node_declaration,   //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
 125        node_doctype,       //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
 126        node_pi             //!< A PI node. Name contains target. Value contains instructions.
 127    };
 128
 129    ///////////////////////////////////////////////////////////////////////
 130    // Parsing flags
 131
 132    //! Parse flag instructing the parser to not create data nodes. 
 133    //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.
 134    //! Can be combined with other flags by use of | operator.
 135    //! <br><br>
 136    //! See xml_document::parse() function.
 137    const int parse_no_data_nodes = 0x1;            
 138
 139    //! Parse flag instructing the parser to not use text of first data node as a value of parent element.
 140    //! Can be combined with other flags by use of | operator.
 141    //! Note that child data nodes of element node take precendence over its value when printing. 
 142    //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.
 143    //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.
 144    //! <br><br>
 145    //! See xml_document::parse() function.
 146    const int parse_no_element_values = 0x2;
 147    
 148    //! Parse flag instructing the parser to not place zero terminators after strings in the source text.
 149    //! By default zero terminators are placed, modifying source text.
 150    //! Can be combined with other flags by use of | operator.
 151    //! <br><br>
 152    //! See xml_document::parse() function.
 153    const int parse_no_string_terminators = 0x4;
 154    
 155    //! Parse flag instructing the parser to not translate entities in the source text.
 156    //! By default entities are translated, modifying source text.
 157    //! Can be combined with other flags by use of | operator.
 158    //! <br><br>
 159    //! See xml_document::parse() function.
 160    const int parse_no_entity_translation = 0x8;
 161    
 162    //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.
 163    //! By default, UTF-8 handling is enabled.
 164    //! Can be combined with other flags by use of | operator.
 165    //! <br><br>
 166    //! See xml_document::parse() function.
 167    const int parse_no_utf8 = 0x10;
 168    
 169    //! Parse flag instructing the parser to create XML declaration node.
 170    //! By default, declaration node is not created.
 171    //! Can be combined with other flags by use of | operator.
 172    //! <br><br>
 173    //! See xml_document::parse() function.
 174    const int parse_declaration_node = 0x20;
 175    
 176    //! Parse flag instructing the parser to create comments nodes.
 177    //! By default, comment nodes are not created.
 178    //! Can be combined with other flags by use of | operator.
 179    //! <br><br>
 180    //! See xml_document::parse() function.
 181    const int parse_comment_nodes = 0x40;
 182    
 183    //! Parse flag instructing the parser to create DOCTYPE node.
 184    //! By default, doctype node is not created.
 185    //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.
 186    //! Can be combined with other flags by use of | operator.
 187    //! <br><br>
 188    //! See xml_document::parse() function.
 189    const int parse_doctype_node = 0x80;
 190    
 191    //! Parse flag instructing the parser to create PI nodes.
 192    //! By default, PI nodes are not created.
 193    //! Can be combined with other flags by use of | operator.
 194    //! <br><br>
 195    //! See xml_document::parse() function.
 196    const int parse_pi_nodes = 0x100;
 197    
 198    //! Parse flag instructing the parser to validate closing tag names. 
 199    //! If not set, name inside closing tag is irrelevant to the parser.
 200    //! By default, closing tags are not validated.
 201    //! Can be combined with other flags by use of | operator.
 202    //! <br><br>
 203    //! See xml_document::parse() function.
 204    const int parse_validate_closing_tags = 0x200;
 205    
 206    //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.
 207    //! By default, whitespace is not trimmed. 
 208    //! This flag does not cause the parser to modify source text.
 209    //! Can be combined with other flags by use of | operator.
 210    //! <br><br>
 211    //! See xml_document::parse() function.
 212    const int parse_trim_whitespace = 0x400;
 213
 214    //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.
 215    //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.
 216    //! By default, whitespace is not normalized. 
 217    //! If this flag is specified, source text will be modified.
 218    //! Can be combined with other flags by use of | operator.
 219    //! <br><br>
 220    //! See xml_document::parse() function.
 221    const int parse_normalize_whitespace = 0x800;
 222
 223    // Compound flags
 224    
 225    //! Parse flags which represent default behaviour of the parser. 
 226    //! This is always equal to 0, so that all other flags can be simply ored together.
 227    //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.
 228    //! This also means that meaning of each flag is a <i>negation</i> of the default setting. 
 229    //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,
 230    //! and using the flag will disable it.
 231    //! <br><br>
 232    //! See xml_document::parse() function.
 233    const int parse_default = 0;
 234    
 235    //! A combination of parse flags that forbids any modifications of the source text. 
 236    //! This also results in faster parsing. However, note that the following will occur:
 237    //! <ul>
 238    //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>
 239    //! <li>entities will not be translated</li>
 240    //! <li>whitespace will not be normalized</li>
 241    //! </ul>
 242    //! See xml_document::parse() function.
 243    const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
 244    
 245    //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.
 246    //! <br><br>
 247    //! See xml_document::parse() function.
 248    const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
 249    
 250    //! A combination of parse flags resulting in largest amount of data being extracted. 
 251    //! This usually results in slowest parsing.
 252    //! <br><br>
 253    //! See xml_document::parse() function.
 254    const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
 255
 256    ///////////////////////////////////////////////////////////////////////
 257    // Internals
 258
 259    //! \cond internal
 260    namespace internal
 261    {
 262
 263        // Struct that contains lookup tables for the parser
 264        // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).
 265        template<int Dummy>
 266        struct lookup_tables
 267        {
 268            static const unsigned char lookup_whitespace[256];              // Whitespace table
 269            static const unsigned char lookup_node_name[256];               // Node name table
 270            static const unsigned char lookup_text[256];                    // Text table
 271            static const unsigned char lookup_text_pure_no_ws[256];         // Text table
 272            static const unsigned char lookup_text_pure_with_ws[256];       // Text table
 273            static const unsigned char lookup_attribute_name[256];          // Attribute name table
 274            static const unsigned char lookup_attribute_data_1[256];        // Attribute data table with single quote
 275            static const unsigned char lookup_attribute_data_1_pure[256];   // Attribute data table with single quote
 276            static const unsigned char lookup_attribute_data_2[256];        // Attribute data table with double quotes
 277            static const unsigned char lookup_attribute_data_2_pure[256];   // Attribute data table with double quotes
 278            static const unsigned char lookup_digits[256];                  // Digits
 279            static const unsigned char lookup_upcase[256];                  // To uppercase conversion table for ASCII characters
 280        };
 281
 282        // Find length of the string
 283        template<class Ch>
 284        inline std::size_t measure(const Ch *p)
 285        {
 286            const Ch *tmp = p;
 287            while (*tmp) 
 288                ++tmp;
 289            return tmp - p;
 290        }
 291
 292        // Compare strings for equality
 293        template<class Ch>
 294        inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive)
 295        {
 296            if (size1 != size2)
 297                return false;
 298            if (case_sensitive)
 299            {
 300                for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
 301                    if (*p1 != *p2)
 302                        return false;
 303            }
 304            else
 305            {
 306                for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
 307                    if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])
 308                        return false;
 309            }
 310            return true;
 311        }
 312
 313        template<class Ch>
 314        inline size_t get_index(const Ch c)
 315        {
 316            // If not ASCII char, its semantic is same as plain 'z'.
 317            // char could be signed, so first stretch and make unsigned.
 318            unsigned n = c;
 319            if (n > 127)
 320            {
 321                return 'z';
 322            }
 323            return c;
 324        }
 325    }
 326    //! \endcond
 327
 328    ///////////////////////////////////////////////////////////////////////
 329    // Memory pool
 330    
 331    //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.
 332    //! In most cases, you will not need to use this class directly. 
 333    //! However, if you need to create nodes manually or modify names/values of nodes, 
 334    //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. 
 335    //! Not only is this faster than allocating them by using <code>new</code> operator, 
 336    //! but also their lifetime will be tied to the lifetime of document, 
 337    //! possibly simplyfing memory management. 
 338    //! <br><br>
 339    //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. 
 340    //! You can also call allocate_string() function to allocate strings.
 341    //! Such strings can then be used as names or values of nodes without worrying about their lifetime.
 342    //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called, 
 343    //! or when the pool is destroyed.
 344    //! <br><br>
 345    //! It is also possible to create a standalone memory_pool, and use it 
 346    //! to allocate nodes, whose lifetime will not be tied to any document.
 347    //! <br><br>
 348    //! Pool maintains <code>BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory. 
 349    //! Until static memory is exhausted, no dynamic memory allocations are done.
 350    //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE</code> each,
 351    //! by using global <code>new[]</code> and <code>delete[]</code> operators. 
 352    //! This behaviour can be changed by setting custom allocation routines. 
 353    //! Use set_allocator() function to set them.
 354    //! <br><br>
 355    //! Allocations for nodes, attributes and strings are aligned at <code>BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT</code> bytes.
 356    //! This value defaults to the size of pointer on target architecture.
 357    //! <br><br>
 358    //! To obtain absolutely top performance from the parser,
 359    //! it is important that all nodes are allocated from a single, contiguous block of memory.
 360    //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.
 361    //! If required, you can tweak <code>BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE</code>, <code>BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT</code> 
 362    //! to obtain best wasted memory to performance compromise.
 363    //! To do it, define their values before rapidxml.hpp file is included.
 364    //! \param Ch Character type of created nodes. 
 365    template<class Ch = char>
 366    class memory_pool
 367    {
 368        
 369    public:
 370
 371        //! \cond internal
 372        typedef void *(alloc_func)(std::size_t);       // Type of user-defined function used to allocate memory
 373        typedef void (free_func)(void *);              // Type of user-defined function used to free memory
 374        //! \endcond
 375        
 376        //! Constructs empty pool with default allocator functions.
 377        memory_pool()
 378            : m_alloc_func(0)
 379            , m_free_func(0)
 380        {
 381            init();
 382        }
 383
 384        //! Destroys pool and frees all the memory. 
 385        //! This causes memory occupied by nodes allocated by the pool to be freed.
 386        //! Nodes allocated from the pool are no longer valid.
 387        ~memory_pool()
 388        {
 389            clear();
 390        }
 391
 392        //! Allocates a new node from the pool, and optionally assigns name and value to it. 
 393        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
 394        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
 395        //! will call rapidxml::parse_error_handler() function.
 396        //! \param type Type of node to create.
 397        //! \param name Name to assign to the node, or 0 to assign no name.
 398        //! \param value Value to assign to the node, or 0 to assign no value.
 399        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
 400        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
 401        //! \return Pointer to allocated node. This pointer will never be NULL.
 402        xml_node<Ch> *allocate_node(node_type type, 
 403                                    const Ch *name = 0, const Ch *value = 0, 
 404                                    std::size_t name_size = 0, std::size_t value_size = 0)
 405        {
 406            void *memory = allocate_aligned(sizeof(xml_node<Ch>));
 407            xml_node<Ch> *node = new(memory) xml_node<Ch>(type);
 408            if (name)
 409            {
 410                if (name_size > 0)
 411                    node->name(name, name_size);
 412                else
 413                    node->name(name);
 414            }
 415            if (value)
 416            {
 417                if (value_size > 0)
 418                    node->value(value, value_size);
 419                else
 420                    node->value(value);
 421            }
 422            return node;
 423        }
 424
 425        //! Allocates a new attribute from the pool, and optionally assigns name and value to it.
 426        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
 427        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
 428        //! will call rapidxml::parse_error_handler() function.
 429        //! \param name Name to assign to the attribute, or 0 to assign no name.
 430        //! \param value Value to assign to the attribute, or 0 to assign no value.
 431        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
 432        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
 433        //! \return Pointer to allocated attribute. This pointer will never be NULL.
 434        xml_attribute<Ch> *allocate_attribute(const Ch *name = 0, const Ch *value = 0, 
 435                                              std::size_t name_size = 0, std::size_t value_size = 0)
 436        {
 437            void *memory = allocate_aligned(sizeof(xml_attribute<Ch>));
 438            xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;
 439            if (name)
 440            {
 441                if (name_size > 0)
 442                    attribute->name(name, name_size);
 443                else
 444                    attribute->name(name);
 445            }
 446            if (value)
 447            {
 448                if (value_size > 0)
 449                    attribute->value(value, value_size);
 450                else
 451                    attribute->value(value);
 452            }
 453            return attribute;
 454        }
 455
 456        //! Allocates a char array of given size from the pool, and optionally copies a given string to it.
 457        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
 458        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
 459        //! will call rapidxml::parse_error_handler() function.
 460        //! \param source String to initialize the allocated memory with, or 0 to not initialize it.
 461        //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.
 462        //! \return Pointer to allocated char array. This pointer will never be NULL.
 463        Ch *allocate_string(const Ch *source = 0, std::size_t size = 0)
 464        {
 465            BOOST_ASSERT(source || size);     // Either source or size (or both) must be specified
 466            if (size == 0)
 467                size = internal::measure(source) + 1;
 468            Ch *result = static_cast<Ch *>(allocate_aligned(size * sizeof(Ch)));
 469            if (source)
 470                for (std::size_t i = 0; i < size; ++i)
 471                    result[i] = source[i];
 472            return result;
 473        }
 474
 475        //! Clones an xml_node and its hierarchy of child nodes and attributes.
 476        //! Nodes and attributes are allocated from this memory pool.
 477        //! Names and values are not cloned, they are shared between the clone and the source.
 478        //! Result node can be optionally specified as a second parameter, 
 479        //! in which case its contents will be replaced with cloned source node.
 480        //! This is useful when you want to clone entire document.
 481        //! \param source Node to clone.
 482        //! \param result Node to put results in, or 0 to automatically allocate result node
 483        //! \return Pointer to cloned node. This pointer will never be NULL.
 484        xml_node<Ch> *clone_node(const xml_node<Ch> *source, xml_node<Ch> *result = 0)
 485        {
 486            // Prepare result node
 487            if (result)
 488            {
 489                result->remove_all_attributes();
 490                result->remove_all_nodes();
 491                result->type(source->type());
 492            }
 493            else
 494                result = allocate_node(source->type());
 495
 496            // Clone name and value
 497            result->name(source->name(), source->name_size());
 498            result->value(source->value(), source->value_size());
 499
 500            // Clone child nodes and attributes
 501            for (xml_node<Ch> *child = source->first_node(); child; child = child->next_sibling())
 502                result->append_node(clone_node(child));
 503            for (xml_attribute<Ch> *attr = source->first_attribute(); attr; attr = attr->next_attribute())
 504                result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));
 505
 506            return result;
 507        }
 508
 509        //! Clears the pool. 
 510        //! This causes memory occupied by nodes allocated by the pool to be freed.
 511        //! Any nodes or strings allocated from the pool will no longer be valid.
 512        void clear()
 513        {
 514            while (m_begin != m_static_memory)
 515            {
 516                char *previous_begin = reinterpret_cast<header *>(align(m_begin))->previous_begin;
 517                if (m_free_func)
 518                    m_free_func(m_begin);
 519                else
 520                    delete[] m_begin;
 521                m_begin = previous_begin;
 522            }
 523            init();
 524        }
 525
 526        //! Sets or resets the user-defined memory allocation functions for the pool.
 527        //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.
 528        //! Allocation function must not return invalid pointer on failure. It should either throw,
 529        //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program. 
 530        //! If it returns invalid pointer, results are undefined.
 531        //! <br><br>
 532        //! User defined allocation functions must have the following forms:
 533        //! <br><code>
 534        //! <br>void *allocate(std::size_t size);
 535        //! <br>void free(void *pointer);
 536        //! </code><br>
 537        //! \param af Allocation function, or 0 to restore default function
 538        //! \param ff Free function, or 0 to restore default function
 539        void set_allocator(alloc_func *af, free_func *ff)
 540        {
 541            BOOST_ASSERT(m_begin == m_static_memory && m_ptr == align(m_begin));    // Verify that no memory is allocated yet
 542            m_alloc_func = af;
 543            m_free_func = ff;
 544        }
 545
 546    private:
 547
 548        struct header
 549        {
 550            char *previous_begin;
 551        };
 552
 553        void init()
 554        {
 555            m_begin = m_static_memory;
 556            m_ptr = align(m_begin);
 557            m_end = m_static_memory + sizeof(m_static_memory);
 558        }
 559        
 560        char *align(char *ptr)
 561        {
 562            std::size_t alignment = ((BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT - 1))) & (BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT - 1));
 563            return ptr + alignment;
 564        }
 565        
 566        char *allocate_raw(std::size_t size)
 567        {
 568            // Allocate
 569            void *memory;   
 570            if (m_alloc_func)   // Allocate memory using either user-specified allocation function or global operator new[]
 571            {
 572                memory = m_alloc_func(size);
 573                BOOST_ASSERT(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp
 574            }
 575            else
 576            {
 577                memory = new char[size];
 578            }
 579            return static_cast<char *>(memory);
 580        }
 581        
 582        void *allocate_aligned(std::size_t size)
 583        {
 584            // Calculate aligned pointer
 585            char *result = align(m_ptr);
 586
 587            // If not enough memory left in current pool, allocate a new pool
 588            if (result + size > m_end)
 589            {
 590                // Calculate required pool size (may be bigger than BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE)
 591                std::size_t pool_size = BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE;
 592                if (pool_size < size)
 593                    pool_size = size;
 594                
 595                // Allocate
 596                std::size_t alloc_size = sizeof(header) + (2 * BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT - 2) + pool_size;     // 2 alignments required in worst case: one for header, one for actual allocation
 597                char *raw_memory = allocate_raw(alloc_size);
 598                    
 599                // Setup new pool in allocated memory
 600                char *pool = align(raw_memory);
 601                header *new_header = reinterpret_cast<header *>(pool);
 602                new_header->previous_begin = m_begin;
 603                m_begin = raw_memory;
 604                m_ptr = pool + sizeof(header);
 605                m_end = raw_memory + alloc_size;
 606
 607                // Calculate aligned pointer again using new pool
 608                result = align(m_ptr);
 609            }
 610
 611            // Update pool and return aligned pointer
 612            m_ptr = result + size;
 613            return result;
 614        }
 615
 616        char *m_begin;                                      // Start of raw memory making up current pool
 617        char *m_ptr;                                        // First free byte in current pool
 618        char *m_end;                                        // One past last available byte in current pool
 619        char m_static_memory[BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE];    // Static raw memory
 620        alloc_func *m_alloc_func;                           // Allocator function, or 0 if default is to be used
 621        free_func *m_free_func;                             // Free function, or 0 if default is to be used
 622    };
 623
 624    ///////////////////////////////////////////////////////////////////////////
 625    // XML base
 626
 627    //! Base class for xml_node and xml_attribute implementing common functions: 
 628    //! name(), name_size(), value(), value_size() and parent().
 629    //! \param Ch Character type to use
 630    template<class Ch = char>
 631    class xml_base
 632    {
 633
 634    public:
 635        
 636        ///////////////////////////////////////////////////////////////////////////
 637        // Construction & destruction
 638    
 639        // Construct a base with empty name, value and parent
 640        xml_base()
 641            : m_name(0)
 642            , m_value(0)
 643            , m_parent(0)
 644        {
 645        }
 646
 647        ///////////////////////////////////////////////////////////////////////////
 648        // Node data access
 649    
 650        //! Gets name of the node. 
 651        //! Interpretation of name depends on type of node.
 652        //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
 653        //! <br><br>
 654        //! Use name_size() function to determine length of the name.
 655        //! \return Name of node, or empty string if node has no name.
 656        Ch *name() const
 657        {
 658            return m_name ? m_name : nullstr();
 659        }
 660
 661        //! Gets size of node name, not including terminator character.
 662        //! This function works correctly irrespective of whether name is or is not zero terminated.
 663        //! \return Size of node name, in characters.
 664        std::size_t name_size() const
 665        {
 666            return m_name ? m_name_size : 0;
 667        }
 668
 669        //! Gets value of node. 
 670        //! Interpretation of value depends on type of node.
 671        //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
 672        //! <br><br>
 673        //! Use value_size() function to determine length of the value.
 674        //! \return Value of node, or empty string if node has no value.
 675        Ch *value() const
 676        {
 677            return m_value ? m_value : nullstr();
 678        }
 679
 680        //! Gets size of node value, not including terminator character.
 681        //! This function works correctly irrespective of whether value is or is not zero terminated.
 682        //! \return Size of node value, in characters.
 683        std::size_t value_size() const
 684        {
 685            return m_value ? m_value_size : 0;
 686        }
 687
 688        ///////////////////////////////////////////////////////////////////////////
 689        // Node modification
 690    
 691        //! Sets name of node to a non zero-terminated string.
 692        //! See \ref ownership_of_strings.
 693        //! <br><br>
 694        //! Note that node does not own its name or value, it only stores a pointer to it. 
 695        //! It will not delete or otherwise free the pointer on destruction.
 696        //! It is reponsibility of the user to properly manage lifetime of the string.
 697        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
 698        //! on destruction of the document the string will be automatically freed.
 699        //! <br><br>
 700        //! Size of name must be specified separately, because name does not have to be zero terminated.
 701        //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
 702        //! \param n Name of node to set. Does not have to be zero terminated.
 703        //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
 704        void name(const Ch *n, std::size_t size)
 705        {
 706            m_name = const_cast<Ch *>(n);
 707            m_name_size = size;
 708        }
 709
 710        //! Sets name of node to a zero-terminated string.
 711        //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
 712        //! \param n Name of node to set. Must be zero terminated.
 713        void name(const Ch *n)
 714        {
 715            name(n, internal::measure(n));
 716        }
 717
 718        //! Sets value of node to a non zero-terminated string.
 719        //! See \ref ownership_of_strings.
 720        //! <br><br>
 721        //! Note that node does not own its name or value, it only stores a pointer to it. 
 722        //! It will not delete or otherwise free the pointer on destruction.
 723        //! It is reponsibility of the user to properly manage lifetime of the string.
 724        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
 725        //! on destruction of the document the string will be automatically freed.
 726        //! <br><br>
 727        //! Size of value must be specified separately, because it does not have to be zero terminated.
 728        //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).
 729        //! <br><br>
 730        //! If an element has a child node of type node_data, it will take precedence over element value when printing.
 731        //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
 732        //! \param val value of node to set. Does not have to be zero terminated.
 733        //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
 734        void value(const Ch *val, std::size_t size)
 735        {
 736            m_value = const_cast<Ch *>(val);
 737            m_value_size = size;
 738        }
 739
 740        //! Sets value of node to a zero-terminated string.
 741        //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
 742        //! \param val Vame of node to set. Must be zero terminated.
 743        void value(const Ch *val)
 744        {
 745            this->value(val, internal::measure(val));
 746        }
 747
 748        ///////////////////////////////////////////////////////////////////////////
 749        // Related nodes access
 750    
 751        //! Gets node parent.
 752        //! \return Pointer to parent node, or 0 if there is no parent.
 753        xml_node<Ch> *parent() const
 754        {
 755            return m_parent;
 756        }
 757
 758    protected:
 759
 760        // Return empty string
 761        static Ch *nullstr()
 762        {
 763            static Ch zero = Ch('\0');
 764            return &zero;
 765        }
 766
 767        Ch *m_name;                         // Name of node, or 0 if no name
 768        Ch *m_value;                        // Value of node, or 0 if no value
 769        std::size_t m_name_size;            // Length of node name, or undefined of no name
 770        std::size_t m_value_size;           // Length of node value, or undefined if no value
 771        xml_node<Ch> *m_parent;             // Pointer to parent node, or 0 if none
 772
 773    };
 774
 775    //! Class representing attribute node of XML document. 
 776    //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
 777    //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. 
 778    //! Thus, this text must persist in memory for the lifetime of attribute.
 779    //! \param Ch Character type to use.
 780    template<class Ch = char>
 781    class xml_attribute: public xml_base<Ch>
 782    {
 783
 784        friend class xml_node<Ch>;
 785    
 786    public:
 787
 788        ///////////////////////////////////////////////////////////////////////////
 789        // Construction & destruction
 790    
 791        //! Constructs an empty attribute with the specified type. 
 792        //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.
 793        xml_attribute()
 794        {
 795        }
 796
 797        ///////////////////////////////////////////////////////////////////////////
 798        // Related nodes access
 799    
 800        //! Gets document of which attribute is a child.
 801        //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.
 802        xml_document<Ch> *document() const
 803        {
 804            if (xml_node<Ch> *node = this->parent())
 805            {
 806                while (node->parent())
 807                    node = node->parent();
 808                return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
 809            }
 810            else
 811                return 0;
 812        }
 813
 814        //! Gets previous attribute, optionally matching attribute name. 
 815        //! \param n Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
 816        //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
 817        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
 818        //! \return Pointer to found attribute, or 0 if not found.
 819        xml_attribute<Ch> *previous_attribute(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
 820        {
 821            if (n)
 822            {
 823                if (nsize == 0)
 824                    nsize = internal::measure(n);
 825                for (xml_attribute<Ch> *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)
 826                    if (internal::compare(attribute->name(), attribute->name_size(), n, nsize, case_sensitive))
 827                        return attribute;
 828                return 0;
 829            }
 830            else
 831                return this->m_parent ? m_prev_attribute : 0;
 832        }
 833
 834        //! Gets next attribute, optionally matching attribute name. 
 835        //! \param n Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
 836        //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
 837        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
 838        //! \return Pointer to found attribute, or 0 if not found.
 839        xml_attribute<Ch> *next_attribute(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
 840        {
 841            if (n)
 842            {
 843                if (nsize == 0)
 844                    nsize = internal::measure(n);
 845                for (xml_attribute<Ch> *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)
 846                    if (internal::compare(attribute->name(), attribute->name_size(), n, nsize, case_sensitive))
 847                        return attribute;
 848                return 0;
 849            }
 850            else
 851                return this->m_parent ? m_next_attribute : 0;
 852        }
 853
 854    private:
 855
 856        xml_attribute<Ch> *m_prev_attribute;        // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
 857        xml_attribute<Ch> *m_next_attribute;        // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
 858    
 859    };
 860
 861    ///////////////////////////////////////////////////////////////////////////
 862    // XML node
 863
 864    //! Class representing a node of XML document. 
 865    //! Each node may have associated name and value strings, which are available through name() and value() functions. 
 866    //! Interpretation of name and value depends on type of the node.
 867    //! Type of node can be determined by using type() function.
 868    //! <br><br>
 869    //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. 
 870    //! Thus, this text must persist in the memory for the lifetime of node.
 871    //! \param Ch Character type to use.
 872    template<class Ch = char>
 873    class xml_node: public xml_base<Ch>
 874    {
 875
 876    public:
 877
 878        ///////////////////////////////////////////////////////////////////////////
 879        // Construction & destruction
 880    
 881        //! Constructs an empty node with the specified type. 
 882        //! Consider using memory_pool of appropriate document to allocate nodes manually.
 883        //! \param t Type of node to construct.
 884        xml_node(node_type t)
 885            : m_type(t)
 886            , m_first_node(0)
 887            , m_first_attribute(0)
 888        {
 889        }
 890
 891        ///////////////////////////////////////////////////////////////////////////
 892        // Node data access
 893    
 894        //! Gets type of node.
 895        //! \return Type of node.
 896        node_type type() const
 897        {
 898            return m_type;
 899        }
 900
 901        ///////////////////////////////////////////////////////////////////////////
 902        // Related nodes access
 903    
 904        //! Gets document of which node is a child.
 905        //! \return Pointer to document that contains this node, or 0 if there is no parent document.
 906        xml_document<Ch> *document() const
 907        {
 908            xml_node<Ch> *node = const_cast<xml_node<Ch> *>(this);
 909            while (node->parent())
 910                node = node->parent();
 911            return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
 912        }
 913
 914        //! Gets first child node, optionally matching node name.
 915        //! \param n Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
 916        //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
 917        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
 918        //! \return Pointer to found child, or 0 if not found.
 919        xml_node<Ch> *first_node(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
 920        {
 921            if (n)
 922            {
 923                if (nsize == 0)
 924                    nsize = internal::measure(n);
 925                for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling())
 926                    if (internal::compare(child->name(), child->name_size(), n, nsize, case_sensitive))
 927                        return child;
 928                return 0;
 929            }
 930            else
 931                return m_first_node;
 932        }
 933
 934        //! Gets last child node, optionally matching node name. 
 935        //! Behaviour is undefined if node has no children.
 936        //! Use first_node() to test if node has children.
 937        //! \param n Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
 938        //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
 939        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
 940        //! \return Pointer to found child, or 0 if not found.
 941        xml_node<Ch> *last_node(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
 942        {
 943            BOOST_ASSERT(m_first_node);  // Cannot query for last child if node has no children
 944            if (n)
 945            {
 946                if (nsize == 0)
 947                    nsize = internal::measure(n);
 948                for (xml_node<Ch> *child = m_last_node; child; child = child->previous_sibling())
 949                    if (internal::compare(child->name(), child->name_size(), n, nsize, case_sensitive))
 950                        return child;
 951                return 0;
 952            }
 953            else
 954                return m_last_node;
 955        }
 956
 957        //! Gets previous sibling node, optionally matching node name. 
 958        //! Behaviour is undefined if node has no parent.
 959        //! Use parent() to test if node has a parent.
 960        //! \param n Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
 961        //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
 962        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
 963        //! \return Pointer to found sibling, or 0 if not found.
 964        xml_node<Ch> *previous_sibling(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
 965        {
 966            BOOST_ASSERT(this->m_parent);     // Cannot query for siblings if node has no parent
 967            if (n)
 968            {
 969                if (nsize == 0)
 970                    nsize = internal::measure(n);
 971                for (xml_node<Ch> *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)
 972                    if (internal::compare(sibling->name(), sibling->name_size(), n, nsize, case_sensitive))
 973                        return sibling;
 974                return 0;
 975            }
 976            else
 977                return m_prev_sibling;
 978        }
 979
 980        //! Gets next sibling node, optionally matching node name. 
 981        //! Behaviour is undefined if node has no parent.
 982        //! Use parent() to test if node has a parent.
 983        //! \param n Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
 984        //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
 985        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
 986        //! \return Pointer to found sibling, or 0 if not found.
 987        xml_node<Ch> *next_sibling(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
 988        {
 989            BOOST_ASSERT(this->m_parent);     // Cannot query for siblings if node has no parent
 990            if (n)
 991            {
 992                if (nsize == 0)
 993                    nsize = internal::measure(n);
 994                for (xml_node<Ch> *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)
 995                    if (internal::compare(sibling->name(), sibling->name_size(), n, nsize, case_sensitive))
 996                        return sibling;
 997                return 0;
 998            }
 999            else
1000                return m_next_sibling;
1001        }
1002
1003        //! Gets first attribute of node, optionally matching attribute name.
1004        //! \param n Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
1005        //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
1006        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
1007        //! \return Pointer to found attribute, or 0 if not found.
1008        xml_attribute<Ch> *first_attribute(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
1009        {
1010            if (n)
1011            {
1012                if (nsize == 0)
1013                    nsize = internal::measure(n);
1014                for (xml_attribute<Ch> *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)
1015                    if (internal::compare(attribute->name(), attribute->name_size(), n, nsize, case_sensitive))
1016                        return attribute;
1017                return 0;
1018            }
1019            else
1020                return m_first_attribute;
1021        }
1022
1023        //! Gets last attribute of node, optionally matching attribute name.
1024        //! \param n Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
1025        //! \param nsize Size of nameā€¦

Large files files are truncated, but you can click here to view the full file