Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r53152 - in trunk: boost/property_tree/detail libs/property_tree/test
From: jewillco_at_[hidden]
Date: 2009-05-21 10:38:02


Author: jewillco
Date: 2009-05-21 10:38:00 EDT (Thu, 21 May 2009)
New Revision: 53152
URL: http://svn.boost.org/trac/boost/changeset/53152

Log:
Fixed more tab and min/max issues
Text files modified:
   trunk/boost/property_tree/detail/pugxml.hpp | 6642 ++++++++++++++++++++--------------------
   trunk/libs/property_tree/test/test_json_parser.cpp | 10
   trunk/libs/property_tree/test/xml_parser_test_data.hpp | 746 ++--
   3 files changed, 3699 insertions(+), 3699 deletions(-)

Modified: trunk/boost/property_tree/detail/pugxml.hpp
==============================================================================
--- trunk/boost/property_tree/detail/pugxml.hpp (original)
+++ trunk/boost/property_tree/detail/pugxml.hpp 2009-05-21 10:38:00 EDT (Thu, 21 May 2009)
@@ -31,9 +31,9 @@
 //#define PUGOPT_NONSEG //Uncomment to enable non-destructive (non-segmenting) parsing support.
 
 #ifdef PUGOPT_MEMFIL
-# ifndef PUGOPT_NONSEG
-# define PUGOPT_NONSEG //PUGOPT_MEMFIL implies PUGOPT_NONSEG.
-# endif
+# ifndef PUGOPT_NONSEG
+# define PUGOPT_NONSEG //PUGOPT_MEMFIL implies PUGOPT_NONSEG.
+# endif
 #endif
 
 #include <iostream>
@@ -41,21 +41,21 @@
 #include <string>
 #include <cstring>
 #if defined(PUGOPT_MEMFIL) | defined(PUGOPT_NONSEG)
-# include <assert.h>
+# include <assert.h>
 #endif
 
 #ifndef HIWORD
 # define UNDEF_LOHIWORD
-# define HIWORD(X) ((unsigned short)((unsigned long)(X)>>16))
-# define LOWORD(X) ((unsigned short)((unsigned long)(X)&0xFFFF))
+# define HIWORD(X) ((unsigned short)((unsigned long)(X)>>16))
+# define LOWORD(X) ((unsigned short)((unsigned long)(X)&0xFFFF))
 #endif
 
 //<summary>
-// Library variant ID. The ID 0x58475550 is owned by Kristen Wegner. You *MUST*
-// provide your own unique ID if you modify or fork the code in this library to
-// your own purposes. If you change this then *you* are now the maintainer, not me.
-// Change also in the package section of pugxml.xml, and append yourself to the
-// authors section.
+// Library variant ID. The ID 0x58475550 is owned by Kristen Wegner. You *MUST*
+// provide your own unique ID if you modify or fork the code in this library to
+// your own purposes. If you change this then *you* are now the maintainer, not me.
+// Change also in the package section of pugxml.xml, and append yourself to the
+// authors section.
 //</summary>
 #define PUGAPI_INTERNAL_VARIANT 0xdeadbeef
 //<summary>Major version. Increment for each major release. Only change if you own the variant.</summary>
@@ -84,85 +84,85 @@
 //<summary>A 'name=value' XML attribute structure.</summary>
 typedef struct t_xml_attribute_struct
 {
- TCHAR* name; //Pointer to attribute name.
- bool name_insitu; //True if 'name' is a segment of the original parse string.
+ TCHAR* name; //Pointer to attribute name.
+ bool name_insitu; //True if 'name' is a segment of the original parse string.
 #ifdef PUGOPT_NONSEG
- unsigned int name_size; //Length of element name.
+ unsigned int name_size; //Length of element name.
 #endif
- TCHAR* value; //Pointer to attribute value.
- bool value_insitu; //True if 'value' is a segment of the original parse string.
+ TCHAR* value; //Pointer to attribute value.
+ bool value_insitu; //True if 'value' is a segment of the original parse string.
 #ifdef PUGOPT_NONSEG
- unsigned int value_size; //Length of element name.
+ unsigned int value_size; //Length of element name.
 #endif
 }
- xml_attribute_struct;
+ xml_attribute_struct;
 
 
 //<summary>Tree node classification.</summary>
 //<remarks>See 'xml_node_struct::type'.</remarks>
 typedef enum t_xml_node_type
 {
- node_null, //An undifferentiated entity.
- node_document, //A document tree's absolute root.
- node_element, //E.g. '&lt;...&gt;'
- node_pcdata, //E.g. '&gt;...&lt;'
- node_cdata, //E.g. '&lt;![CDATA[...]]&gt;'
- node_comment, //E.g. '&lt;!--...--&gt;'
- node_pi, //E.g. '&lt;?...?&gt;'
- node_include, //E.g. '&lt;![INCLUDE[...]]&gt;'
- node_doctype, //E.g. '&lt;!DOCTYPE ...&gt;'.
- node_dtd_entity, //E.g. '&lt;!ENTITY ...&gt;'.
- node_dtd_attlist, //E.g. '&lt;!ATTLIST ...&gt;'.
- node_dtd_element, //E.g. '&lt;!ELEMENT ...&gt;'.
- node_dtd_notation //E.g. '&lt;!NOTATION ...&gt;'.
+ node_null, //An undifferentiated entity.
+ node_document, //A document tree's absolute root.
+ node_element, //E.g. '&lt;...&gt;'
+ node_pcdata, //E.g. '&gt;...&lt;'
+ node_cdata, //E.g. '&lt;![CDATA[...]]&gt;'
+ node_comment, //E.g. '&lt;!--...--&gt;'
+ node_pi, //E.g. '&lt;?...?&gt;'
+ node_include, //E.g. '&lt;![INCLUDE[...]]&gt;'
+ node_doctype, //E.g. '&lt;!DOCTYPE ...&gt;'.
+ node_dtd_entity, //E.g. '&lt;!ENTITY ...&gt;'.
+ node_dtd_attlist, //E.g. '&lt;!ATTLIST ...&gt;'.
+ node_dtd_element, //E.g. '&lt;!ELEMENT ...&gt;'.
+ node_dtd_notation //E.g. '&lt;!NOTATION ...&gt;'.
 }
- xml_node_type;
+ xml_node_type;
 
 
 static const unsigned long parse_grow = 4; //Default child element & attribute space growth increment.
 
 
 //Parser Options
-static const unsigned long parse_minimal = 0x00000000; //Unset the following flags.
-static const unsigned long parse_pi = 0x00000002; //Parse '&lt;?...?&gt;'
-static const unsigned long parse_doctype = 0x00000004; //Parse '&lt;!DOCTYPE ...&gt;' section, setting '[...]' as data member.
-static const unsigned long parse_comments = 0x00000008; //Parse &lt;!--...--&gt;'
-static const unsigned long parse_cdata = 0x00000010; //Parse '&lt;![CDATA[...]]&gt;', and/or '&lt;![INCLUDE[...]]&gt;'
-static const unsigned long parse_escapes = 0x00000020; //Not implemented.
-static const unsigned long parse_trim_pcdata = 0x00000040; //Trim '&gt;...&lt;'
+static const unsigned long parse_minimal = 0x00000000; //Unset the following flags.
+static const unsigned long parse_pi = 0x00000002; //Parse '&lt;?...?&gt;'
+static const unsigned long parse_doctype = 0x00000004; //Parse '&lt;!DOCTYPE ...&gt;' section, setting '[...]' as data member.
+static const unsigned long parse_comments = 0x00000008; //Parse &lt;!--...--&gt;'
+static const unsigned long parse_cdata = 0x00000010; //Parse '&lt;![CDATA[...]]&gt;', and/or '&lt;![INCLUDE[...]]&gt;'
+static const unsigned long parse_escapes = 0x00000020; //Not implemented.
+static const unsigned long parse_trim_pcdata = 0x00000040; //Trim '&gt;...&lt;'
 static const unsigned long parse_trim_attribute = 0x00000080; //Trim 'foo="..."'.
-static const unsigned long parse_trim_cdata = 0x00000100; //Trim '&lt;![CDATA[...]]&gt;', and/or '&lt;![INCLUDE[...]]&gt;'
-static const unsigned long parse_trim_entity = 0x00000200; //Trim '&lt;!ENTITY name ...&gt;', etc.
-static const unsigned long parse_trim_doctype = 0x00000400; //Trim '&lt;!DOCTYPE [...]&gt;'
-static const unsigned long parse_trim_comment = 0x00000800; //Trim &lt;!--...--&gt;'
-static const unsigned long parse_wnorm = 0x00001000; //Normalize all entities that are flagged to be trimmed.
-static const unsigned long parse_dtd = 0x00002000; //If parse_doctype set, then parse whatever is in data member ('[...]').
-static const unsigned long parse_dtd_only = 0x00004000; //If parse_doctype|parse_dtd set, then parse only '&lt;!DOCTYPE [*]&gt;'
-static const unsigned long parse_default = 0x0000FFFF;
-static const unsigned long parse_noset = 0x80000000;
+static const unsigned long parse_trim_cdata = 0x00000100; //Trim '&lt;![CDATA[...]]&gt;', and/or '&lt;![INCLUDE[...]]&gt;'
+static const unsigned long parse_trim_entity = 0x00000200; //Trim '&lt;!ENTITY name ...&gt;', etc.
+static const unsigned long parse_trim_doctype = 0x00000400; //Trim '&lt;!DOCTYPE [...]&gt;'
+static const unsigned long parse_trim_comment = 0x00000800; //Trim &lt;!--...--&gt;'
+static const unsigned long parse_wnorm = 0x00001000; //Normalize all entities that are flagged to be trimmed.
+static const unsigned long parse_dtd = 0x00002000; //If parse_doctype set, then parse whatever is in data member ('[...]').
+static const unsigned long parse_dtd_only = 0x00004000; //If parse_doctype|parse_dtd set, then parse only '&lt;!DOCTYPE [*]&gt;'
+static const unsigned long parse_default = 0x0000FFFF;
+static const unsigned long parse_noset = 0x80000000;
 
 
 //<summary>An XML document tree node.</summary>
 typedef struct t_xml_node_struct
 {
- t_xml_node_struct* parent; //Pointer to parent
- TCHAR* name; //Pointer to element name.
+ t_xml_node_struct* parent; //Pointer to parent
+ TCHAR* name; //Pointer to element name.
 #ifdef PUGOPT_NONSEG
- unsigned int name_size; //Length of element name. Since 19 Jan 2003 NF.
+ unsigned int name_size; //Length of element name. Since 19 Jan 2003 NF.
 #endif
- bool name_insitu; //True if 'name' is a segment of the original parse string.
- xml_node_type type; //Node type; see xml_node_type.
- unsigned int attributes; //Count attributes.
- unsigned int attribute_space; //Available pointer space in 'attribute'.
- xml_attribute_struct** attribute; //Array of pointers to attributes; see xml_attribute_struct.
- unsigned int children; //Count children in member 'child'.
- unsigned int child_space; //Available pointer space in 'child'.
- t_xml_node_struct** child; //Array of pointers to children.
- TCHAR* value; //Pointer to any associated string data.
+ bool name_insitu; //True if 'name' is a segment of the original parse string.
+ xml_node_type type; //Node type; see xml_node_type.
+ unsigned int attributes; //Count attributes.
+ unsigned int attribute_space; //Available pointer space in 'attribute'.
+ xml_attribute_struct** attribute; //Array of pointers to attributes; see xml_attribute_struct.
+ unsigned int children; //Count children in member 'child'.
+ unsigned int child_space; //Available pointer space in 'child'.
+ t_xml_node_struct** child; //Array of pointers to children.
+ TCHAR* value; //Pointer to any associated string data.
 #ifdef PUGOPT_NONSEG
- unsigned int value_size; //Length of element data. Since 19 Jan 2003 NF.
+ unsigned int value_size; //Length of element data. Since 19 Jan 2003 NF.
 #endif
- bool value_insitu; //True if 'data' is a segment of the original parse string.
+ bool value_insitu; //True if 'data' is a segment of the original parse string.
 }
 xml_node_struct;
 
@@ -174,19 +174,19 @@
 //<remarks>'rhs' is resized and 'rhs' is concatenated to it.</remarks>
 inline static bool strcatgrow(TCHAR** lhs,const TCHAR* rhs)
 {
- if(!*lhs) //Null, so first allocate.
- {
- *lhs = (TCHAR*) malloc(1UL*sizeof(TCHAR));
- **lhs = 0; //Zero-terminate.
- }
- size_t ulhs = _tcslen(*lhs);
- size_t urhs = _tcslen(rhs);
- TCHAR* temp = (TCHAR*) realloc(*lhs,(ulhs+urhs+1UL)*sizeof(TCHAR));
- if(!temp) return false; //Realloc failed.
- memcpy(temp+ulhs,rhs,urhs*sizeof(TCHAR)); //Concatenate.
- temp[ulhs+urhs] = 0; //Terminate it.
- *lhs = temp;
- return true;
+ if(!*lhs) //Null, so first allocate.
+ {
+ *lhs = (TCHAR*) malloc(1UL*sizeof(TCHAR));
+ **lhs = 0; //Zero-terminate.
+ }
+ size_t ulhs = _tcslen(*lhs);
+ size_t urhs = _tcslen(rhs);
+ TCHAR* temp = (TCHAR*) realloc(*lhs,(ulhs+urhs+1UL)*sizeof(TCHAR));
+ if(!temp) return false; //Realloc failed.
+ memcpy(temp+ulhs,rhs,urhs*sizeof(TCHAR)); //Concatenate.
+ temp[ulhs+urhs] = 0; //Terminate it.
+ *lhs = temp;
+ return true;
 }
 
 
@@ -228,28 +228,28 @@
 //<remarks>'lhs' is resized and 'rhs' is concatenated to it.</remarks>
 inline static bool strcatgrown_impl(TCHAR** lhs,const TCHAR* rhs,unsigned int& lsize,unsigned int rsize)
 {
- if(!*lhs) //Null, allocate and copy.
- {
- *lhs = (TCHAR*) malloc(rsize+sizeof(TCHAR));
- if(!*lhs)
- {
- lsize = 0;
- return false; //Allocate failed.
- }
- memcpy(*lhs,rhs,rsize); //Concatenate.
- *(*lhs + rsize) = 0; //Terminate it.
- lsize = rsize;
- }
- else //Reallocate. NF I don't think this is right for MBCS, nor is code in 'StrCatGrow()'.
- {
- TCHAR* temp = (TCHAR*) realloc(*lhs,lsize + rsize + sizeof(TCHAR));
- if(!temp) return false; //Realloc failed.
- memcpy(temp+lsize,rhs,rsize); //Concatenate.
- lsize += rsize; //Set new length.
- temp[lsize] = 0; //Terminate it.
- *lhs = temp;
- }
- return true;
+ if(!*lhs) //Null, allocate and copy.
+ {
+ *lhs = (TCHAR*) malloc(rsize+sizeof(TCHAR));
+ if(!*lhs)
+ {
+ lsize = 0;
+ return false; //Allocate failed.
+ }
+ memcpy(*lhs,rhs,rsize); //Concatenate.
+ *(*lhs + rsize) = 0; //Terminate it.
+ lsize = rsize;
+ }
+ else //Reallocate. NF I don't think this is right for MBCS, nor is code in 'StrCatGrow()'.
+ {
+ TCHAR* temp = (TCHAR*) realloc(*lhs,lsize + rsize + sizeof(TCHAR));
+ if(!temp) return false; //Realloc failed.
+ memcpy(temp+lsize,rhs,rsize); //Concatenate.
+ lsize += rsize; //Set new length.
+ temp[lsize] = 0; //Terminate it.
+ *lhs = temp;
+ }
+ return true;
 }
 
 //<summary>Concatenate 'rhs' to 'lhs', growing 'lhs' if neccessary.</summary>
@@ -260,8 +260,8 @@
 //<remarks>'lhs' is resized and 'rhs' is concatenated to it.</remarks>
 inline static bool strcatgrown(TCHAR** lhs,const TCHAR* rhs,unsigned int& lsize)
 {
- const unsigned int rsize = _tcslen(rhs) * sizeof(TCHAR);
- return pug::strcatgrown_impl(lhs,rhs,lsize,rsize);
+ const unsigned int rsize = _tcslen(rhs) * sizeof(TCHAR);
+ return pug::strcatgrown_impl(lhs,rhs,lsize,rsize);
 }
 
 //<summary>Trim leading and trailing whitespace.</summary>
@@ -271,19 +271,19 @@
 //<remarks>*s is modified to point to the first non-white character in the string.</remarks>
 inline static bool strwtrim(TCHAR** s,unsigned int& len)
 {
- if(!s || !*s) return false;
- TCHAR* pse = *s + len;
- while(*s < pse && pug::chartype_space(**s)) //Find first non-white character.
- ++*s; //As long as we hit whitespace, increment the string pointer.
- for(; *s < --pse;) //As long as we hit whitespace, decrement.
- {
- if(!pug::chartype_space(*pse))
- {
- len = pse + 1 - *s;
- break;
- }
- }
- return true;
+ if(!s || !*s) return false;
+ TCHAR* pse = *s + len;
+ while(*s < pse && pug::chartype_space(**s)) //Find first non-white character.
+ ++*s; //As long as we hit whitespace, increment the string pointer.
+ for(; *s < --pse;) //As long as we hit whitespace, decrement.
+ {
+ if(!pug::chartype_space(*pse))
+ {
+ len = pse + 1 - *s;
+ break;
+ }
+ }
+ return true;
 }
 
 
@@ -295,59 +295,59 @@
 //<returns>Success.</returns>
 inline static bool strwtrim(TCHAR** s)
 {
- if(!s || !*s) return false;
- while(**s > 0 && **s < _T('!')) ++*s; //As long as we hit whitespace, increment the string pointer.
- const TCHAR* temp = *s;
- while(0 != *temp++); //Find the terminating null.
- long i, n = (long)(temp-*s-1);
- --n; //Start from the last string TCHAR.
- for(i=n; (i > -1) && (*s)[i] > 0 && (*s)[i] < _T('!'); --i); //As long as we hit whitespace, decrement.
- if(i<n) (*s)[i+1] = 0; //Zero-terminate.
- return true;
+ if(!s || !*s) return false;
+ while(**s > 0 && **s < _T('!')) ++*s; //As long as we hit whitespace, increment the string pointer.
+ const TCHAR* temp = *s;
+ while(0 != *temp++); //Find the terminating null.
+ long i, n = (long)(temp-*s-1);
+ --n; //Start from the last string TCHAR.
+ for(i=n; (i > -1) && (*s)[i] > 0 && (*s)[i] < _T('!'); --i); //As long as we hit whitespace, decrement.
+ if(i<n) (*s)[i+1] = 0; //Zero-terminate.
+ return true;
 }
 
 
 //<summary>
-// In situ trim leading and trailing whitespace, then convert all consecutive
-// whitespace to a single space TCHAR.
+// In situ trim leading and trailing whitespace, then convert all consecutive
+// whitespace to a single space TCHAR.
 //</summary>
 //<param name="s">Pointer to pointer to string.</param>
 //<returns>Success.</returns>
 inline static bool strwnorm(TCHAR** s)
 {
- if(!s || !*s) return false; //No string to normalize.
- while(**s > 0 && **s < _T('!')) ++(*s); //As long as we hit whitespace, increment the string pointer.
- const TCHAR* temp = *s;
- while(0 != *temp++); //Find the terminating null.
- long n = (long)(temp-*s-1);
- TCHAR* norm = (TCHAR*)malloc(sizeof(TCHAR)*(n+1)); //Allocate a temporary normalization buffer.
- if(!norm) return false; //Allocation failed.
- memset(norm,0,sizeof(TCHAR)*(n+1)); //Zero it.
- long j = 1;
- norm[0] = (*s)[0];
- long i;
+ if(!s || !*s) return false; //No string to normalize.
+ while(**s > 0 && **s < _T('!')) ++(*s); //As long as we hit whitespace, increment the string pointer.
+ const TCHAR* temp = *s;
+ while(0 != *temp++); //Find the terminating null.
+ long n = (long)(temp-*s-1);
+ TCHAR* norm = (TCHAR*)malloc(sizeof(TCHAR)*(n+1)); //Allocate a temporary normalization buffer.
+ if(!norm) return false; //Allocation failed.
+ memset(norm,0,sizeof(TCHAR)*(n+1)); //Zero it.
+ long j = 1;
+ norm[0] = (*s)[0];
+ long i;
     for(i=1; i<n; ++i) //For each character, starting at offset 1.
- {
- if((*s)[i] < _T('!')) //Whitespace-like.
- {
- if((*s)[i-1] >= _T('!')) //Previous was not whitespace-like.
- {
- norm[j] = _T(' '); //Convert to a space TCHAR.
- ++j; //Normalization buffer grew by one TCHAR.
- }
- }
- else { norm[j] = (*s)[i]; ++j; } //Not whitespace, so just copy over.
- }
- if(j < n) //Normalization buffer is actually different that input.
- {
- _tcsncpy(*s,norm,j); //So, copy it back to input.
- (*s)[j] = 0; //Zero-terminate.
- }
- free(norm); //Don't need this anymore.
- --n; //Start from the last string TCHAR.
- for(i=n; (i > -1) && (*s)[i] > 0 && (*s)[i] < _T('!'); --i); //Find the first non-whitespace from the end.
- if(i<n) (*s)[i+1] = 0; //Truncate it.
- return true;
+ {
+ if((*s)[i] < _T('!')) //Whitespace-like.
+ {
+ if((*s)[i-1] >= _T('!')) //Previous was not whitespace-like.
+ {
+ norm[j] = _T(' '); //Convert to a space TCHAR.
+ ++j; //Normalization buffer grew by one TCHAR.
+ }
+ }
+ else { norm[j] = (*s)[i]; ++j; } //Not whitespace, so just copy over.
+ }
+ if(j < n) //Normalization buffer is actually different that input.
+ {
+ _tcsncpy(*s,norm,j); //So, copy it back to input.
+ (*s)[j] = 0; //Zero-terminate.
+ }
+ free(norm); //Don't need this anymore.
+ --n; //Start from the last string TCHAR.
+ for(i=n; (i > -1) && (*s)[i] > 0 && (*s)[i] < _T('!'); --i); //Find the first non-whitespace from the end.
+ if(i<n) (*s)[i+1] = 0; //Truncate it.
+ return true;
 
 }
 
@@ -360,47 +360,47 @@
 //<param name="insitu">Pointer to boolean in-situ string flag.</param>
 //<returns>True if member was set to the new value.</returns>
 //<remarks>
-// If 'src' is larger than 'dest' then 'dest' is resized, in which case
-// it is probably no longer in-situ,and 'in_situ' is set to false. If
-// 'dest' is already no longer in-situ, and 'src' is too small then the
-// existing memory pointed to is freed. If 'dest' is larger than or equal
-// to 'dest' then it is merely copied with no resize.
+// If 'src' is larger than 'dest' then 'dest' is resized, in which case
+// it is probably no longer in-situ,and 'in_situ' is set to false. If
+// 'dest' is already no longer in-situ, and 'src' is too small then the
+// existing memory pointed to is freed. If 'dest' is larger than or equal
+// to 'dest' then it is merely copied with no resize.
 //</remarks>
 inline static bool strcpyinsitu
- (
- TCHAR** dest,
- const TCHAR* src,
- bool* insitu
+ (
+ TCHAR** dest,
+ const TCHAR* src,
+ bool* insitu
 #ifdef PUGOPT_NONSEG
- ,
- unsigned int& destlen
+ ,
+ unsigned int& destlen
 #endif
- )
+ )
 {
- if(!dest || !src || !insitu) return false; //Bad argument(s), so fail.
+ if(!dest || !src || !insitu) return false; //Bad argument(s), so fail.
 #ifndef PUGOPT_NONSEG //Always use heap for our r/o string.
- size_t l = (*dest) ? _tcslen(*dest) : 0; //How long is destination?
- if(l >= _tcslen(src)) //Destination is large enough, so just copy.
- {
- _tcscpy(*dest,src); //Copy.
- return true; //Success.
- }
- else //Destination is too small.
-#endif
- {
- if(*dest && !*insitu) free(*dest); //If destination is not in-situ, then free it.
- *dest = NULL; //Mark destination as NULL, forcing 'StrCatGrow' to 'malloc.
-#ifdef PUGOPT_NONSEG
- if(strcatgrown(dest,src,destlen)) //Allocate & copy source to destination
-#else
- if(strcatgrow(dest,src)) //Allocate & copy source to destination
-#endif
- {
- *insitu = false; //Mark as no longer being in-situ, so we can free it later.
- return true; //Success.
- }
- }
- return false; //Failure.
+ size_t l = (*dest) ? _tcslen(*dest) : 0; //How long is destination?
+ if(l >= _tcslen(src)) //Destination is large enough, so just copy.
+ {
+ _tcscpy(*dest,src); //Copy.
+ return true; //Success.
+ }
+ else //Destination is too small.
+#endif
+ {
+ if(*dest && !*insitu) free(*dest); //If destination is not in-situ, then free it.
+ *dest = NULL; //Mark destination as NULL, forcing 'StrCatGrow' to 'malloc.
+#ifdef PUGOPT_NONSEG
+ if(strcatgrown(dest,src,destlen)) //Allocate & copy source to destination
+#else
+ if(strcatgrow(dest,src)) //Allocate & copy source to destination
+#endif
+ {
+ *insitu = false; //Mark as no longer being in-situ, so we can free it later.
+ return true; //Success.
+ }
+ }
+ return false; //Failure.
 }
 
 
@@ -410,34 +410,34 @@
 //<remarks>Used by 'strcmpwild'.</remarks>
 inline int strcmpwild_cset(const TCHAR** src,const TCHAR** dst)
 {
- int find = 0;
- int excl = 0;
- int star = 1;
- if(**src == _T('!'))
- {
- excl = 1;
- ++(*src);
- }
- while(**src != _T(']') || star == 1)
- {
- if(find == 0)
- {
- if(**src == _T('-') && *(*src-1) < *(*src+1) && *(*src+1) != _T(']') && star == 0)
- {
- if(**dst >= *(*src-1) && **dst <= *(*src+1))
- {
- find = 1;
- ++(*src);
- }
- }
- else if(**src == **dst) find = 1;
- }
- ++(*src);
- star = 0;
- }
- if(excl == 1) find = (1 - find);
- if(find == 1) ++(*dst);
- return find;
+ int find = 0;
+ int excl = 0;
+ int star = 1;
+ if(**src == _T('!'))
+ {
+ excl = 1;
+ ++(*src);
+ }
+ while(**src != _T(']') || star == 1)
+ {
+ if(find == 0)
+ {
+ if(**src == _T('-') && *(*src-1) < *(*src+1) && *(*src+1) != _T(']') && star == 0)
+ {
+ if(**dst >= *(*src-1) && **dst <= *(*src+1))
+ {
+ find = 1;
+ ++(*src);
+ }
+ }
+ else if(**src == **dst) find = 1;
+ }
+ ++(*src);
+ star = 0;
+ }
+ if(excl == 1) find = (1 - find);
+ if(find == 1) ++(*dst);
+ return find;
 }
 
 
@@ -450,31 +450,31 @@
 //<remarks>Used by 'strcmpwild'.</remarks>
 inline int strcmpwild_astr(const TCHAR** src,const TCHAR** dst)
 {
- int find = 1;
- ++(*src);
- while((**dst != 0 && **src == _T('?')) || **src == _T('*'))
- {
- if(**src == _T('?')) ++(*dst);
- ++(*src);
- }
- while(**src == _T('*')) ++(*src);
- if(**dst == 0 && **src != 0) return 0;
- if(**dst == 0 && **src == 0) return 1;
- else
- {
- if(strcmpwild_impl(*src,*dst) == 0)
- {
- do
- {
- ++(*dst);
- while(**src != **dst && **src != _T('[') && **dst != 0)
- ++(*dst);
- }
- while((**dst != 0) ? strcmpwild_impl(*src,*dst) == 0 : 0 != (find=0));
- }
- if(**dst == 0 && **src == 0) find = 1;
- return find;
- }
+ int find = 1;
+ ++(*src);
+ while((**dst != 0 && **src == _T('?')) || **src == _T('*'))
+ {
+ if(**src == _T('?')) ++(*dst);
+ ++(*src);
+ }
+ while(**src == _T('*')) ++(*src);
+ if(**dst == 0 && **src != 0) return 0;
+ if(**dst == 0 && **src == 0) return 1;
+ else
+ {
+ if(strcmpwild_impl(*src,*dst) == 0)
+ {
+ do
+ {
+ ++(*dst);
+ while(**src != **dst && **src != _T('[') && **dst != 0)
+ ++(*dst);
+ }
+ while((**dst != 0) ? strcmpwild_impl(*src,*dst) == 0 : 0 != (find=0));
+ }
+ if(**dst == 0 && **src == 0) find = 1;
+ return find;
+ }
 }
 
 
@@ -484,38 +484,38 @@
 //<remarks>Used by 'strcmpwild'.</remarks>
 inline int strcmpwild_impl(const TCHAR* src,const TCHAR* dst)
 {
- int find = 1;
- for(; *src != 0 && find == 1 && *dst != 0; ++src)
- {
- switch(*src)
- {
- case _T('?'): ++dst; break;
- case _T('['): ++src; find = strcmpwild_cset(&src,&dst); break;
- case _T('*'): find = strcmpwild_astr(&src,&dst); --src; break;
- default : find = (int) (*src == *dst); ++dst;
- }
- }
- while(*src == _T('*') && find == 1) ++src;
- return (int) (find == 1 && *dst == 0 && *src == 0);
+ int find = 1;
+ for(; *src != 0 && find == 1 && *dst != 0; ++src)
+ {
+ switch(*src)
+ {
+ case _T('?'): ++dst; break;
+ case _T('['): ++src; find = strcmpwild_cset(&src,&dst); break;
+ case _T('*'): find = strcmpwild_astr(&src,&dst); --src; break;
+ default : find = (int) (*src == *dst); ++dst;
+ }
+ }
+ while(*src == _T('*') && find == 1) ++src;
+ return (int) (find == 1 && *dst == 0 && *src == 0);
 }
 
 //<summary>Compare two strings, with globbing, and character sets.</summary>
 //<param name="lhs">String or expression for left-hand side of comparison.</param>
 //<param name="rhs">String for right-hand side of comparison.</param>
 //<returns>
-// Returns 1 if src does not match dst, or -1 if either src or dst are null,
-// or 0 if src matches dst.
+// Returns 1 if src does not match dst, or -1 if either src or dst are null,
+// or 0 if src matches dst.
 //</returns>
 //<remarks>
-// Simple regular expressions are permitted in 'src': The character '*' matches
-// zero or more characters up to the next pattern, or the end of the string. The
-// '?' character matches any single character. Character sets and negation are
-// also permitted, for example, '[abcd]', '[a-zA-Z]', etc.
+// Simple regular expressions are permitted in 'src': The character '*' matches
+// zero or more characters up to the next pattern, or the end of the string. The
+// '?' character matches any single character. Character sets and negation are
+// also permitted, for example, '[abcd]', '[a-zA-Z]', etc.
 //</remarks>
 inline int strcmpwild(const TCHAR* src,const TCHAR* dst)
 {
- if(!src || !dst) return -1;
- return (strcmpwild_impl(src,dst)==1)?0:1;
+ if(!src || !dst) return -1;
+ return (strcmpwild_impl(src,dst)==1)?0:1;
 }
 
 
@@ -523,16 +523,16 @@
 //<returns>Pointer to new xml_attribute_struct structure.</returns>
 inline static xml_attribute_struct* new_attribute(void)
 {
- xml_attribute_struct* p = (xml_attribute_struct*)malloc(sizeof(xml_attribute_struct)); //Allocate one attribute.
- if(p) //If allocation succeeded.
- {
- p->name = p->value = 0; //No name or value.
-#ifdef PUGOPT_NONSEG
- p->name_size = p->value_size = 0; //Lengths of zero.
-#endif
- p->name_insitu = p->value_insitu = true; //Default to being in-situ of the parse string.
- }
- return p;
+ xml_attribute_struct* p = (xml_attribute_struct*)malloc(sizeof(xml_attribute_struct)); //Allocate one attribute.
+ if(p) //If allocation succeeded.
+ {
+ p->name = p->value = 0; //No name or value.
+#ifdef PUGOPT_NONSEG
+ p->name_size = p->value_size = 0; //Lengths of zero.
+#endif
+ p->name_insitu = p->value_insitu = true; //Default to being in-situ of the parse string.
+ }
+ return p;
 }
 
 
@@ -541,38 +541,38 @@
 //<returns>Pointer to new xml_node_struct structure.</returns>
 inline static xml_node_struct* new_node(xml_node_type type = node_element)
 {
- xml_node_struct* p = (xml_node_struct*)malloc(sizeof(xml_node_struct)); //Allocate one node.
- if(p) //If allocation succeeded.
- {
- p->name = p->value = 0; //No name or data.
-#ifdef PUGOPT_NONSEG
- p->name_size = p->value_size = 0;
-#endif
- p->type = type; //Set the desired type.
- p->attributes = p->children = 0; //No attributes or children.
- p->name_insitu = p->value_insitu = true; //Default to being in-situ of the parse string.
- if
- (
- type != node_document && //None of these will have attributes.
- type != node_pcdata &&
- type != node_cdata &&
- type != node_include &&
- type != node_comment
- )
- p->attribute = (xml_attribute_struct**)malloc(sizeof(xml_attribute_struct*)); //Allocate one attribute.
- else p->attribute = NULL;
- p->attribute_space = (p->attribute) ? 1 : 0;
- if
- (
- type == node_element || //Only these will have children.
- type == node_doctype ||
- type == node_document
- )
- p->child = (xml_node_struct**)malloc(sizeof(xml_node_struct*)); //Allocate one child.
- else p->child = NULL;
- p->child_space = (p->child) ? 1 : 0;
- }
- return p;
+ xml_node_struct* p = (xml_node_struct*)malloc(sizeof(xml_node_struct)); //Allocate one node.
+ if(p) //If allocation succeeded.
+ {
+ p->name = p->value = 0; //No name or data.
+#ifdef PUGOPT_NONSEG
+ p->name_size = p->value_size = 0;
+#endif
+ p->type = type; //Set the desired type.
+ p->attributes = p->children = 0; //No attributes or children.
+ p->name_insitu = p->value_insitu = true; //Default to being in-situ of the parse string.
+ if
+ (
+ type != node_document && //None of these will have attributes.
+ type != node_pcdata &&
+ type != node_cdata &&
+ type != node_include &&
+ type != node_comment
+ )
+ p->attribute = (xml_attribute_struct**)malloc(sizeof(xml_attribute_struct*)); //Allocate one attribute.
+ else p->attribute = NULL;
+ p->attribute_space = (p->attribute) ? 1 : 0;
+ if
+ (
+ type == node_element || //Only these will have children.
+ type == node_doctype ||
+ type == node_document
+ )
+ p->child = (xml_node_struct**)malloc(sizeof(xml_node_struct*)); //Allocate one child.
+ else p->child = NULL;
+ p->child_space = (p->child) ? 1 : 0;
+ }
+ return p;
 }
 
 
@@ -584,21 +584,21 @@
 //<remarks>Child pointer space of 'node' may be reallocated.</remarks>
 inline static xml_node_struct* append_node(xml_node_struct* parent,long grow,xml_node_type type = node_element)
 {
- if(!parent) return NULL; //Must have a parent.
- if(parent->children == parent->child_space) //Out of pointer space.
- {
- xml_node_struct** t = (xml_node_struct**)realloc(parent->child,sizeof(xml_node_struct*)*(parent->child_space+grow)); //Grow pointer space.
- if(t) //Reallocation succeeded.
- {
- parent->child = t;
- parent->child_space += grow; //Update the available space.
- }
- }
- xml_node_struct* child = new_node(type); //Allocate a new child.
- child->parent = parent; //Set it's parent pointer.
- parent->child[parent->children] = child; //Set the parent's child pointer.
- parent->children++; //One more child.
- return child;
+ if(!parent) return NULL; //Must have a parent.
+ if(parent->children == parent->child_space) //Out of pointer space.
+ {
+ xml_node_struct** t = (xml_node_struct**)realloc(parent->child,sizeof(xml_node_struct*)*(parent->child_space+grow)); //Grow pointer space.
+ if(t) //Reallocation succeeded.
+ {
+ parent->child = t;
+ parent->child_space += grow; //Update the available space.
+ }
+ }
+ xml_node_struct* child = new_node(type); //Allocate a new child.
+ child->parent = parent; //Set it's parent pointer.
+ parent->child[parent->children] = child; //Set the parent's child pointer.
+ parent->children++; //One more child.
+ return child;
 }
 
 
@@ -609,91 +609,91 @@
 //<remarks>Attribute pointer space of 'node' may be reallocated.</remarks>
 inline static xml_attribute_struct* append_attribute(xml_node_struct* node,long grow)
 {
- if(!node) return NULL;
- xml_attribute_struct* a = new_attribute();
- if(!a) return NULL;
- if(node->attributes == node->attribute_space) //Out of space, so grow.
- {
- xml_attribute_struct** t = (xml_attribute_struct**)realloc(node->attribute,sizeof(xml_node_struct*)*(node->attribute_space+grow));
- if(t)
- {
- node->attribute = t;
- node->attribute_space += grow;
- }
- }
- node->attribute[node->attributes] = a;
- node->attributes++;
- return a;
+ if(!node) return NULL;
+ xml_attribute_struct* a = new_attribute();
+ if(!a) return NULL;
+ if(node->attributes == node->attribute_space) //Out of space, so grow.
+ {
+ xml_attribute_struct** t = (xml_attribute_struct**)realloc(node->attribute,sizeof(xml_node_struct*)*(node->attribute_space+grow));
+ if(t)
+ {
+ node->attribute = t;
+ node->attribute_space += grow;
+ }
+ }
+ node->attribute[node->attributes] = a;
+ node->attributes++;
+ return a;
 }
 
 
 //<summary>Non-recursively free a tree.</summary>
 //<param name="root">
-// Pointer to the root of the tree. Note: 'root' must have been dynamically
-// allocated using 'malloc' or 'realloc', as 'free_node' tries to also free
-// the structure pointed to by 'root'.
+// Pointer to the root of the tree. Note: 'root' must have been dynamically
+// allocated using 'malloc' or 'realloc', as 'free_node' tries to also free
+// the structure pointed to by 'root'.
 //</param>
 //<remarks>'root' no longer points to a valid structure.</remarks>
 inline static void free_node(xml_node_struct* node)
 {
- if(!node) return;
+ if(!node) return;
 
- register xml_node_struct* cursor = node;
+ register xml_node_struct* cursor = node;
 
- //Free all children of children.
- do
- {
+ //Free all children of children.
+ do
+ {
 LOC_STEP_INTO:
- for(; cursor->children>0; --cursor->children) //Free each child in turn; 'children' keeps count while we jump around.
- {
- register xml_node_struct* t = cursor->child[cursor->children-1]; //Take a pointer to the child.
- if(t && t->children) //If the child has children.
- {
- cursor = t; //Step in.
- goto LOC_STEP_INTO; //Step into this node.
- }
- else if(t)
- {
- if(t->attributes) //Child has attributes.
- {
- register unsigned int n = t->attributes; //Free each attribute.
- for(register unsigned int i=0; i<n; ++i)
- {
- if(t->attribute[i]->name && !t->attribute[i]->name_insitu)
- free(t->attribute[i]->name);
- if(t->attribute[i]->value && !t->attribute[i]->value_insitu)
- free(t->attribute[i]->value);
- free(t->attribute[i]);
- }
- }
- if(t->attribute) free(t->attribute); //Free attribute pointer space.
- if(t->child) free(t->child); //Free child pointer space.
- if(t->name && !t->name_insitu) free(t->name);
- if(t->value && !t->value_insitu) free(t->value);
- free(t); //Free the child node.
- }
- }
- cursor = cursor->parent; //Step out.
- }
- while(cursor->children); //While there are children.
- //Finally, free the root's children & the root itself.
- if(cursor->attributes)
- {
- register unsigned int n = cursor->attributes;
- for(register unsigned int i=0; i<n; ++i)
- {
- if(cursor->attribute[i]->name && !cursor->attribute[i]->name_insitu)
- free(cursor->attribute[i]->name);
- if(cursor->attribute[i]->value && !cursor->attribute[i]->value_insitu)
- free(cursor->attribute[i]->value);
- free(cursor->attribute[i]);
- }
- }
- if(cursor->attribute) free(cursor->attribute); //Free attribute pointer space.
- if(cursor->child) free(cursor->child); //Free child pointer space.
- if(cursor->name && !cursor->name_insitu) free(cursor->name); //Free name & data.
- if(cursor->value && !cursor->value_insitu) free(cursor->value);
- free(cursor); //Free the root itself.
+ for(; cursor->children>0; --cursor->children) //Free each child in turn; 'children' keeps count while we jump around.
+ {
+ register xml_node_struct* t = cursor->child[cursor->children-1]; //Take a pointer to the child.
+ if(t && t->children) //If the child has children.
+ {
+ cursor = t; //Step in.
+ goto LOC_STEP_INTO; //Step into this node.
+ }
+ else if(t)
+ {
+ if(t->attributes) //Child has attributes.
+ {
+ register unsigned int n = t->attributes; //Free each attribute.
+ for(register unsigned int i=0; i<n; ++i)
+ {
+ if(t->attribute[i]->name && !t->attribute[i]->name_insitu)
+ free(t->attribute[i]->name);
+ if(t->attribute[i]->value && !t->attribute[i]->value_insitu)
+ free(t->attribute[i]->value);
+ free(t->attribute[i]);
+ }
+ }
+ if(t->attribute) free(t->attribute); //Free attribute pointer space.
+ if(t->child) free(t->child); //Free child pointer space.
+ if(t->name && !t->name_insitu) free(t->name);
+ if(t->value && !t->value_insitu) free(t->value);
+ free(t); //Free the child node.
+ }
+ }
+ cursor = cursor->parent; //Step out.
+ }
+ while(cursor->children); //While there are children.
+ //Finally, free the root's children & the root itself.
+ if(cursor->attributes)
+ {
+ register unsigned int n = cursor->attributes;
+ for(register unsigned int i=0; i<n; ++i)
+ {
+ if(cursor->attribute[i]->name && !cursor->attribute[i]->name_insitu)
+ free(cursor->attribute[i]->name);
+ if(cursor->attribute[i]->value && !cursor->attribute[i]->value_insitu)
+ free(cursor->attribute[i]->value);
+ free(cursor->attribute[i]);
+ }
+ }
+ if(cursor->attribute) free(cursor->attribute); //Free attribute pointer space.
+ if(cursor->child) free(cursor->child); //Free child pointer space.
+ if(cursor->name && !cursor->name_insitu) free(cursor->name); //Free name & data.
+ if(cursor->value && !cursor->value_insitu) free(cursor->value);
+ free(cursor); //Free the root itself.
 }
 
 //<summary>Recursively free a tree.</summary>
@@ -701,45 +701,45 @@
 //<remarks>Not used.</remarks>
 inline static void free_node_recursive(xml_node_struct* root)
 {
- if(root)
- {
- unsigned int n = root->attributes;
- register unsigned int i;
- for(i=0; i<n; i++)
- {
- if(root->attribute[i]->name && !root->attribute[i]->name_insitu)
- free(root->attribute[i]->name);
- if(root->attribute[i]->value && !root->attribute[i]->value_insitu)
- free(root->attribute[i]->value);
- free(root->attribute[i]);
- }
- free(root->attribute);
- n = root->children;
- for(i=0; i<n; i++)
- free_node_recursive(root->child[i]);
- free(root->child);
- if(root->name && !root->name_insitu) free(root->name);
- if(root->value && !root->value_insitu) free(root->value);
- free(root);
- }
+ if(root)
+ {
+ unsigned int n = root->attributes;
+ register unsigned int i;
+ for(i=0; i<n; i++)
+ {
+ if(root->attribute[i]->name && !root->attribute[i]->name_insitu)
+ free(root->attribute[i]->name);
+ if(root->attribute[i]->value && !root->attribute[i]->value_insitu)
+ free(root->attribute[i]->value);
+ free(root->attribute[i]);
+ }
+ free(root->attribute);
+ n = root->children;
+ for(i=0; i<n; i++)
+ free_node_recursive(root->child[i]);
+ free(root->child);
+ if(root->name && !root->name_insitu) free(root->name);
+ if(root->value && !root->value_insitu) free(root->value);
+ free(root);
+ }
 }
 
 
 //<summary>Parser utilities.</summary>
-#define SKIPWS() { while(chartype_space(*s)) ++s; if(*s==0) return s; }
-#define OPTSET(OPT) ( optmsk & OPT )
-#define PUSHNODE(TYPE) { cursor = append_node(cursor,growby,TYPE); }
-#define POPNODE() { cursor = cursor->parent; }
-#define SCANFOR(X) { while(*s!=0 && !(X)) ++s; if(*s==0) return s; }
-#define SCANWHILE(X) { while((X)) ++s; if(*s==0) return s; }
+#define SKIPWS() { while(chartype_space(*s)) ++s; if(*s==0) return s; }
+#define OPTSET(OPT) ( optmsk & OPT )
+#define PUSHNODE(TYPE) { cursor = append_node(cursor,growby,TYPE); }
+#define POPNODE() { cursor = cursor->parent; }
+#define SCANFOR(X) { while(*s!=0 && !(X)) ++s; if(*s==0) return s; }
+#define SCANWHILE(X) { while((X)) ++s; if(*s==0) return s; }
 #ifndef PUGOPT_NONSEG
-# define ENDSEG() { ch = *s; *s = 0; ++s; if(*s==0) return s; }
+# define ENDSEG() { ch = *s; *s = 0; ++s; if(*s==0) return s; }
 #else
-# define ENDSEG() { ch = *s; ++s; if(*s==0) return s; }
-# define SETLEN() ( cursor->value_size = s - cursor->value )
-# define ENDSEGDAT() { ch = *s; SETLEN(); ++s; if(*s==0) return s; }
-# define ENDSEGNAM(S) { ch = *s; S->name_size = s - S->name; ++s; if(*s==0) return s; }
-# define ENDSEGATT(S) { ch = *s; S->value_size = s - S->value; ++s; if(*s==0) return s; }
+# define ENDSEG() { ch = *s; ++s; if(*s==0) return s; }
+# define SETLEN() ( cursor->value_size = s - cursor->value )
+# define ENDSEGDAT() { ch = *s; SETLEN(); ++s; if(*s==0) return s; }
+# define ENDSEGNAM(S) { ch = *s; S->name_size = s - S->name; ++s; if(*s==0) return s; }
+# define ENDSEGATT(S) { ch = *s; S->value_size = s - S->value; ++s; if(*s==0) return s; }
 #endif
 
 
@@ -750,645 +750,645 @@
 //<param name="optmsk">Parse options mask.</param>
 //<returns>Last string position or null.</returns>
 //<remarks>
-// Input string is zero-segmented if 'PUGOPT_NONSEG' is not defined. Memory
-// may have been allocated to 'root' (free with 'free_node').
+// Input string is zero-segmented if 'PUGOPT_NONSEG' is not defined. Memory
+// may have been allocated to 'root' (free with 'free_node').
 //</remarks>
 static TCHAR* parse(register TCHAR* s,xml_node_struct* xmldoc,long growby,unsigned long optmsk = parse_default)
 {
- if(!s || !xmldoc) return s;
- TCHAR ch = 0; //Current char, in cases where we must null-terminate before we test.
- xml_node_struct* cursor = xmldoc; //Tree node cursor.
- TCHAR* mark = s; //Marked string position for temporary look-ahead.
- while(*s!=0)
- {
+ if(!s || !xmldoc) return s;
+ TCHAR ch = 0; //Current char, in cases where we must null-terminate before we test.
+ xml_node_struct* cursor = xmldoc; //Tree node cursor.
+ TCHAR* mark = s; //Marked string position for temporary look-ahead.
+ while(*s!=0)
+ {
 LOC_SEARCH: //Obliviously search for next element.
- SCANFOR(chartype_enter(*s)); //Find the next '<'.
- if(chartype_enter(*s))
- {
- ++s;
+ SCANFOR(chartype_enter(*s)); //Find the next '<'.
+ if(chartype_enter(*s))
+ {
+ ++s;
 LOC_CLASSIFY: //What kind of element?
- if(chartype_pi(*s)) //'<?...'
- {
- ++s;
- if(chartype_symbol(*s) && OPTSET(parse_pi))
- {
- mark = s;
- SCANFOR(chartype_pi(*s)); //Look for terminating '?'.
+ if(chartype_pi(*s)) //'<?...'
+ {
+ ++s;
+ if(chartype_symbol(*s) && OPTSET(parse_pi))
+ {
+ mark = s;
+ SCANFOR(chartype_pi(*s)); //Look for terminating '?'.
 #ifndef PUGOPT_NONSEG
- if(chartype_pi(*s)) *s = _T('/'); //Same semantics as for '<.../>', so fudge it.
+ if(chartype_pi(*s)) *s = _T('/'); //Same semantics as for '<.../>', so fudge it.
 #endif
- s = mark;
- PUSHNODE(node_pi); //Append a new node on the tree.
- goto LOC_ELEMENT; //Go read the element name.
- }
- else //Bad PI or parse_pi not set.
- {
- SCANFOR(chartype_leave(*s)); //Look for '>'.
- ++s;
- mark = 0;
- continue;
- }
- }
- else if(chartype_special(*s)) //'<!...'
- {
- ++s;
- if(chartype_dash(*s)) //'<!-...'
- {
- ++s;
- if(OPTSET(parse_comments) && chartype_dash(*s)) //'<!--...'
- {
- ++s;
- PUSHNODE(node_comment); //Append a new node on the tree.
- cursor->value = s; //Save the offset.
- while(*s!=0 && *(s+1) && *(s+2) && !((chartype_dash(*s) && chartype_dash(*(s+1))) && chartype_leave(*(s+2)))) ++s; //Scan for terminating '-->'.
- if(*s==0) return s;
-#ifdef PUGOPT_NONSEG
- SETLEN(); //NF 19 Jan 2003.
-#else
- *s = 0; //Zero-terminate this segment at the first terminating '-'.
-#endif
- if(OPTSET(parse_trim_comment)) //Trim whitespace.
- {
-#ifdef PUGOPT_NONSEG
- strwtrim(&cursor->value,cursor->value_size);
-#else
- if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
- else strwtrim(&cursor->value);
-#endif
- }
- s += 2; //Step over the '\0-'.
- POPNODE(); //Pop since this is a standalone.
- goto LOC_LEAVE; //Look for any following PCDATA.
- }
- else
- {
- while(*s!=0 && *(s+1)!=0 && *(s+2)!=0 && !((chartype_dash(*s) && chartype_dash(*(s+1))) && chartype_leave(*(s+2)))) ++s; //Scan for terminating '-->'.
- if(*s==0) return s;
- s += 2;
- goto LOC_LEAVE; //Look for any following PCDATA.
- }
- }
- else if(chartype_lbracket(*s)) //'<![...'
- {
- ++s;
- if(*s==_T('I')) //'<![I...'
- {
- ++s;
- if(*s==_T('N')) //'<![IN...'
- {
- ++s;
- if(*s==_T('C')) //'<![INC...'
- {
- ++s;
- if(*s==_T('L')) //'<![INCL...'
- {
- ++s;
- if(*s==_T('U')) //'<![INCLU...'
- {
- ++s;
- if(*s==_T('D')) //'<![INCLUD...'
- {
- ++s;
- if(*s==_T('E')) //'<![INCLUDE...'
- {
- ++s;
- if(chartype_lbracket(*s)) //'<![INCLUDE[...'
- {
- ++s;
- if(OPTSET(node_cdata))
- {
- PUSHNODE(node_include); //Append a new node on the tree.
- cursor->value = s; //Save the offset.
- while(!(chartype_rbracket(*s) && chartype_rbracket(*(s+1)) && chartype_leave(*(s+2)))) ++s; //Scan for terminating ']]>'.
- if(chartype_rbracket(*s))
- {
-#ifdef PUGOPT_NONSEG
- SETLEN(); //NF 19 Jan 2003.
-#else
- *s = 0; //Zero-terminate this segment.
-#endif
- ++s;
- if(OPTSET(parse_trim_cdata)) //Trim whitespace.
- {
-#ifdef PUGOPT_NONSEG
- strwtrim(&cursor->value, cursor->value_size);
-#else
- if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
- else strwtrim(&cursor->value);
-#endif
- }
- }
- POPNODE(); //Pop since this is a standalone.
- }
- else //Flagged for discard, but we still have to scan for the terminator.
- {
- while(*s!=0 && *(s+1)!=0 && *(s+2)!=0 && !(chartype_rbracket(*s) && chartype_rbracket(*(s+1)) && chartype_leave(*(s+2)))) ++s; //Scan for terminating ']]>'.
- ++s;
- }
- ++s; //Step over the last ']'.
- goto LOC_LEAVE; //Look for any following PCDATA.
- }
- }
- }
- }
- }
- }
- }
- }
- else if(*s==_T('C')) //'<![C...'
- {
- ++s;
- if(*s==_T('D')) //'<![CD...'
- {
- ++s;
- if(*s==_T('A')) //'<![CDA...'
- {
- ++s;
- if(*s==_T('T')) //'<![CDAT...'
- {
- ++s;
- if(*s==_T('A')) //'<![CDATA...'
- {
- ++s;
- if(chartype_lbracket(*s)) //'<![CDATA[...'
- {
- ++s;
- if(OPTSET(parse_cdata))
- {
- PUSHNODE(node_cdata); //Append a new node on the tree.
- cursor->value = s; //Save the offset.
- while(*s!=0 && *(s+1)!=0 && *(s+2)!=0 && !(chartype_rbracket(*s) && chartype_rbracket(*(s+1)) && chartype_leave(*(s+2)))) ++s; //Scan for terminating ']]>'.
- if(*(s+2)==0) return s; //Very badly formed.
- if(chartype_rbracket(*s))
- {
-#ifdef PUGOPT_NONSEG
- SETLEN(); //NF 19 Jan 2003.
-#else
- *s = 0; //Zero-terminate this segment.
-#endif
- ++s;
- if(OPTSET(parse_trim_cdata)) //Trim whitespace.
- {
-#ifdef PUGOPT_NONSEG
- strwtrim(&cursor->value,cursor->value_size);
-#else
- if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
- else strwtrim(&cursor->value);
-#endif
- }
- }
- POPNODE(); //Pop since this is a standalone.
- }
- else //Flagged for discard, but we still have to scan for the terminator.
- {
- while(*s!=0 && *(s+1)!=0 && *(s+2)!=0 && !(chartype_rbracket(*s) && chartype_rbracket(*(s+1)) && chartype_leave(*(s+2)))) ++s; //Scan for terminating ']]>'.
- ++s;
- }
- ++s; //Step over the last ']'.
- goto LOC_LEAVE; //Look for any following PCDATA.
- }
- }
- }
- }
- }
- }
- continue; //Probably a corrupted CDATA section, so just eat it.
- }
- else if(*s==_T('D')) //'<!D...'
- {
- ++s;
- if(*s==_T('O')) //'<!DO...'
- {
- ++s;
- if(*s==_T('C')) //'<!DOC...'
- {
- ++s;
- if(*s==_T('T')) //'<!DOCT...'
- {
- ++s;
- if(*s==_T('Y')) //'<!DOCTY...'
- {
- ++s;
- if(*s==_T('P')) //'<!DOCTYP...'
- {
- ++s;
- if(*s==_T('E')) //'<!DOCTYPE...'
- {
- ++s;
- SKIPWS(); //Eat any whitespace.
- xml_attribute_struct* a = 0;
- if(OPTSET(parse_doctype))
- {
- PUSHNODE(node_doctype); //Append a new node on the tree.
- a = append_attribute(cursor,3); //Store the DOCTYPE name.
- a->value = a->name = s; //Save the offset.
- }
- SCANWHILE(chartype_symbol(*s)); //'<!DOCTYPE symbol...'
+ s = mark;
+ PUSHNODE(node_pi); //Append a new node on the tree.
+ goto LOC_ELEMENT; //Go read the element name.
+ }
+ else //Bad PI or parse_pi not set.
+ {
+ SCANFOR(chartype_leave(*s)); //Look for '>'.
+ ++s;
+ mark = 0;
+ continue;
+ }
+ }
+ else if(chartype_special(*s)) //'<!...'
+ {
+ ++s;
+ if(chartype_dash(*s)) //'<!-...'
+ {
+ ++s;
+ if(OPTSET(parse_comments) && chartype_dash(*s)) //'<!--...'
+ {
+ ++s;
+ PUSHNODE(node_comment); //Append a new node on the tree.
+ cursor->value = s; //Save the offset.
+ while(*s!=0 && *(s+1) && *(s+2) && !((chartype_dash(*s) && chartype_dash(*(s+1))) && chartype_leave(*(s+2)))) ++s; //Scan for terminating '-->'.
+ if(*s==0) return s;
+#ifdef PUGOPT_NONSEG
+ SETLEN(); //NF 19 Jan 2003.
+#else
+ *s = 0; //Zero-terminate this segment at the first terminating '-'.
+#endif
+ if(OPTSET(parse_trim_comment)) //Trim whitespace.
+ {
+#ifdef PUGOPT_NONSEG
+ strwtrim(&cursor->value,cursor->value_size);
+#else
+ if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
+ else strwtrim(&cursor->value);
+#endif
+ }
+ s += 2; //Step over the '\0-'.
+ POPNODE(); //Pop since this is a standalone.
+ goto LOC_LEAVE; //Look for any following PCDATA.
+ }
+ else
+ {
+ while(*s!=0 && *(s+1)!=0 && *(s+2)!=0 && !((chartype_dash(*s) && chartype_dash(*(s+1))) && chartype_leave(*(s+2)))) ++s; //Scan for terminating '-->'.
+ if(*s==0) return s;
+ s += 2;
+ goto LOC_LEAVE; //Look for any following PCDATA.
+ }
+ }
+ else if(chartype_lbracket(*s)) //'<![...'
+ {
+ ++s;
+ if(*s==_T('I')) //'<![I...'
+ {
+ ++s;
+ if(*s==_T('N')) //'<![IN...'
+ {
+ ++s;
+ if(*s==_T('C')) //'<![INC...'
+ {
+ ++s;
+ if(*s==_T('L')) //'<![INCL...'
+ {
+ ++s;
+ if(*s==_T('U')) //'<![INCLU...'
+ {
+ ++s;
+ if(*s==_T('D')) //'<![INCLUD...'
+ {
+ ++s;
+ if(*s==_T('E')) //'<![INCLUDE...'
+ {
+ ++s;
+ if(chartype_lbracket(*s)) //'<![INCLUDE[...'
+ {
+ ++s;
+ if(OPTSET(node_cdata))
+ {
+ PUSHNODE(node_include); //Append a new node on the tree.
+ cursor->value = s; //Save the offset.
+ while(!(chartype_rbracket(*s) && chartype_rbracket(*(s+1)) && chartype_leave(*(s+2)))) ++s; //Scan for terminating ']]>'.
+ if(chartype_rbracket(*s))
+ {
+#ifdef PUGOPT_NONSEG
+ SETLEN(); //NF 19 Jan 2003.
+#else
+ *s = 0; //Zero-terminate this segment.
+#endif
+ ++s;
+ if(OPTSET(parse_trim_cdata)) //Trim whitespace.
+ {
+#ifdef PUGOPT_NONSEG
+ strwtrim(&cursor->value, cursor->value_size);
+#else
+ if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
+ else strwtrim(&cursor->value);
+#endif
+ }
+ }
+ POPNODE(); //Pop since this is a standalone.
+ }
+ else //Flagged for discard, but we still have to scan for the terminator.
+ {
+ while(*s!=0 && *(s+1)!=0 && *(s+2)!=0 && !(chartype_rbracket(*s) && chartype_rbracket(*(s+1)) && chartype_leave(*(s+2)))) ++s; //Scan for terminating ']]>'.
+ ++s;
+ }
+ ++s; //Step over the last ']'.
+ goto LOC_LEAVE; //Look for any following PCDATA.
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if(*s==_T('C')) //'<![C...'
+ {
+ ++s;
+ if(*s==_T('D')) //'<![CD...'
+ {
+ ++s;
+ if(*s==_T('A')) //'<![CDA...'
+ {
+ ++s;
+ if(*s==_T('T')) //'<![CDAT...'
+ {
+ ++s;
+ if(*s==_T('A')) //'<![CDATA...'
+ {
+ ++s;
+ if(chartype_lbracket(*s)) //'<![CDATA[...'
+ {
+ ++s;
+ if(OPTSET(parse_cdata))
+ {
+ PUSHNODE(node_cdata); //Append a new node on the tree.
+ cursor->value = s; //Save the offset.
+ while(*s!=0 && *(s+1)!=0 && *(s+2)!=0 && !(chartype_rbracket(*s) && chartype_rbracket(*(s+1)) && chartype_leave(*(s+2)))) ++s; //Scan for terminating ']]>'.
+ if(*(s+2)==0) return s; //Very badly formed.
+ if(chartype_rbracket(*s))
+ {
+#ifdef PUGOPT_NONSEG
+ SETLEN(); //NF 19 Jan 2003.
+#else
+ *s = 0; //Zero-terminate this segment.
+#endif
+ ++s;
+ if(OPTSET(parse_trim_cdata)) //Trim whitespace.
+ {
+#ifdef PUGOPT_NONSEG
+ strwtrim(&cursor->value,cursor->value_size);
+#else
+ if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
+ else strwtrim(&cursor->value);
+#endif
+ }
+ }
+ POPNODE(); //Pop since this is a standalone.
+ }
+ else //Flagged for discard, but we still have to scan for the terminator.
+ {
+ while(*s!=0 && *(s+1)!=0 && *(s+2)!=0 && !(chartype_rbracket(*s) && chartype_rbracket(*(s+1)) && chartype_leave(*(s+2)))) ++s; //Scan for terminating ']]>'.
+ ++s;
+ }
+ ++s; //Step over the last ']'.
+ goto LOC_LEAVE; //Look for any following PCDATA.
+ }
+ }
+ }
+ }
+ }
+ }
+ continue; //Probably a corrupted CDATA section, so just eat it.
+ }
+ else if(*s==_T('D')) //'<!D...'
+ {
+ ++s;
+ if(*s==_T('O')) //'<!DO...'
+ {
+ ++s;
+ if(*s==_T('C')) //'<!DOC...'
+ {
+ ++s;
+ if(*s==_T('T')) //'<!DOCT...'
+ {
+ ++s;
+ if(*s==_T('Y')) //'<!DOCTY...'
+ {
+ ++s;
+ if(*s==_T('P')) //'<!DOCTYP...'
+ {
+ ++s;
+ if(*s==_T('E')) //'<!DOCTYPE...'
+ {
+ ++s;
+ SKIPWS(); //Eat any whitespace.
+ xml_attribute_struct* a = 0;
+ if(OPTSET(parse_doctype))
+ {
+ PUSHNODE(node_doctype); //Append a new node on the tree.
+ a = append_attribute(cursor,3); //Store the DOCTYPE name.
+ a->value = a->name = s; //Save the offset.
+ }
+ SCANWHILE(chartype_symbol(*s)); //'<!DOCTYPE symbol...'
 #ifdef PUGOPT_NONSEG
- if(OPTSET(parse_doctype))
- a->name_size = a->value_size = s - a->value; //Save the length. rem: Before ENDSEG()
+ if(OPTSET(parse_doctype))
+ a->name_size = a->value_size = s - a->value; //Save the length. rem: Before ENDSEG()
 #endif
- ENDSEG(); //Save char in 'ch', terminate & step over.
- if(chartype_space(ch)) SKIPWS(); //Eat any whitespace.
+ ENDSEG(); //Save char in 'ch', terminate & step over.
+ if(chartype_space(ch)) SKIPWS(); //Eat any whitespace.
 LOC_DOCTYPE_SYMBOL:
- if(chartype_symbol(*s))
- {
- mark = s;
- SCANWHILE(chartype_symbol(*s)); //'...symbol SYSTEM...'
- if(OPTSET(parse_doctype))
- {
- a = append_attribute(cursor,1);
- a->value = a->name = mark;
-#ifdef PUGOPT_NONSEG
- a->value_size = a->name_size = s - mark; //NF 19 Jan 2003.
-#else
- *s = 0;
-#endif
- }
- ++s;
- SKIPWS();
- }
- if(chartype_quote(*s)) //'...SYSTEM "..."'
- {
+ if(chartype_symbol(*s))
+ {
+ mark = s;
+ SCANWHILE(chartype_symbol(*s)); //'...symbol SYSTEM...'
+ if(OPTSET(parse_doctype))
+ {
+ a = append_attribute(cursor,1);
+ a->value = a->name = mark;
+#ifdef PUGOPT_NONSEG
+ a->value_size = a->name_size = s - mark; //NF 19 Jan 2003.
+#else
+ *s = 0;
+#endif
+ }
+ ++s;
+ SKIPWS();
+ }
+ if(chartype_quote(*s)) //'...SYSTEM "..."'
+ {
 LOC_DOCTYPE_QUOTE:
- ch = *s;
- ++s;
- mark = s;
- while(*s!=0 && *s != ch) ++s;
- if(*s!=0)
- {
- if(OPTSET(parse_doctype))
- {
- a = append_attribute(cursor,1);
- a->value = mark;
-#ifdef PUGOPT_NONSEG
- a->value_size = s - mark; //NF 19 Jan 2003.
-#else
- *s = 0;
-#endif
- }
- ++s;
- SKIPWS(); //Eat whitespace.
- if(chartype_quote(*s)) goto LOC_DOCTYPE_QUOTE; //Another quoted section to store.
- else if(chartype_symbol(*s)) goto LOC_DOCTYPE_SYMBOL; //Not wellformed, but just parse it.
- }
- }
- if(chartype_lbracket(*s)) //'...[...'
- {
- ++s; //Step over the bracket.
- if(OPTSET(parse_doctype)) cursor->value = s; //Store the offset.
- unsigned int bd = 1; //Bracket depth counter.
- while(*s!=0) //Loop till we're out of all brackets.
- {
- if(chartype_rbracket(*s)) --bd;
- else if(chartype_lbracket(*s)) ++bd;
- if(bd == 0) break;
- ++s;
- }
- //Note: 's' now points to end of DTD, i.e.: ']'.
- if(OPTSET(parse_doctype))
- {
- //Note: If we aren't parsing the DTD ('!parse_dtd', etc.) then it is stored in the DOM as one whole chunk.
-#ifdef PUGOPT_NONSEG
- SETLEN(); //NF 19 Jan 2003
-#else
- *s = 0; //Zero-terminate.
-#endif
- if(OPTSET(parse_dtd)||OPTSET(parse_dtd_only))
- {
- if(OPTSET(parse_dtd))
- {
-#ifdef PUGOPT_NONSEG
- TCHAR svch = *s;
- try
- {
- *s = 0; //Zero-terminate.
- parse(cursor->value,cursor,growby,optmsk); //Parse it.
- }
- catch(...){ assert(false); }
- *s = svch;
-#else
- parse(cursor->value,cursor,growby,optmsk); //Parse it.
-#endif
- }
- if(OPTSET(parse_dtd_only)) return (s+1); //Flagged to parse DTD only, so leave here.
- }
- else if(OPTSET(parse_trim_doctype)) //Trim whitespace.
- {
-#ifdef PUGOPT_NONSEG
- strwtrim(&cursor->value, cursor->value_size);
-#else
- if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
- else strwtrim(&cursor->value);
-#endif
- }
- ++s; //Step over the zero.
- POPNODE(); //Pop since this is a standalone.
- }
- SCANFOR(chartype_leave(*s));
- continue;
- }
- //Fall-through; make sure we pop.
- POPNODE(); //Pop since this is a standalone.
- continue;
- }
- }
- }
- }
- }
- }
- }
- else if(chartype_symbol(*s)) //An inline DTD tag.
- {
- mark = s;
- SCANWHILE(chartype_symbol(*s));
- ENDSEG(); //Save char in 'ch', terminate & step over.
- xml_node_type e = node_dtd_entity;
-#ifdef PUGOPT_NONSEG
- const unsigned int dtdilen = (s - 1) - mark;
- if(_tcsncmp(mark,_T("ATTLIST"),max((7*sizeof(TCHAR)),dtdilen))==0) e = node_dtd_attlist;
- else if(_tcsncmp(mark,_T("ELEMENT"),max((7*sizeof(TCHAR)),dtdilen))==0) e = node_dtd_element;
- else if(_tcsncmp(mark,_T("NOTATION"),max((8*sizeof(TCHAR)),dtdilen))==0) e = node_dtd_notation;
-#else
- if(_tcscmp(mark,_T("ATTLIST"))==0) e = node_dtd_attlist;
- else if(_tcscmp(mark,_T("ELEMENT"))==0) e = node_dtd_element;
- else if(_tcscmp(mark,_T("NOTATION"))==0) e = node_dtd_notation;
-#endif
- PUSHNODE(e); //Append a new node on the tree.
- if(*s!=0 && chartype_space(ch))
- {
- SKIPWS(); //Eat whitespace.
- if(chartype_symbol(*s) || *s==_T('%'))
- {
- mark = s;
- if(*s==_T('%')) //Could be '<!ENTITY % name' -or- '<!ENTITY %name'
- {
-#ifdef PUGOPT_NONSEG
- //Note: For memory-mapped file support we need to treat 's' as read-only so we can't do '*(s-1) = _T('%');' below.
- cursor->name = mark; //Sort out extraneous whitespace when we retrieve it. TODO: Whitespace cleanup.
-#endif
- ++s;
- if(chartype_space(*s))
- {
- SKIPWS(); //Eat whitespace.
+ ch = *s;
+ ++s;
+ mark = s;
+ while(*s!=0 && *s != ch) ++s;
+ if(*s!=0)
+ {
+ if(OPTSET(parse_doctype))
+ {
+ a = append_attribute(cursor,1);
+ a->value = mark;
+#ifdef PUGOPT_NONSEG
+ a->value_size = s - mark; //NF 19 Jan 2003.
+#else
+ *s = 0;
+#endif
+ }
+ ++s;
+ SKIPWS(); //Eat whitespace.
+ if(chartype_quote(*s)) goto LOC_DOCTYPE_QUOTE; //Another quoted section to store.
+ else if(chartype_symbol(*s)) goto LOC_DOCTYPE_SYMBOL; //Not wellformed, but just parse it.
+ }
+ }
+ if(chartype_lbracket(*s)) //'...[...'
+ {
+ ++s; //Step over the bracket.
+ if(OPTSET(parse_doctype)) cursor->value = s; //Store the offset.
+ unsigned int bd = 1; //Bracket depth counter.
+ while(*s!=0) //Loop till we're out of all brackets.
+ {
+ if(chartype_rbracket(*s)) --bd;
+ else if(chartype_lbracket(*s)) ++bd;
+ if(bd == 0) break;
+ ++s;
+ }
+ //Note: 's' now points to end of DTD, i.e.: ']'.
+ if(OPTSET(parse_doctype))
+ {
+ //Note: If we aren't parsing the DTD ('!parse_dtd', etc.) then it is stored in the DOM as one whole chunk.
+#ifdef PUGOPT_NONSEG
+ SETLEN(); //NF 19 Jan 2003
+#else
+ *s = 0; //Zero-terminate.
+#endif
+ if(OPTSET(parse_dtd)||OPTSET(parse_dtd_only))
+ {
+ if(OPTSET(parse_dtd))
+ {
+#ifdef PUGOPT_NONSEG
+ TCHAR svch = *s;
+ try
+ {
+ *s = 0; //Zero-terminate.
+ parse(cursor->value,cursor,growby,optmsk); //Parse it.
+ }
+ catch(...){ assert(false); }
+ *s = svch;
+#else
+ parse(cursor->value,cursor,growby,optmsk); //Parse it.
+#endif
+ }
+ if(OPTSET(parse_dtd_only)) return (s+1); //Flagged to parse DTD only, so leave here.
+ }
+ else if(OPTSET(parse_trim_doctype)) //Trim whitespace.
+ {
+#ifdef PUGOPT_NONSEG
+ strwtrim(&cursor->value, cursor->value_size);
+#else
+ if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
+ else strwtrim(&cursor->value);
+#endif
+ }
+ ++s; //Step over the zero.
+ POPNODE(); //Pop since this is a standalone.
+ }
+ SCANFOR(chartype_leave(*s));
+ continue;
+ }
+ //Fall-through; make sure we pop.
+ POPNODE(); //Pop since this is a standalone.
+ continue;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if(chartype_symbol(*s)) //An inline DTD tag.
+ {
+ mark = s;
+ SCANWHILE(chartype_symbol(*s));
+ ENDSEG(); //Save char in 'ch', terminate & step over.
+ xml_node_type e = node_dtd_entity;
+#ifdef PUGOPT_NONSEG
+ const unsigned int dtdilen = (s - 1) - mark;
+ if(_tcsncmp(mark,_T("ATTLIST"),(std::max)((7*sizeof(TCHAR)),dtdilen))==0) e = node_dtd_attlist;
+ else if(_tcsncmp(mark,_T("ELEMENT"),(std::max)((7*sizeof(TCHAR)),dtdilen))==0) e = node_dtd_element;
+ else if(_tcsncmp(mark,_T("NOTATION"),(std::max)((8*sizeof(TCHAR)),dtdilen))==0) e = node_dtd_notation;
+#else
+ if(_tcscmp(mark,_T("ATTLIST"))==0) e = node_dtd_attlist;
+ else if(_tcscmp(mark,_T("ELEMENT"))==0) e = node_dtd_element;
+ else if(_tcscmp(mark,_T("NOTATION"))==0) e = node_dtd_notation;
+#endif
+ PUSHNODE(e); //Append a new node on the tree.
+ if(*s!=0 && chartype_space(ch))
+ {
+ SKIPWS(); //Eat whitespace.
+ if(chartype_symbol(*s) || *s==_T('%'))
+ {
+ mark = s;
+ if(*s==_T('%')) //Could be '<!ENTITY % name' -or- '<!ENTITY %name'
+ {
+#ifdef PUGOPT_NONSEG
+ //Note: For memory-mapped file support we need to treat 's' as read-only so we can't do '*(s-1) = _T('%');' below.
+ cursor->name = mark; //Sort out extraneous whitespace when we retrieve it. TODO: Whitespace cleanup.
+#endif
+ ++s;
+ if(chartype_space(*s))
+ {
+ SKIPWS(); //Eat whitespace.
 #ifndef PUGOPT_NONSEG
- *(s-1) = _T('%');
- cursor->name = (s-1);
+ *(s-1) = _T('%');
+ cursor->name = (s-1);
 #endif
- }
+ }
 #ifndef PUGOPT_NONSEG
- else cursor->name = mark;
+ else cursor->name = mark;
 #endif
- }
- else cursor->name = s;
- SCANWHILE(chartype_symbol(*s));
-#ifdef PUGOPT_NONSEG
- cursor->name_size = s - cursor->name;
-#endif
- ENDSEG(); //Save char in 'ch', terminate & step over.
- if(chartype_space(ch))
- {
- SKIPWS(); //Eat whitespace.
- if(e == node_dtd_entity) //Special case; may have multiple quoted sections w/anything inside.
- {
- cursor->value = s; //Just store everything here.
- bool qq = false; //Quote in/out flag.
- while(*s != 0) //Loop till we find the right sequence.
- {
- if(!qq && chartype_quote(*s)){ ch = *s; qq = true; }
- else if(qq && *s == ch) qq = false;
- else if(!qq && chartype_leave(*s)) //Not in quoted reqion and '>' hit.
- {
-#ifdef PUGOPT_NONSEG
- SETLEN(); //NF 19 Jan 2003.
-#else
- *s = 0;
-#endif
- ++s;
- if(OPTSET(parse_trim_entity))
- {
-#ifdef PUGOPT_NONSEG
- strwtrim(&cursor->value,cursor->value_size);
-#else
- if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
- else strwtrim(&cursor->value);
-#endif
- }
- POPNODE();
- goto LOC_SEARCH;
- }
- ++s;
- }
- if(OPTSET(parse_trim_entity))
- {
-#ifdef PUGOPT_NONSEG
- strwtrim(&cursor->value, cursor->value_size);
-#else
- if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
- else strwtrim(&cursor->value);
-#endif
- }
- }
- else
- {
- cursor->value = s;
- SCANFOR(chartype_leave(*s)); //Just look for '>'.
-#ifdef PUGOPT_NONSEG
- SETLEN(); //NF 19 Jan 2003.
-#else
- *s = 0;
-#endif
- ++s;
- if(OPTSET(parse_trim_entity))
- {
-#ifdef PUGOPT_NONSEG
- strwtrim(&cursor->value, cursor->value_size);
-#else
- if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
- else strwtrim(&cursor->value);
-#endif
- }
- POPNODE();
- goto LOC_SEARCH;
- }
- }
- }
- }
- POPNODE();
- }
- }
- else if(chartype_symbol(*s)) //'<#...'
- {
- cursor = append_node(cursor,growby); //Append a new node to the tree.
+ }
+ else cursor->name = s;
+ SCANWHILE(chartype_symbol(*s));
+#ifdef PUGOPT_NONSEG
+ cursor->name_size = s - cursor->name;
+#endif
+ ENDSEG(); //Save char in 'ch', terminate & step over.
+ if(chartype_space(ch))
+ {
+ SKIPWS(); //Eat whitespace.
+ if(e == node_dtd_entity) //Special case; may have multiple quoted sections w/anything inside.
+ {
+ cursor->value = s; //Just store everything here.
+ bool qq = false; //Quote in/out flag.
+ while(*s != 0) //Loop till we find the right sequence.
+ {
+ if(!qq && chartype_quote(*s)){ ch = *s; qq = true; }
+ else if(qq && *s == ch) qq = false;
+ else if(!qq && chartype_leave(*s)) //Not in quoted reqion and '>' hit.
+ {
+#ifdef PUGOPT_NONSEG
+ SETLEN(); //NF 19 Jan 2003.
+#else
+ *s = 0;
+#endif
+ ++s;
+ if(OPTSET(parse_trim_entity))
+ {
+#ifdef PUGOPT_NONSEG
+ strwtrim(&cursor->value,cursor->value_size);
+#else
+ if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
+ else strwtrim(&cursor->value);
+#endif
+ }
+ POPNODE();
+ goto LOC_SEARCH;
+ }
+ ++s;
+ }
+ if(OPTSET(parse_trim_entity))
+ {
+#ifdef PUGOPT_NONSEG
+ strwtrim(&cursor->value, cursor->value_size);
+#else
+ if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
+ else strwtrim(&cursor->value);
+#endif
+ }
+ }
+ else
+ {
+ cursor->value = s;
+ SCANFOR(chartype_leave(*s)); //Just look for '>'.
+#ifdef PUGOPT_NONSEG
+ SETLEN(); //NF 19 Jan 2003.
+#else
+ *s = 0;
+#endif
+ ++s;
+ if(OPTSET(parse_trim_entity))
+ {
+#ifdef PUGOPT_NONSEG
+ strwtrim(&cursor->value, cursor->value_size);
+#else
+ if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
+ else strwtrim(&cursor->value);
+#endif
+ }
+ POPNODE();
+ goto LOC_SEARCH;
+ }
+ }
+ }
+ }
+ POPNODE();
+ }
+ }
+ else if(chartype_symbol(*s)) //'<#...'
+ {
+ cursor = append_node(cursor,growby); //Append a new node to the tree.
 LOC_ELEMENT: //Scan for & store element name.
- cursor->name = s;
- SCANWHILE(chartype_symbol(*s)); //Scan for a terminator.
+ cursor->name = s;
+ SCANWHILE(chartype_symbol(*s)); //Scan for a terminator.
 #ifdef PUGOPT_NONSEG
- cursor->name_size = s - cursor->name; //Note: Before ENDSEG().
+ cursor->name_size = s - cursor->name; //Note: Before ENDSEG().
 #endif
- ENDSEG(); //Save char in 'ch', terminate & step over.
- if
- (
- *s!=0 &&
- (
- chartype_close(ch) //'</...'
-#ifdef PUGOPT_NONSEG
- //||
- //chartype_pi(ch) //Treat '?>' as '/>' NF 19 Jan 2003
-#endif
- )
- )
- {
- SCANFOR(chartype_leave(*s)); //Scan for '>', stepping over the tag name.
- POPNODE(); //Pop.
- continue;
- }
- else if(*s!=0 && !chartype_space(ch)) goto LOC_PCDATA; //No attributes, so scan for PCDATA.
- else if(*s!=0 && chartype_space(ch))
- {
- SKIPWS(); //Eat any whitespace.
+ ENDSEG(); //Save char in 'ch', terminate & step over.
+ if
+ (
+ *s!=0 &&
+ (
+ chartype_close(ch) //'</...'
+#ifdef PUGOPT_NONSEG
+ //||
+ //chartype_pi(ch) //Treat '?>' as '/>' NF 19 Jan 2003
+#endif
+ )
+ )
+ {
+ SCANFOR(chartype_leave(*s)); //Scan for '>', stepping over the tag name.
+ POPNODE(); //Pop.
+ continue;
+ }
+ else if(*s!=0 && !chartype_space(ch)) goto LOC_PCDATA; //No attributes, so scan for PCDATA.
+ else if(*s!=0 && chartype_space(ch))
+ {
+ SKIPWS(); //Eat any whitespace.
 LOC_ATTRIBUTE:
- if(chartype_symbol(*s)) //<... #...
- {
- xml_attribute_struct* a = append_attribute(cursor,growby); //Make space for this attribute.
- a->name = s; //Save the offset.
- SCANWHILE(chartype_symbol(*s)); //Scan for a terminator.
-#ifdef PUGOPT_NONSEG
- ENDSEGNAM(a);
-#else
- ENDSEG(); //Save char in 'ch', terminate & step over.
-#endif
- if(*s!=0 && chartype_space(ch)) SKIPWS(); //Eat any whitespace.
- if(*s!=0 && (chartype_equals(ch) || chartype_equals(*s))) //'<... #=...'
- {
- if(chartype_equals(*s)) ++s;
- SKIPWS(); //Eat any whitespace.
- if(chartype_quote(*s)) //'<... #="...'
- {
- ch = *s; //Save quote char to avoid breaking on "''" -or- '""'.
- ++s; //Step over the quote.
- a->value = s; //Save the offset.
- SCANFOR(*s == ch); //Scan for the terminating quote, or '>'.
-#ifdef PUGOPT_NONSEG
- ENDSEGATT(a);
-#else
- ENDSEG(); //Save char in 'ch', terminate & step over.
-#endif
- if(OPTSET(parse_trim_attribute)) //Trim whitespace.
- {
-#ifdef PUGOPT_NONSEG
- strwtrim(&a->value,a->value_size);
-#else
- if(OPTSET(parse_wnorm)) strwnorm(&a->value);
- else strwtrim(&a->value);
-#endif
- }
- if(chartype_leave(*s)){ ++s; goto LOC_PCDATA; }
- else if(chartype_close(*s))
- {
- ++s;
- POPNODE();
- SKIPWS(); //Eat any whitespace.
- if(chartype_leave(*s)) ++s;
- goto LOC_PCDATA;
- }
- if(chartype_space(*s)) //This may indicate a following attribute.
- {
- SKIPWS(); //Eat any whitespace.
- goto LOC_ATTRIBUTE; //Go scan for additional attributes.
- }
- }
- }
- if(chartype_symbol(*s)) goto LOC_ATTRIBUTE;
- else if(*s!=0 && cursor->type == node_pi)
- {
-#ifdef PUGOPT_NONSEG
- SCANFOR(chartype_pi(*s)); //compliments change where we don't fudge to '/>' when we find the PI. NF 20 Jan 2003
- SKIPWS(); //Eat any whitespace.
- if(chartype_pi(*s)) ++s;
-#else
- SCANFOR(chartype_close(*s));
- SKIPWS(); //Eat any whitespace.
- if(chartype_close(*s)) ++s;
-#endif
- SKIPWS(); //Eat any whitespace.
- if(chartype_leave(*s)) ++s;
- POPNODE();
- goto LOC_PCDATA;
- }
- }
- }
+ if(chartype_symbol(*s)) //<... #...
+ {
+ xml_attribute_struct* a = append_attribute(cursor,growby); //Make space for this attribute.
+ a->name = s; //Save the offset.
+ SCANWHILE(chartype_symbol(*s)); //Scan for a terminator.
+#ifdef PUGOPT_NONSEG
+ ENDSEGNAM(a);
+#else
+ ENDSEG(); //Save char in 'ch', terminate & step over.
+#endif
+ if(*s!=0 && chartype_space(ch)) SKIPWS(); //Eat any whitespace.
+ if(*s!=0 && (chartype_equals(ch) || chartype_equals(*s))) //'<... #=...'
+ {
+ if(chartype_equals(*s)) ++s;
+ SKIPWS(); //Eat any whitespace.
+ if(chartype_quote(*s)) //'<... #="...'
+ {
+ ch = *s; //Save quote char to avoid breaking on "''" -or- '""'.
+ ++s; //Step over the quote.
+ a->value = s; //Save the offset.
+ SCANFOR(*s == ch); //Scan for the terminating quote, or '>'.
+#ifdef PUGOPT_NONSEG
+ ENDSEGATT(a);
+#else
+ ENDSEG(); //Save char in 'ch', terminate & step over.
+#endif
+ if(OPTSET(parse_trim_attribute)) //Trim whitespace.
+ {
+#ifdef PUGOPT_NONSEG
+ strwtrim(&a->value,a->value_size);
+#else
+ if(OPTSET(parse_wnorm)) strwnorm(&a->value);
+ else strwtrim(&a->value);
+#endif
+ }
+ if(chartype_leave(*s)){ ++s; goto LOC_PCDATA; }
+ else if(chartype_close(*s))
+ {
+ ++s;
+ POPNODE();
+ SKIPWS(); //Eat any whitespace.
+ if(chartype_leave(*s)) ++s;
+ goto LOC_PCDATA;
+ }
+ if(chartype_space(*s)) //This may indicate a following attribute.
+ {
+ SKIPWS(); //Eat any whitespace.
+ goto LOC_ATTRIBUTE; //Go scan for additional attributes.
+ }
+ }
+ }
+ if(chartype_symbol(*s)) goto LOC_ATTRIBUTE;
+ else if(*s!=0 && cursor->type == node_pi)
+ {
+#ifdef PUGOPT_NONSEG
+ SCANFOR(chartype_pi(*s)); //compliments change where we don't fudge to '/>' when we find the PI. NF 20 Jan 2003
+ SKIPWS(); //Eat any whitespace.
+ if(chartype_pi(*s)) ++s;
+#else
+ SCANFOR(chartype_close(*s));
+ SKIPWS(); //Eat any whitespace.
+ if(chartype_close(*s)) ++s;
+#endif
+ SKIPWS(); //Eat any whitespace.
+ if(chartype_leave(*s)) ++s;
+ POPNODE();
+ goto LOC_PCDATA;
+ }
+ }
+ }
 LOC_LEAVE:
- if(chartype_leave(*s)) //'...>'
- {
- ++s; //Step over the '>'.
+ if(chartype_leave(*s)) //'...>'
+ {
+ ++s; //Step over the '>'.
 LOC_PCDATA: //'>...<'
- mark = s; //Save this offset while searching for a terminator.
- SKIPWS(); //Eat whitespace if no genuine PCDATA here.
- if(chartype_enter(*s)) //We hit a '<...', with only whitespace, so don't bother storing anything.
- {
- if(chartype_close(*(s+1))) //'</...'
- {
- SCANFOR(chartype_leave(*s)); //Scan for '>', stepping over any end-tag name.
- POPNODE(); //Pop.
- continue; //Continue scanning.
- }
- else goto LOC_SEARCH; //Expect a new element enter, so go scan for it.
- }
- s = mark; //We hit something other than whitespace; restore the original offset.
- PUSHNODE(node_pcdata); //Append a new node on the tree.
- cursor->value = s; //Save the offset.
- SCANFOR(chartype_enter(*s)); //'...<'
-#ifdef PUGOPT_NONSEG
- ENDSEGDAT();
-#else
- ENDSEG(); //Save char in 'ch', terminate & step over.
-#endif
- if(OPTSET(parse_trim_pcdata)) //Trim whitespace.
- {
-#ifdef PUGOPT_NONSEG
- strwtrim(&cursor->value,cursor->value_size);
-#else
- if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
- else strwtrim(&cursor->value);
-#endif
- }
- POPNODE(); //Pop since this is a standalone.
- if(chartype_enter(ch)) //Did we hit a '<...'?
- {
- if(chartype_close(*s)) //'</...'
- {
- SCANFOR(chartype_leave(*s)); //'...>'
- POPNODE(); //Pop.
- goto LOC_LEAVE;
- }
- else if(chartype_special(*s)) goto LOC_CLASSIFY; //We hit a '<!...'. We must test this here if we want comments intermixed w/PCDATA.
- else if(*s) goto LOC_CLASSIFY;
- else return s;
- }
- }
- //Fall-through A.
- else if(chartype_close(*s)) //'.../'
- {
- ++s;
- if(chartype_leave(*s)) //'.../>'
- {
- POPNODE(); //Pop.
- ++s;
- continue;
- }
- }
- }
- //Fall-through B.
- else if(chartype_close(*s)) //'.../'
- {
- SCANFOR(chartype_leave(*s)); //'.../>'
- POPNODE(); //Pop.
- continue;
- }
- }
- }
- return s;
+ mark = s; //Save this offset while searching for a terminator.
+ SKIPWS(); //Eat whitespace if no genuine PCDATA here.
+ if(chartype_enter(*s)) //We hit a '<...', with only whitespace, so don't bother storing anything.
+ {
+ if(chartype_close(*(s+1))) //'</...'
+ {
+ SCANFOR(chartype_leave(*s)); //Scan for '>', stepping over any end-tag name.
+ POPNODE(); //Pop.
+ continue; //Continue scanning.
+ }
+ else goto LOC_SEARCH; //Expect a new element enter, so go scan for it.
+ }
+ s = mark; //We hit something other than whitespace; restore the original offset.
+ PUSHNODE(node_pcdata); //Append a new node on the tree.
+ cursor->value = s; //Save the offset.
+ SCANFOR(chartype_enter(*s)); //'...<'
+#ifdef PUGOPT_NONSEG
+ ENDSEGDAT();
+#else
+ ENDSEG(); //Save char in 'ch', terminate & step over.
+#endif
+ if(OPTSET(parse_trim_pcdata)) //Trim whitespace.
+ {
+#ifdef PUGOPT_NONSEG
+ strwtrim(&cursor->value,cursor->value_size);
+#else
+ if(OPTSET(parse_wnorm)) strwnorm(&cursor->value);
+ else strwtrim(&cursor->value);
+#endif
+ }
+ POPNODE(); //Pop since this is a standalone.
+ if(chartype_enter(ch)) //Did we hit a '<...'?
+ {
+ if(chartype_close(*s)) //'</...'
+ {
+ SCANFOR(chartype_leave(*s)); //'...>'
+ POPNODE(); //Pop.
+ goto LOC_LEAVE;
+ }
+ else if(chartype_special(*s)) goto LOC_CLASSIFY; //We hit a '<!...'. We must test this here if we want comments intermixed w/PCDATA.
+ else if(*s) goto LOC_CLASSIFY;
+ else return s;
+ }
+ }
+ //Fall-through A.
+ else if(chartype_close(*s)) //'.../'
+ {
+ ++s;
+ if(chartype_leave(*s)) //'.../>'
+ {
+ POPNODE(); //Pop.
+ ++s;
+ continue;
+ }
+ }
+ }
+ //Fall-through B.
+ else if(chartype_close(*s)) //'.../'
+ {
+ SCANFOR(chartype_leave(*s)); //'.../>'
+ POPNODE(); //Pop.
+ continue;
+ }
+ }
+ }
+ return s;
 }
 
 
@@ -1402,23 +1402,23 @@
 //<remarks>Memory is allocated at '*buffer'. Free with 'free'.</remarks>
 inline static bool load_file(const TCHAR* path,TCHAR** buffer,unsigned long* size,unsigned long tempsize = 4096)
 {
- if(!path || !buffer || !size) return false;
- *size = 0;
- *buffer = 0;
- HANDLE file_handle = CreateFile(path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
- if(file_handle == INVALID_HANDLE_VALUE) return false;
- TCHAR* temp = (TCHAR*) malloc(sizeof(TCHAR)*tempsize);
- if(!temp) return false;
- unsigned long read_bytes = 0;
- ZeroMemory(temp,sizeof(TCHAR)*tempsize);
- while(ReadFile(file_handle,(void*)temp,tempsize-1,&read_bytes,0) && read_bytes && strcatgrow(buffer,temp))
- {
- *size += read_bytes;
- ZeroMemory(temp,sizeof(TCHAR)*tempsize);
- }
- CloseHandle(file_handle);
- free(temp);
- return (*size) ? true : false;
+ if(!path || !buffer || !size) return false;
+ *size = 0;
+ *buffer = 0;
+ HANDLE file_handle = CreateFile(path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
+ if(file_handle == INVALID_HANDLE_VALUE) return false;
+ TCHAR* temp = (TCHAR*) malloc(sizeof(TCHAR)*tempsize);
+ if(!temp) return false;
+ unsigned long read_bytes = 0;
+ ZeroMemory(temp,sizeof(TCHAR)*tempsize);
+ while(ReadFile(file_handle,(void*)temp,tempsize-1,&read_bytes,0) && read_bytes && strcatgrow(buffer,temp))
+ {
+ *size += read_bytes;
+ ZeroMemory(temp,sizeof(TCHAR)*tempsize);
+ }
+ CloseHandle(file_handle);
+ free(temp);
+ return (*size) ? true : false;
 }
 */
 
@@ -1428,67 +1428,67 @@
 {
 //Internal Data Members
 protected:
- unsigned int _size; //Count items.
- unsigned int _room; //Available space.
- void** _data; //The list.
- unsigned int _grow; //Grow by increment.
-public:
- //<summary>Default constructor.</summary>
- //<param name="grow">Array growth increment.</param>
- pointer_array(unsigned int grow = 4):
- _size(0),
- _room(0),
- _data(NULL),
- _grow(grow)
- {
- _data = (void**)malloc(sizeof(void*)*_grow);
- _room = (_data) ? _grow : 0;
- }
- ~pointer_array(){ if(_data) free(_data); }
-public:
- bool empty(){ return (_size == 0); } //True if there is no data in the array.
- void remove_all(){ _size = 0; } //Remove all data elements from the array.
- void clear() //Free any allocated memory.
- {
- if(_data)
- {
- _data = (void**)realloc(_data,sizeof(void*)*_grow); //Reallocate to first growth increment.
- _room = _grow; //Mark it as such.
- _size = 0; //Mark array as empty.
- }
- }
- virtual void*& operator[](unsigned int i) //Access element at subscript, or dummy value if overflow.
- {
- static void* dummy = 0;
- if(i < _size) return _data[i]; else return dummy;
- }
- unsigned int size(){ return _size; } //Count data elements in the array.
- virtual void* at(unsigned int i){ if(i < _size) return _data[i]; else return NULL; } //Access element at subscript, or NULL if overflow.
- long push_back(void* element) //Append a new element to the array.
- {
- if(_data) //Fail if no array.
- {
- if(_size < _room) //There is enough allocated space.
- {
- _data[_size] = element; //Set it.
- _size++; //Increment our count of elements.
- return _size-1; //Return the element's subscript.
- }
- else //Not enough room.
- {
- void** temp = (void**)realloc(_data,sizeof(void*)*(_size+_grow)); //Grow the array.
- if(temp) //Reallocation succeeded.
- {
- _room += _grow; //Increment available space.
- _data = temp; //Assign reallocated value to array pointer.
- _data[_size] = element; //Set the element to be added.
- _size++; //Increment our count of elements.
- return _size-1; //Return the element's subscript.
- }
- }
- }
- return -1; //Something failed, so return a bad subscript.
- }
+ unsigned int _size; //Count items.
+ unsigned int _room; //Available space.
+ void** _data; //The list.
+ unsigned int _grow; //Grow by increment.
+public:
+ //<summary>Default constructor.</summary>
+ //<param name="grow">Array growth increment.</param>
+ pointer_array(unsigned int grow = 4):
+ _size(0),
+ _room(0),
+ _data(NULL),
+ _grow(grow)
+ {
+ _data = (void**)malloc(sizeof(void*)*_grow);
+ _room = (_data) ? _grow : 0;
+ }
+ ~pointer_array(){ if(_data) free(_data); }
+public:
+ bool empty(){ return (_size == 0); } //True if there is no data in the array.
+ void remove_all(){ _size = 0; } //Remove all data elements from the array.
+ void clear() //Free any allocated memory.
+ {
+ if(_data)
+ {
+ _data = (void**)realloc(_data,sizeof(void*)*_grow); //Reallocate to first growth increment.
+ _room = _grow; //Mark it as such.
+ _size = 0; //Mark array as empty.
+ }
+ }
+ virtual void*& operator[](unsigned int i) //Access element at subscript, or dummy value if overflow.
+ {
+ static void* dummy = 0;
+ if(i < _size) return _data[i]; else return dummy;
+ }
+ unsigned int size(){ return _size; } //Count data elements in the array.
+ virtual void* at(unsigned int i){ if(i < _size) return _data[i]; else return NULL; } //Access element at subscript, or NULL if overflow.
+ long push_back(void* element) //Append a new element to the array.
+ {
+ if(_data) //Fail if no array.
+ {
+ if(_size < _room) //There is enough allocated space.
+ {
+ _data[_size] = element; //Set it.
+ _size++; //Increment our count of elements.
+ return _size-1; //Return the element's subscript.
+ }
+ else //Not enough room.
+ {
+ void** temp = (void**)realloc(_data,sizeof(void*)*(_size+_grow)); //Grow the array.
+ if(temp) //Reallocation succeeded.
+ {
+ _room += _grow; //Increment available space.
+ _data = temp; //Assign reallocated value to array pointer.
+ _data[_size] = element; //Set the element to be added.
+ _size++; //Increment our count of elements.
+ return _size-1; //Return the element's subscript.
+ }
+ }
+ }
+ return -1; //Something failed, so return a bad subscript.
+ }
 };
 
 
@@ -1498,327 +1498,327 @@
 {
 //Internal Data Members
 protected:
- TCHAR _inch; //The indent character.
- TCHAR* _stac; //The aggregate indent string (stack).
- int _size; //Current depth (avoids using '_tcslen' on push/pop).
+ TCHAR _inch; //The indent character.
+ TCHAR* _stac; //The aggregate indent string (stack).
+ int _size; //Current depth (avoids using '_tcslen' on push/pop).
 //Construction/Destruction
 public:
- //<summary>Default constructor.</summary>
- //<param name="c">Indent character.</param>
- indent_stack(TCHAR c = _T('\t')):
- _inch(c),
- _stac(0) ,
- _size(0)
- {
- _stac = (TCHAR*)malloc(sizeof(TCHAR)); //Allocate.
- *_stac = 0; //Zero-terminate.
- }
- //Destructor.
- virtual ~indent_stack(){ if(_stac) free(_stac); }
+ //<summary>Default constructor.</summary>
+ //<param name="c">Indent character.</param>
+ indent_stack(TCHAR c = _T('\t')):
+ _inch(c),
+ _stac(0) ,
+ _size(0)
+ {
+ _stac = (TCHAR*)malloc(sizeof(TCHAR)); //Allocate.
+ *_stac = 0; //Zero-terminate.
+ }
+ //Destructor.
+ virtual ~indent_stack(){ if(_stac) free(_stac); }
 //Stack Operators
 public:
- //<summary>Grow indent string by one indent character.</summary>
- //<remarks>Reallocates the indent string.</remarks>
- void push()
- {
- if(_inch && _stac)
- {
- _size++;
- _stac = (TCHAR*)realloc(_stac,sizeof(TCHAR)*(_size+1));
- _stac[_size-1] = _inch;
- _stac[_size] = 0;
- }
- }
- //<summary>Shrink the indent string by one indent character.</summary>
- void pop()
- {
- if(_inch && _stac && _size > 0)
- {
- _size--;
- _stac = (TCHAR*)realloc(_stac,sizeof(TCHAR)*(_size+1));
- _stac[_size] = 0;
- }
- }
- //<summary>Accesses the indent depth.</summary>
- //<returns>The current indent string, or "" if empty.</returns>
- const TCHAR* depth(){ return (_inch && _stac) ? _stac : _T(""); }
+ //<summary>Grow indent string by one indent character.</summary>
+ //<remarks>Reallocates the indent string.</remarks>
+ void push()
+ {
+ if(_inch && _stac)
+ {
+ _size++;
+ _stac = (TCHAR*)realloc(_stac,sizeof(TCHAR)*(_size+1));
+ _stac[_size-1] = _inch;
+ _stac[_size] = 0;
+ }
+ }
+ //<summary>Shrink the indent string by one indent character.</summary>
+ void pop()
+ {
+ if(_inch && _stac && _size > 0)
+ {
+ _size--;
+ _stac = (TCHAR*)realloc(_stac,sizeof(TCHAR)*(_size+1));
+ _stac[_size] = 0;
+ }
+ }
+ //<summary>Accesses the indent depth.</summary>
+ //<returns>The current indent string, or "" if empty.</returns>
+ const TCHAR* depth(){ return (_inch && _stac) ? _stac : _T(""); }
 };
 
 
 //<summary>
-// Stream output. Recursively writes the given xml_node_struct structure to
-// the given stream. NOTE: Use this recursive implementation for debug purposes
-// only, since a large tree may cause a stack overflow.
+// Stream output. Recursively writes the given xml_node_struct structure to
+// the given stream. NOTE: Use this recursive implementation for debug purposes
+// only, since a large tree may cause a stack overflow.
 //</summary>
 //<param name="os">Reference to output stream.</param>
 //<param name="indent">Reference to indentation stack.</param>
 //<param name="node">Pointer to the node.</param>
 //<param name="breaks">Use linebreaks?</param>
 //<returns>
-// String data is written to stream. Indent stack may be altered.
-// If you want to make this prettier, and to avoid propagating whitespace,
-// you will have to trim excess whitespace from the PCDATA sections.
+// String data is written to stream. Indent stack may be altered.
+// If you want to make this prettier, and to avoid propagating whitespace,
+// you will have to trim excess whitespace from the PCDATA sections.
 //</returns>
 inline static void outer_xml(std::basic_ostream<TCHAR,std::char_traits<TCHAR> > & os,indent_stack& indent,xml_node_struct* node,bool breaks = true)
 {
- if(node && os.good()) //There is a node and ostream is OK.
- {
- register unsigned int n, i;
- os << indent.depth();
- switch(node->type)
- {
- case node_dtd_attlist:
- if(node->name)
- {
-#ifdef PUGOPT_NONSEG
- os << _T("<!ATTLIST ");
- os.write( node->name, node->name_size );
-#else
- os << _T("<!ATTLIST ") << node->name;
-#endif
- if(node->value)
-#ifdef PUGOPT_NONSEG
- {
- os << _T(" ");
- os.write( node->value, node->value_size );
- }
-#else
- os << _T(" ") << node->value;
-#endif
-
- os << _T(">");
- }
- break;
- case node_dtd_element:
- if(node->name)
- {
-#ifdef PUGOPT_NONSEG
- os << _T("<!ELEMENT ");
- os.write( node->name, node->name_size );
- if(node->value)
- {
- os << _T(" ");
- os.write( node->value, node->value_size );
- }
-#else
- os << _T("<!ELEMENT ") << node->name;
- if(node->value) os << _T(" ") << node->value;
-#endif
- os << _T(">");
- }
- break;
- case node_dtd_entity:
- if(node->name)
- {
-#ifdef PUGOPT_NONSEG
- os << _T("<!ENTITY ");
- os.write( node->name, node->name_size );
- if(node->value)
- {
- os << _T(" ");
- os.write( node->value, node->value_size );
- }
-#else
- os << _T("<!ENTITY ") << node->name;
- if(node->value) os << _T(" ") << node->value;
-#endif
- os << _T(">");
- }
- break;
- case node_dtd_notation:
- if(node->name)
- {
-#ifdef PUGOPT_NONSEG
- os << _T("<!NOTATION ");
- os.write( node->name, node->name_size );
- if(node->value)
- {
- os << _T(" ");
- os.write( node->value, node->value_size );
- }
-#else
- os << _T("<!NOTATION ") << node->name;
- if(node->value) os << _T(" ") << node->value;
-#endif
- os << _T(">");
- }
- break;
- case node_doctype:
- os << _T("<!DOCTYPE");
- n = node->attributes;
- for(i=0; i<n; ++i)
- {
- os << _T(" ");
- if(node->attribute[i]->name)
-#ifdef PUGOPT_NONSEG
- os.write( node->attribute[i]->name, node->attribute[i]->name_size );
-#else
- os << node->attribute[i]->name;
-#endif
- else if(node->attribute[i]->value)
-#ifdef PUGOPT_NONSEG
- {
- os << _T("\"");
- os.write( node->attribute[i]->value, node->attribute[i]->value_size );
- os << _T("\"");
- }
-#else
- os << _T("\"") << node->attribute[i]->value << _T("\"");
-#endif
- }
- if(node->children)
- {
- if(breaks) os << std::endl;
- else os << _T(" ");
- os << _T("[");
- if(breaks) os << std::endl;
- else os << _T(" ");
- n = node->children;
- indent.push(); //Push the indent stack.
- for(i=0; i<n; ++i)
- {
- if
- (
- node->child[i] && //There is a child at i.
- (
- node->child[i]->type == node_dtd_attlist || //Skip all other types.
- node->child[i]->type == node_dtd_element ||
- node->child[i]->type == node_dtd_entity ||
- node->child[i]->type == node_dtd_notation
- )
- )
- outer_xml(os,indent,node->child[i],breaks);
- }
- indent.pop(); //Pop the indent stack.
- os << _T("]");
- }
- else if(node->value)
-#ifdef PUGOPT_NONSEG
- {
- os << _T(" [");
- os.write(node->value,node->value_size);
- os << _T("]");
- }
-#else
- os << _T(" [") << node->value << _T("]");
-#endif
- os << _T(">");
- break;
- case node_pcdata:
-#ifdef PUGOPT_NONSEG
- if(node->value) os.write(node->value,node->value_size);
-#else
- if(node->value) os << node->value;
-#endif
- break;
- case node_cdata:
-#ifdef PUGOPT_NONSEG
- if(node->value)
- {
- os << _T("<![CDATA[");
- os.write(node->value,node->value_size);
- os << _T("]]>");
- }
-#else
- if(node->value) os << _T("<![CDATA[") << node->value << _T("]]>");
-#endif
- break;
- case node_include:
-#ifdef PUGOPT_NONSEG
- if(node->value)
- {
- os << _T("<![INCLUDE[");
- os.write(node->value, node->value_size);
- os << _T("]]>");
- }
-#else
- if(node->value) os << _T("<![INCLUDE[") << node->value << _T("]]>");
-#endif
- break;
- case node_comment:
-#ifdef PUGOPT_NONSEG
- if(node->value)
- {
- os << _T("<!--");
- os.write(node->value, node->value_size);
- os << _T("-->");
- }
-#else
- if(node->value) os << _T("<!--") << node->value << _T("-->");
-#endif
- break;
- case node_element:
- case node_pi:
- os << _T("<");
- if(node->type==node_pi) os << _T("?");
- if(node->name)
-#ifdef PUGOPT_NONSEG
- os.write(node->name,node->name_size);
-#else
- os << node->name;
-#endif
- else os << _T("anonymous");
- n = node->attributes;
- for(i=0; i<n; ++i)
- {
- if(node->attribute[i] && node->attribute[i]->name)
- {
-#ifdef PUGOPT_NONSEG
- os << _T(" ");
- os.write(node->attribute[i]->name,node->attribute[i]->name_size);
- if(node->attribute[i]->value)
- {
- os << _T("=\"");
- os.write(node->attribute[i]->value,node->attribute[i]->value_size);
- os << _T("\"");
- }
-#else
- os << _T(" ") << node->attribute[i]->name;
- if(node->attribute[i]->value) os << _T("=\"") << node->attribute[i]->value << _T("\"");
-#endif
- }
- }
- n = node->children;
- if(n && node->type == node_element)
- {
- os << _T(">");
- if(n == 1 && node->child[0]->type == node_pcdata)
- {
- if(node->child[0] && node->child[0]->value)
-#ifdef PUGOPT_NONSEG
- os.write(node->child[0]->value,node->child[0]->value_size);
-#else
- os << node->child[0]->value;
-#endif
- }
- else
- {
- if(breaks) os << std::endl;
- indent.push();
- for(i=0; i<n; ++i) pug::outer_xml(os,indent,node->child[i],breaks);
- indent.pop();
- os << indent.depth();
- }
- os << _T("</");
-#ifdef PUGOPT_NONSEG
- if(node->name)
- os.write(node->name, node->name_size);
-#else
- if(node->name) os << node->name;
-#endif
- os << _T(">");
- }
- else
- {
- if(node->type==node_pi) os << _T("?>");
- else os << _T("/>");
- }
- break;
- default: break;
- }
- if(breaks) os << std::endl;
- os.flush();
- }
+ if(node && os.good()) //There is a node and ostream is OK.
+ {
+ register unsigned int n, i;
+ os << indent.depth();
+ switch(node->type)
+ {
+ case node_dtd_attlist:
+ if(node->name)
+ {
+#ifdef PUGOPT_NONSEG
+ os << _T("<!ATTLIST ");
+ os.write( node->name, node->name_size );
+#else
+ os << _T("<!ATTLIST ") << node->name;
+#endif
+ if(node->value)
+#ifdef PUGOPT_NONSEG
+ {
+ os << _T(" ");
+ os.write( node->value, node->value_size );
+ }
+#else
+ os << _T(" ") << node->value;
+#endif
+
+ os << _T(">");
+ }
+ break;
+ case node_dtd_element:
+ if(node->name)
+ {
+#ifdef PUGOPT_NONSEG
+ os << _T("<!ELEMENT ");
+ os.write( node->name, node->name_size );
+ if(node->value)
+ {
+ os << _T(" ");
+ os.write( node->value, node->value_size );
+ }
+#else
+ os << _T("<!ELEMENT ") << node->name;
+ if(node->value) os << _T(" ") << node->value;
+#endif
+ os << _T(">");
+ }
+ break;
+ case node_dtd_entity:
+ if(node->name)
+ {
+#ifdef PUGOPT_NONSEG
+ os << _T("<!ENTITY ");
+ os.write( node->name, node->name_size );
+ if(node->value)
+ {
+ os << _T(" ");
+ os.write( node->value, node->value_size );
+ }
+#else
+ os << _T("<!ENTITY ") << node->name;
+ if(node->value) os << _T(" ") << node->value;
+#endif
+ os << _T(">");
+ }
+ break;
+ case node_dtd_notation:
+ if(node->name)
+ {
+#ifdef PUGOPT_NONSEG
+ os << _T("<!NOTATION ");
+ os.write( node->name, node->name_size );
+ if(node->value)
+ {
+ os << _T(" ");
+ os.write( node->value, node->value_size );
+ }
+#else
+ os << _T("<!NOTATION ") << node->name;
+ if(node->value) os << _T(" ") << node->value;
+#endif
+ os << _T(">");
+ }
+ break;
+ case node_doctype:
+ os << _T("<!DOCTYPE");
+ n = node->attributes;
+ for(i=0; i<n; ++i)
+ {
+ os << _T(" ");
+ if(node->attribute[i]->name)
+#ifdef PUGOPT_NONSEG
+ os.write( node->attribute[i]->name, node->attribute[i]->name_size );
+#else
+ os << node->attribute[i]->name;
+#endif
+ else if(node->attribute[i]->value)
+#ifdef PUGOPT_NONSEG
+ {
+ os << _T("\"");
+ os.write( node->attribute[i]->value, node->attribute[i]->value_size );
+ os << _T("\"");
+ }
+#else
+ os << _T("\"") << node->attribute[i]->value << _T("\"");
+#endif
+ }
+ if(node->children)
+ {
+ if(breaks) os << std::endl;
+ else os << _T(" ");
+ os << _T("[");
+ if(breaks) os << std::endl;
+ else os << _T(" ");
+ n = node->children;
+ indent.push(); //Push the indent stack.
+ for(i=0; i<n; ++i)
+ {
+ if
+ (
+ node->child[i] && //There is a child at i.
+ (
+ node->child[i]->type == node_dtd_attlist || //Skip all other types.
+ node->child[i]->type == node_dtd_element ||
+ node->child[i]->type == node_dtd_entity ||
+ node->child[i]->type == node_dtd_notation
+ )
+ )
+ outer_xml(os,indent,node->child[i],breaks);
+ }
+ indent.pop(); //Pop the indent stack.
+ os << _T("]");
+ }
+ else if(node->value)
+#ifdef PUGOPT_NONSEG
+ {
+ os << _T(" [");
+ os.write(node->value,node->value_size);
+ os << _T("]");
+ }
+#else
+ os << _T(" [") << node->value << _T("]");
+#endif
+ os << _T(">");
+ break;
+ case node_pcdata:
+#ifdef PUGOPT_NONSEG
+ if(node->value) os.write(node->value,node->value_size);
+#else
+ if(node->value) os << node->value;
+#endif
+ break;
+ case node_cdata:
+#ifdef PUGOPT_NONSEG
+ if(node->value)
+ {
+ os << _T("<![CDATA[");
+ os.write(node->value,node->value_size);
+ os << _T("]]>");
+ }
+#else
+ if(node->value) os << _T("<![CDATA[") << node->value << _T("]]>");
+#endif
+ break;
+ case node_include:
+#ifdef PUGOPT_NONSEG
+ if(node->value)
+ {
+ os << _T("<![INCLUDE[");
+ os.write(node->value, node->value_size);
+ os << _T("]]>");
+ }
+#else
+ if(node->value) os << _T("<![INCLUDE[") << node->value << _T("]]>");
+#endif
+ break;
+ case node_comment:
+#ifdef PUGOPT_NONSEG
+ if(node->value)
+ {
+ os << _T("<!--");
+ os.write(node->value, node->value_size);
+ os << _T("-->");
+ }
+#else
+ if(node->value) os << _T("<!--") << node->value << _T("-->");
+#endif
+ break;
+ case node_element:
+ case node_pi:
+ os << _T("<");
+ if(node->type==node_pi) os << _T("?");
+ if(node->name)
+#ifdef PUGOPT_NONSEG
+ os.write(node->name,node->name_size);
+#else
+ os << node->name;
+#endif
+ else os << _T("anonymous");
+ n = node->attributes;
+ for(i=0; i<n; ++i)
+ {
+ if(node->attribute[i] && node->attribute[i]->name)
+ {
+#ifdef PUGOPT_NONSEG
+ os << _T(" ");
+ os.write(node->attribute[i]->name,node->attribute[i]->name_size);
+ if(node->attribute[i]->value)
+ {
+ os << _T("=\"");
+ os.write(node->attribute[i]->value,node->attribute[i]->value_size);
+ os << _T("\"");
+ }
+#else
+ os << _T(" ") << node->attribute[i]->name;
+ if(node->attribute[i]->value) os << _T("=\"") << node->attribute[i]->value << _T("\"");
+#endif
+ }
+ }
+ n = node->children;
+ if(n && node->type == node_element)
+ {
+ os << _T(">");
+ if(n == 1 && node->child[0]->type == node_pcdata)
+ {
+ if(node->child[0] && node->child[0]->value)
+#ifdef PUGOPT_NONSEG
+ os.write(node->child[0]->value,node->child[0]->value_size);
+#else
+ os << node->child[0]->value;
+#endif
+ }
+ else
+ {
+ if(breaks) os << std::endl;
+ indent.push();
+ for(i=0; i<n; ++i) pug::outer_xml(os,indent,node->child[i],breaks);
+ indent.pop();
+ os << indent.depth();
+ }
+ os << _T("</");
+#ifdef PUGOPT_NONSEG
+ if(node->name)
+ os.write(node->name, node->name_size);
+#else
+ if(node->name) os << node->name;
+#endif
+ os << _T(">");
+ }
+ else
+ {
+ if(node->type==node_pi) os << _T("?>");
+ else os << _T("/>");
+ }
+ break;
+ default: break;
+ }
+ if(breaks) os << std::endl;
+ os.flush();
+ }
 }
 
 
@@ -1828,31 +1828,31 @@
 class xml_iterator : public std::_Ranit<_Ty,_Diff,_Pointer,_Reference>
 {
 protected:
- xml_node_struct* _vref; //A pointer to the node over which to iterate.
- long _sscr; //Current subscript of element.
+ xml_node_struct* _vref; //A pointer to the node over which to iterate.
+ long _sscr; //Current subscript of element.
 public:
- xml_iterator() : _vref(0), _sscr(-1) {} //Default constructor.
- xml_iterator(xml_node_struct* vref,long sscr = 0) : _vref(vref), _sscr(sscr){ } //Initializing constructor.
- xml_iterator(const xml_iterator& r) : _vref(r._vref), _sscr(r._sscr){ } //Copy constructor.
- virtual ~xml_iterator(){} //Destructor.
-public:
- virtual bool good() = 0; //Internal validity of '_vref'.
- virtual bool oob() = 0; //Out of bounds check for '_sscr' with respect to '_vref'. Returns true if '_sscr' is O.O.B.
-public:
- virtual long subscript(){ return _sscr; } //Get subscript value;
- virtual void subscript(long new_subscript){ _sscr = new_subscript; } //Set subscript value;
-public:
- virtual xml_iterator& operator=(const xml_iterator& rhs){ _vref = rhs._vref; _sscr = rhs._sscr; return *this; } //Assignment.
- virtual bool operator==(const xml_iterator& rhs){ return (_sscr == rhs._sscr); } //True if this is equal to RHS.
- virtual bool operator!=(const xml_iterator& rhs){ return (_sscr != rhs._sscr); } //True if this is not equal to RHS.
- virtual bool operator<(const xml_iterator& rhs){ return (_sscr < rhs._sscr); } //True if this subscript is less than RHS.
- virtual bool operator>(const xml_iterator& rhs){ return (_sscr > rhs._sscr); } //True if this subscript is greater than RHS.
- virtual bool operator<=(const xml_iterator& rhs){ return (_sscr <= rhs._sscr); } //True if this subscript is less than or equal to RHS.
- virtual bool operator>=(const xml_iterator& rhs){ return (_sscr >= rhs._sscr); } //True if this subscript is greater than or equal to RHS.
- virtual xml_iterator& operator++(){ _sscr++; return *this; } //Increment the iterator (subscript).
- virtual xml_iterator& operator--(){ _sscr--; return *this; } //Decrement the iterator (subscript).
- virtual _Ty& operator*() = 0; //Dereference operator.
- virtual _Ty* operator->() = 0;
+ xml_iterator() : _vref(0), _sscr(-1) {} //Default constructor.
+ xml_iterator(xml_node_struct* vref,long sscr = 0) : _vref(vref), _sscr(sscr){ } //Initializing constructor.
+ xml_iterator(const xml_iterator& r) : _vref(r._vref), _sscr(r._sscr){ } //Copy constructor.
+ virtual ~xml_iterator(){} //Destructor.
+public:
+ virtual bool good() = 0; //Internal validity of '_vref'.
+ virtual bool oob() = 0; //Out of bounds check for '_sscr' with respect to '_vref'. Returns true if '_sscr' is O.O.B.
+public:
+ virtual long subscript(){ return _sscr; } //Get subscript value;
+ virtual void subscript(long new_subscript){ _sscr = new_subscript; } //Set subscript value;
+public:
+ virtual xml_iterator& operator=(const xml_iterator& rhs){ _vref = rhs._vref; _sscr = rhs._sscr; return *this; } //Assignment.
+ virtual bool operator==(const xml_iterator& rhs){ return (_sscr == rhs._sscr); } //True if this is equal to RHS.
+ virtual bool operator!=(const xml_iterator& rhs){ return (_sscr != rhs._sscr); } //True if this is not equal to RHS.
+ virtual bool operator<(const xml_iterator& rhs){ return (_sscr < rhs._sscr); } //True if this subscript is less than RHS.
+ virtual bool operator>(const xml_iterator& rhs){ return (_sscr > rhs._sscr); } //True if this subscript is greater than RHS.
+ virtual bool operator<=(const xml_iterator& rhs){ return (_sscr <= rhs._sscr); } //True if this subscript is less than or equal to RHS.
+ virtual bool operator>=(const xml_iterator& rhs){ return (_sscr >= rhs._sscr); } //True if this subscript is greater than or equal to RHS.
+ virtual xml_iterator& operator++(){ _sscr++; return *this; } //Increment the iterator (subscript).
+ virtual xml_iterator& operator--(){ _sscr--; return *this; } //Decrement the iterator (subscript).
+ virtual _Ty& operator*() = 0; //Dereference operator.
+ virtual _Ty* operator->() = 0;
 };
 
 class xml_node; //Forward decl.
@@ -1862,260 +1862,260 @@
 class xml_tree_walker
 {
 protected:
- long _deep; //Current node depth.
+ long _deep; //Current node depth.
 public:
- xml_tree_walker() : _deep(0) {} //Default constructor.
- virtual ~xml_tree_walker(){} //Destructor.
+ xml_tree_walker() : _deep(0) {} //Default constructor.
+ virtual ~xml_tree_walker(){} //Destructor.
 public:
- virtual void push(){ ++_deep; } //Increment node depth.
- virtual void pop(){ --_deep; } //Decrement node depth.
- virtual long depth(){ return (_deep > 0) ? _deep : 0; } //Access node depth.
-public:
- //<summary>Callback when traverse on a given root node begins.</summary>
- //<returns>Returning false will abort the traversal.</returns>
- //<remarks>Override this to implement your own custom behavior.</remarks>
- virtual bool begin(xml_node&){ return true; }
- //<summary>Callback for each node that is hit on traverse.</summary>
- //<returns>Returning false will abort the traversal.</returns>
- virtual bool for_each(xml_node&) = 0;
- //<summary>Callback when traverse on a given root node ends.</summary>
- //<returns>Returning false will abort the traversal.</returns>
- //<remarks>Override this to implement your own custom behavior.</remarks>
- virtual bool end(xml_node&){ return true; }
+ virtual void push(){ ++_deep; } //Increment node depth.
+ virtual void pop(){ --_deep; } //Decrement node depth.
+ virtual long depth(){ return (_deep > 0) ? _deep : 0; } //Access node depth.
+public:
+ //<summary>Callback when traverse on a given root node begins.</summary>
+ //<returns>Returning false will abort the traversal.</returns>
+ //<remarks>Override this to implement your own custom behavior.</remarks>
+ virtual bool begin(xml_node&){ return true; }
+ //<summary>Callback for each node that is hit on traverse.</summary>
+ //<returns>Returning false will abort the traversal.</returns>
+ virtual bool for_each(xml_node&) = 0;
+ //<summary>Callback when traverse on a given root node ends.</summary>
+ //<returns>Returning false will abort the traversal.</returns>
+ //<remarks>Override this to implement your own custom behavior.</remarks>
+ virtual bool end(xml_node&){ return true; }
 };
 
 
 //<summary>Provides a light-weight wrapper for manipulating xml_attribute_struct structures.</summary>
 //<remarks>
-// Note: xml_attribute does not create any memory for the attribute it wraps;
-// it only wraps a pointer to an existing xml_attribute_struct.
+// Note: xml_attribute does not create any memory for the attribute it wraps;
+// it only wraps a pointer to an existing xml_attribute_struct.
 //</remarks>
 class xml_attribute
 {
 //Internal Data Members
 protected:
- xml_attribute_struct* _attr; //The internal attribute pointer.
+ xml_attribute_struct* _attr; //The internal attribute pointer.
 //Construction/Destruction
 public:
- xml_attribute() : _attr(NULL) {} //Default constructor.
- xml_attribute(xml_attribute_struct* attr) : _attr(attr) {} //Initializing constructor.
- xml_attribute(const xml_attribute& r) : _attr(r._attr) {} //Copy constructor.
- virtual ~xml_attribute(){} //Destructor.
+ xml_attribute() : _attr(NULL) {} //Default constructor.
+ xml_attribute(xml_attribute_struct* attr) : _attr(attr) {} //Initializing constructor.
+ xml_attribute(const xml_attribute& r) : _attr(r._attr) {} //Copy constructor.
+ virtual ~xml_attribute(){} //Destructor.
 //Operators
 public:
- void attach(xml_attribute_struct* v){ _attr = v; }
- xml_attribute& operator=(const xml_attribute& r){ _attr = r._attr; return *this; } //Assign internal pointer.
- bool operator==(const xml_attribute& r){ return (_attr == r._attr); } //Compare internal pointer.
- bool operator!=(const xml_attribute& r){ return (_attr != r._attr); }
- operator xml_attribute_struct*(){ return _attr; }
- //<summary>Cast attribute value as std::string. If not found, return empty.</summary>
- //<returns>The std::string attribute value, or empty.</returns>
- //<remarks>Note: Modifying this will not change the value, e.g. read only.</remarks>
- operator std::string()
- {
- std::string temp;
- if(!empty() && has_value())
- {
-#ifdef PUGOPT_NONSEG
- temp.append(_attr->value,_attr->value_size);
-#else
- temp = _attr->value;
-#endif
- }
- return temp;
- }
- //<summary>Cast attribute value as integral character string. If not found, return NULL.</summary>
- //<returns>Integral character string attribute value, or NULL.</returns>
- //<remarks>Warning: Modifying this may corrupt portions of the document tree.</remarks>
- operator const TCHAR*()
- {
- if(empty() || !has_value()) return NULL;
- return _attr->value;
- }
- //<summary>Cast attribute value as long. If not found, return 0.</summary>
- //<returns>Attribute value as long, or 0.</returns>
- //<remarks>Note: Modifying this will not change the value, e.g. read only.</remarks>
- operator long()
- {
- if(empty() || !has_value()) return 0;
-#ifdef PUGOPT_NONSEG
- TCHAR temp[PUGDEF_ATTR_VALU_SIZE];
- unsigned int valulen = sizeof(temp)-1;
- const unsigned int maxlen = valulen ? min(valulen,_attr->value_size) : _attr->value_size;
- _tcsncpy(temp,_attr->value,maxlen);
- temp[maxlen] = 0;
- return _tcstol(temp,NULL,10);
-#else
- return _tcstol(_attr->value,NULL,10);
-#endif
- }
- //<summary>Cast attribute value as double. If not found, return 0.0.</summary>
- //<returns>Attribute value as double, or 0.0.</returns>
- //<remarks>Note: Modifying this will not change the value, e.g. read only.</remarks>
- operator double()
- {
- if(empty() || !has_value()) return 0.0;
-#ifdef PUGOPT_NONSEG
- TCHAR temp[PUGDEF_ATTR_VALU_SIZE];
- unsigned int valulen = sizeof(temp)-1;
- const unsigned int maxlen = valulen ? min(valulen,_attr->value_size) : _attr->value_size;
- _tcsncpy(temp,_attr->value,maxlen);
- temp[maxlen] = 0;
- return _tcstod(temp,0);
-#else
- return _tcstod(_attr->value,0);
-#endif
- }
- //<summary>Cast attribute value as bool. If not found, return false.</summary>
- //<returns>Attribute value as bool, or false.</returns>
- //<remarks>Note: Modifying this will not change the value, e.g. read only.</remarks>
- operator bool()
- {
- if(empty() || !has_value()) return false;
- if(*(_attr->value))
- {
- return //Only look at first char:
- (
- *(_attr->value) == _T('1') || //1*
- *(_attr->value) == _T('t') || //t* (true)
- *(_attr->value) == _T('T') || //T* (True|true)
- *(_attr->value) == _T('y') || //y* (yes)
- *(_attr->value) == _T('Y') //Y* (Yes|YES)
- )
- ? true : false; //Return true if matches above, else false.
- }
- }
- //<summary>Set attribute to std::string.</summary>
- //<param name="rhs">Value std::string to set.</param>
- //<returns>Reference to xml_attribute.</returns>
- xml_attribute& operator=(const std::string& rhs){ value(rhs.c_str()); return *this; }
- //<summary>Set attribute to string.</summary>
- //<param name="rhs">Value string to set.</param>
- //<returns>Reference to xml_attribute.</returns>
- xml_attribute& operator=(const TCHAR* rhs){ if(rhs) value(rhs); return *this; }
- //<summary>Set attribute to long.</summary>
- //<param name="rhs">Value long to set.</param>
- //<returns>Reference to xml_attribute.</returns>
- xml_attribute& operator=(long rhs)
- {
- TCHAR temp[32] = {0};
- _stprintf(temp,_T("%ld"),rhs);
- value(temp);
- return *this;
- }
- //<summary>Set attribute to double.</summary>
- //<param name="rhs">Value double to set.</param>
- //<returns>Reference to xml_attribute.</returns>
- xml_attribute& operator=(double rhs)
- {
- TCHAR temp[32] = {0};
- _stprintf(temp,_T("%lf"),rhs);
- value(temp);
- return *this;
- }
- //<summary>Set attribute to bool.</summary>
- //<param name="rhs">Value bool to set.</param>
- //<returns>Reference to xml_attribute.</returns>
- xml_attribute& operator=(bool rhs)
- {
- value(rhs?_T("true"):_T("false"));
- return *this;
- }
- //<summary>Right-shift attribute value to std::string.</summary>
- //<param name="rhs">Reference to std::string to set.</param>
- //<returns>Reference to xml_attribute.</returns>
- xml_attribute& operator>>(std::string& rhs)
- {
-#ifdef PUGOPT_NONSEG
- rhs.clear();
- rhs.append(_attr->value,_attr->value_size);
-#else
- rhs = value();
-#endif
- return *this;
- }
- //<summary>Right-shift attribute value to long.</summary>
- //<param name="rhs">Reference to long to set.</param>
- //<returns>Reference to xml_attribute.</returns>
- xml_attribute& operator>>(long& rhs){ rhs = (long)*this; return *this; }
- //<summary>Right-shift attribute value to double.</summary>
- //<param name="rhs">Reference to double to set.</param>
- //<returns>Reference to xml_attribute.</returns>
- xml_attribute& operator>>(double& rhs){ rhs = (double)*this; return *this; }
- //<summary>Right-shift attribute value to bool.</summary>
- //<param name="rhs">Reference to bool to set.</param>
- //<returns>Reference to xml_attribute.</returns>
- xml_attribute& operator>>(bool& rhs){ rhs = (bool)*this; return *this; }
- //<summary>Left-shift attribute value to long.</summary>
- //<param name="lhs">Reference to long to set.</param>
- //<param name="rhs">Reference to xml_attribute to read.</param>
- //<returns>Reference to long.</returns>
- friend long& operator<<(long& lhs,xml_attribute& rhs){ lhs = (long)rhs; return lhs; }
- //<summary>Left-shift attribute value to double.</summary>
- //<param name="lhs">Reference to double to set.</param>
- //<param name="rhs">Reference to xml_attribute to read.</param>
- //<returns>Reference to double.</returns>
- friend double& operator<<(double& lhs,xml_attribute& rhs){ lhs = (double)rhs; return lhs; }
- //<summary>Left-shift attribute value to bool.</summary>
- //<param name="lhs">Reference to bool to set.</param>
- //<param name="rhs">Reference to xml_attribute to read.</param>
- //<returns>Reference to bool.</returns>
- friend bool& operator<<(bool& lhs,xml_attribute& rhs){ lhs = (bool)rhs; return lhs; }
- //<summary>Left-shift long to attribute value.</summary>
- //<param name="lhs">Reference to xml_attribute to set.</param>
- //<param name="rhs">Reference to long to read.</param>
- //<returns>Reference to xml_attribute.</returns>
- friend xml_attribute& operator<<(xml_attribute& lhs,const long rhs){ lhs = rhs; return lhs; }
- //<summary>Left-shift double to attribute value.</summary>
- //<param name="lhs">Reference to xml_attribute to set.</param>
- //<param name="rhs">Reference to double to read.</param>
- //<returns>Reference to xml_attribute.</returns>
- friend xml_attribute& operator<<(xml_attribute& lhs,const double& rhs){ lhs = rhs; return lhs; }
- //<summary>Left-shift bool to attribute value.</summary>
- //<param name="lhs">Reference to xml_attribute to set.</param>
- //<param name="rhs">Reference to bool to read.</param>
- //<returns>Reference to xml_attribute.</returns>
- friend xml_attribute& operator<<(xml_attribute& lhs,const bool& rhs){ lhs = rhs; return lhs; }
-public:
- bool empty(){ return (_attr == NULL); } //True if the internal xml_attribute_struct pointer is NULL.
- bool has_name(){ return (!empty() && _attr->name); } //True if the attribute has a name.
- bool has_value(){ return (!empty() && _attr->value); } //True if the attribute has a value.
-#ifdef PUGOPT_NONSEG
- bool has_name(const TCHAR* name) { return (name && !empty() && has_name() && _tcsncmp(_attr->name,name,_attr->name_size)==0); } //Is named 'name'.
- bool has_value(const TCHAR* value) { return (value && !empty() && has_value() && _tcsncmp(_attr->value,value,_attr->value_size)==0); } //Has value 'value'.
-#else
- bool has_name(const TCHAR* name) { return (name && !empty() && has_name() && _tcscmp(_attr->name,name)==0); } //Is named 'name'.
- bool has_value(const TCHAR* value) { return (value && !empty() && has_value() && _tcscmp(_attr->value,value)==0); } //Has value 'value'.
-#endif
-public:
- const TCHAR* name(){ return (!empty() && _attr->name) ? _attr->name : _T(""); } //Access the attribute name.
-#ifdef PUGOPT_NONSEG
- const unsigned int name_size(){ return (!empty()) ? _attr->name_size : 0; } //Access the attribute name length (for PUGOPT_NONSEG).
-#endif
- bool name(TCHAR* new_name) //Set the attribute name.
- {
- if(!empty() && new_name)
-#ifdef PUGOPT_NONSEG
- return strcpyinsitu(&_attr->name,new_name,&_attr->name_insitu,_attr->name_size);
-#else
- return strcpyinsitu(&_attr->name,new_name,&_attr->name_insitu);
-#endif
- return false;
- }
- const TCHAR* value(){ return (!empty()) ? _attr->value : _T(""); } //Access the attribute value.
-#ifdef PUGOPT_NONSEG
- const unsigned int value_size(){ return (!empty()) ? _attr->value_size : 0; } //Access the attribute name length (for PUGOPT_NONSEG).
-#endif
- bool value(const TCHAR* new_value) //Set the attribute value.
- {
- if(!empty() && new_value)
+ void attach(xml_attribute_struct* v){ _attr = v; }
+ xml_attribute& operator=(const xml_attribute& r){ _attr = r._attr; return *this; } //Assign internal pointer.
+ bool operator==(const xml_attribute& r){ return (_attr == r._attr); } //Compare internal pointer.
+ bool operator!=(const xml_attribute& r){ return (_attr != r._attr); }
+ operator xml_attribute_struct*(){ return _attr; }
+ //<summary>Cast attribute value as std::string. If not found, return empty.</summary>
+ //<returns>The std::string attribute value, or empty.</returns>
+ //<remarks>Note: Modifying this will not change the value, e.g. read only.</remarks>
+ operator std::string()
+ {
+ std::string temp;
+ if(!empty() && has_value())
+ {
+#ifdef PUGOPT_NONSEG
+ temp.append(_attr->value,_attr->value_size);
+#else
+ temp = _attr->value;
+#endif
+ }
+ return temp;
+ }
+ //<summary>Cast attribute value as integral character string. If not found, return NULL.</summary>
+ //<returns>Integral character string attribute value, or NULL.</returns>
+ //<remarks>Warning: Modifying this may corrupt portions of the document tree.</remarks>
+ operator const TCHAR*()
+ {
+ if(empty() || !has_value()) return NULL;
+ return _attr->value;
+ }
+ //<summary>Cast attribute value as long. If not found, return 0.</summary>
+ //<returns>Attribute value as long, or 0.</returns>
+ //<remarks>Note: Modifying this will not change the value, e.g. read only.</remarks>
+ operator long()
+ {
+ if(empty() || !has_value()) return 0;
+#ifdef PUGOPT_NONSEG
+ TCHAR temp[PUGDEF_ATTR_VALU_SIZE];
+ unsigned int valulen = sizeof(temp)-1;
+ const unsigned int maxlen = valulen ? (std::min)(valulen,_attr->value_size) : _attr->value_size;
+ _tcsncpy(temp,_attr->value,maxlen);
+ temp[maxlen] = 0;
+ return _tcstol(temp,NULL,10);
+#else
+ return _tcstol(_attr->value,NULL,10);
+#endif
+ }
+ //<summary>Cast attribute value as double. If not found, return 0.0.</summary>
+ //<returns>Attribute value as double, or 0.0.</returns>
+ //<remarks>Note: Modifying this will not change the value, e.g. read only.</remarks>
+ operator double()
+ {
+ if(empty() || !has_value()) return 0.0;
+#ifdef PUGOPT_NONSEG
+ TCHAR temp[PUGDEF_ATTR_VALU_SIZE];
+ unsigned int valulen = sizeof(temp)-1;
+ const unsigned int maxlen = valulen ? (std::min)(valulen,_attr->value_size) : _attr->value_size;
+ _tcsncpy(temp,_attr->value,maxlen);
+ temp[maxlen] = 0;
+ return _tcstod(temp,0);
+#else
+ return _tcstod(_attr->value,0);
+#endif
+ }
+ //<summary>Cast attribute value as bool. If not found, return false.</summary>
+ //<returns>Attribute value as bool, or false.</returns>
+ //<remarks>Note: Modifying this will not change the value, e.g. read only.</remarks>
+ operator bool()
+ {
+ if(empty() || !has_value()) return false;
+ if(*(_attr->value))
+ {
+ return //Only look at first char:
+ (
+ *(_attr->value) == _T('1') || //1*
+ *(_attr->value) == _T('t') || //t* (true)
+ *(_attr->value) == _T('T') || //T* (True|true)
+ *(_attr->value) == _T('y') || //y* (yes)
+ *(_attr->value) == _T('Y') //Y* (Yes|YES)
+ )
+ ? true : false; //Return true if matches above, else false.
+ }
+ }
+ //<summary>Set attribute to std::string.</summary>
+ //<param name="rhs">Value std::string to set.</param>
+ //<returns>Reference to xml_attribute.</returns>
+ xml_attribute& operator=(const std::string& rhs){ value(rhs.c_str()); return *this; }
+ //<summary>Set attribute to string.</summary>
+ //<param name="rhs">Value string to set.</param>
+ //<returns>Reference to xml_attribute.</returns>
+ xml_attribute& operator=(const TCHAR* rhs){ if(rhs) value(rhs); return *this; }
+ //<summary>Set attribute to long.</summary>
+ //<param name="rhs">Value long to set.</param>
+ //<returns>Reference to xml_attribute.</returns>
+ xml_attribute& operator=(long rhs)
+ {
+ TCHAR temp[32] = {0};
+ _stprintf(temp,_T("%ld"),rhs);
+ value(temp);
+ return *this;
+ }
+ //<summary>Set attribute to double.</summary>
+ //<param name="rhs">Value double to set.</param>
+ //<returns>Reference to xml_attribute.</returns>
+ xml_attribute& operator=(double rhs)
+ {
+ TCHAR temp[32] = {0};
+ _stprintf(temp,_T("%lf"),rhs);
+ value(temp);
+ return *this;
+ }
+ //<summary>Set attribute to bool.</summary>
+ //<param name="rhs">Value bool to set.</param>
+ //<returns>Reference to xml_attribute.</returns>
+ xml_attribute& operator=(bool rhs)
+ {
+ value(rhs?_T("true"):_T("false"));
+ return *this;
+ }
+ //<summary>Right-shift attribute value to std::string.</summary>
+ //<param name="rhs">Reference to std::string to set.</param>
+ //<returns>Reference to xml_attribute.</returns>
+ xml_attribute& operator>>(std::string& rhs)
+ {
+#ifdef PUGOPT_NONSEG
+ rhs.clear();
+ rhs.append(_attr->value,_attr->value_size);
+#else
+ rhs = value();
+#endif
+ return *this;
+ }
+ //<summary>Right-shift attribute value to long.</summary>
+ //<param name="rhs">Reference to long to set.</param>
+ //<returns>Reference to xml_attribute.</returns>
+ xml_attribute& operator>>(long& rhs){ rhs = (long)*this; return *this; }
+ //<summary>Right-shift attribute value to double.</summary>
+ //<param name="rhs">Reference to double to set.</param>
+ //<returns>Reference to xml_attribute.</returns>
+ xml_attribute& operator>>(double& rhs){ rhs = (double)*this; return *this; }
+ //<summary>Right-shift attribute value to bool.</summary>
+ //<param name="rhs">Reference to bool to set.</param>
+ //<returns>Reference to xml_attribute.</returns>
+ xml_attribute& operator>>(bool& rhs){ rhs = (bool)*this; return *this; }
+ //<summary>Left-shift attribute value to long.</summary>
+ //<param name="lhs">Reference to long to set.</param>
+ //<param name="rhs">Reference to xml_attribute to read.</param>
+ //<returns>Reference to long.</returns>
+ friend long& operator<<(long& lhs,xml_attribute& rhs){ lhs = (long)rhs; return lhs; }
+ //<summary>Left-shift attribute value to double.</summary>
+ //<param name="lhs">Reference to double to set.</param>
+ //<param name="rhs">Reference to xml_attribute to read.</param>
+ //<returns>Reference to double.</returns>
+ friend double& operator<<(double& lhs,xml_attribute& rhs){ lhs = (double)rhs; return lhs; }
+ //<summary>Left-shift attribute value to bool.</summary>
+ //<param name="lhs">Reference to bool to set.</param>
+ //<param name="rhs">Reference to xml_attribute to read.</param>
+ //<returns>Reference to bool.</returns>
+ friend bool& operator<<(bool& lhs,xml_attribute& rhs){ lhs = (bool)rhs; return lhs; }
+ //<summary>Left-shift long to attribute value.</summary>
+ //<param name="lhs">Reference to xml_attribute to set.</param>
+ //<param name="rhs">Reference to long to read.</param>
+ //<returns>Reference to xml_attribute.</returns>
+ friend xml_attribute& operator<<(xml_attribute& lhs,const long rhs){ lhs = rhs; return lhs; }
+ //<summary>Left-shift double to attribute value.</summary>
+ //<param name="lhs">Reference to xml_attribute to set.</param>
+ //<param name="rhs">Reference to double to read.</param>
+ //<returns>Reference to xml_attribute.</returns>
+ friend xml_attribute& operator<<(xml_attribute& lhs,const double& rhs){ lhs = rhs; return lhs; }
+ //<summary>Left-shift bool to attribute value.</summary>
+ //<param name="lhs">Reference to xml_attribute to set.</param>
+ //<param name="rhs">Reference to bool to read.</param>
+ //<returns>Reference to xml_attribute.</returns>
+ friend xml_attribute& operator<<(xml_attribute& lhs,const bool& rhs){ lhs = rhs; return lhs; }
+public:
+ bool empty(){ return (_attr == NULL); } //True if the internal xml_attribute_struct pointer is NULL.
+ bool has_name(){ return (!empty() && _attr->name); } //True if the attribute has a name.
+ bool has_value(){ return (!empty() && _attr->value); } //True if the attribute has a value.
+#ifdef PUGOPT_NONSEG
+ bool has_name(const TCHAR* name) { return (name && !empty() && has_name() && _tcsncmp(_attr->name,name,_attr->name_size)==0); } //Is named 'name'.
+ bool has_value(const TCHAR* value) { return (value && !empty() && has_value() && _tcsncmp(_attr->value,value,_attr->value_size)==0); } //Has value 'value'.
+#else
+ bool has_name(const TCHAR* name) { return (name && !empty() && has_name() && _tcscmp(_attr->name,name)==0); } //Is named 'name'.
+ bool has_value(const TCHAR* value) { return (value && !empty() && has_value() && _tcscmp(_attr->value,value)==0); } //Has value 'value'.
+#endif
+public:
+ const TCHAR* name(){ return (!empty() && _attr->name) ? _attr->name : _T(""); } //Access the attribute name.
+#ifdef PUGOPT_NONSEG
+ const unsigned int name_size(){ return (!empty()) ? _attr->name_size : 0; } //Access the attribute name length (for PUGOPT_NONSEG).
+#endif
+ bool name(TCHAR* new_name) //Set the attribute name.
+ {
+ if(!empty() && new_name)
+#ifdef PUGOPT_NONSEG
+ return strcpyinsitu(&_attr->name,new_name,&_attr->name_insitu,_attr->name_size);
+#else
+ return strcpyinsitu(&_attr->name,new_name,&_attr->name_insitu);
+#endif
+ return false;
+ }
+ const TCHAR* value(){ return (!empty()) ? _attr->value : _T(""); } //Access the attribute value.
+#ifdef PUGOPT_NONSEG
+ const unsigned int value_size(){ return (!empty()) ? _attr->value_size : 0; } //Access the attribute name length (for PUGOPT_NONSEG).
+#endif
+ bool value(const TCHAR* new_value) //Set the attribute value.
+ {
+ if(!empty() && new_value)
 #ifdef PUGOPT_NONSEG
- return strcpyinsitu(&_attr->value,new_value,&_attr->value_insitu,_attr->value_size);
+ return strcpyinsitu(&_attr->value,new_value,&_attr->value_insitu,_attr->value_size);
 #else
- return strcpyinsitu(&_attr->value,new_value,&_attr->value_insitu);
+ return strcpyinsitu(&_attr->value,new_value,&_attr->value_insitu);
 #endif
- return false;
- }
+ return false;
+ }
 };
 
 
@@ -2124,24 +2124,24 @@
 
 //<summary>Forward wrapper for any as-yet undefined class.</summary>
 //<remarks>
-// Used by xml_node_iterator, and xml_attribute_iterator to assist with
-// operator->(), and operator*() mapping to xml_node and xml_attribute
-// types.
+// Used by xml_node_iterator, and xml_attribute_iterator to assist with
+// operator->(), and operator*() mapping to xml_node and xml_attribute
+// types.
 //</remarks>
 template <typename TYPE> class forward_class
 {
 protected:
- TYPE* _obj; //The class, internal.
+ TYPE* _obj; //The class, internal.
 public:
- forward_class() : _obj(NULL) { _obj = new TYPE(); } //Default constructor.
- forward_class(const TYPE& r) : _obj(NULL) { _obj = new TYPE(r); } //Copy constructor.
- virtual ~forward_class(){ if(_obj) delete _obj; } //Destructor.
-public:
- TYPE& operator* (){ return *_obj; } //Dereference to the class.
- TYPE* operator->(){ return _obj; } //Class member selection.
- operator TYPE (){ return *_obj; } //Cast as class type.
- operator TYPE&(){ return *_obj; } //Cast as class type reference.
- operator TYPE*(){ return _obj; } //Cast as class type pointer.
+ forward_class() : _obj(NULL) { _obj = new TYPE(); } //Default constructor.
+ forward_class(const TYPE& r) : _obj(NULL) { _obj = new TYPE(r); } //Copy constructor.
+ virtual ~forward_class(){ if(_obj) delete _obj; } //Destructor.
+public:
+ TYPE& operator* (){ return *_obj; } //Dereference to the class.
+ TYPE* operator->(){ return _obj; } //Class member selection.
+ operator TYPE (){ return *_obj; } //Cast as class type.
+ operator TYPE&(){ return *_obj; } //Cast as class type reference.
+ operator TYPE*(){ return _obj; } //Cast as class type pointer.
 };
 
 
@@ -2151,1355 +2151,1355 @@
 //Internal Data Members
 protected:
 
- xml_node_struct* _root; //Pointer to node root.
- xml_node_struct _dummy; //Utility.
+ xml_node_struct* _root; //Pointer to node root.
+ xml_node_struct _dummy; //Utility.
 
 //Construction/Destruction
 public:
 
- //<summary>Default constructor.</summary>
- //<remarks>
- // Node root points to a dummy 'xml_node_struct' structure. Test for this
- // with 'empty'.
- //</remarks>
- xml_node(): _root(0)
- {
- memset(&_dummy,0,sizeof(xml_node_struct));
- _dummy.type = node_null;
- _dummy.parent = &_dummy;
- _root = &_dummy;
- }
-
- //<summary>Construct, wrapping the given 'xml_node_struct' pointer.</summary>
- //<param name="p">Pointer to node to wrap.</param>
- //<remarks>It is possible that 'p' is NULL, so test for this with 'empty'.</remarks>
- xml_node(xml_node_struct* p): _root(p) { memset(&_dummy,0,sizeof(xml_node_struct)); }
-
- //<summary>Copy constructor.</summary>
- //<param name="r">Reference to node.</param>
- //<remarks>
- // Only the root pointer is assigned, so both classes now in fact point
- // to the same structure.
- //</remarks>
- xml_node(const xml_node& r): _root(r._root) {}
-
- //<summary>Destructor.</summary>
- virtual ~xml_node(){}
-
- //<summary>Attach to the given structure.</summary>
- //<param name="p">Pointer to node structure to wrap.</param>
- //<returns>Pointer to previous node structure.</returns>
- xml_node_struct* attach(xml_node_struct* p)
- {
- xml_node_struct* prev = _root;
- _root = p;
- return prev;
- }
+ //<summary>Default constructor.</summary>
+ //<remarks>
+ // Node root points to a dummy 'xml_node_struct' structure. Test for this
+ // with 'empty'.
+ //</remarks>
+ xml_node(): _root(0)
+ {
+ memset(&_dummy,0,sizeof(xml_node_struct));
+ _dummy.type = node_null;
+ _dummy.parent = &_dummy;
+ _root = &_dummy;
+ }
+
+ //<summary>Construct, wrapping the given 'xml_node_struct' pointer.</summary>
+ //<param name="p">Pointer to node to wrap.</param>
+ //<remarks>It is possible that 'p' is NULL, so test for this with 'empty'.</remarks>
+ xml_node(xml_node_struct* p): _root(p) { memset(&_dummy,0,sizeof(xml_node_struct)); }
+
+ //<summary>Copy constructor.</summary>
+ //<param name="r">Reference to node.</param>
+ //<remarks>
+ // Only the root pointer is assigned, so both classes now in fact point
+ // to the same structure.
+ //</remarks>
+ xml_node(const xml_node& r): _root(r._root) {}
+
+ //<summary>Destructor.</summary>
+ virtual ~xml_node(){}
+
+ //<summary>Attach to the given structure.</summary>
+ //<param name="p">Pointer to node structure to wrap.</param>
+ //<returns>Pointer to previous node structure.</returns>
+ xml_node_struct* attach(xml_node_struct* p)
+ {
+ xml_node_struct* prev = _root;
+ _root = p;
+ return prev;
+ }
 
 //Iteration
 public:
 
- //<summary>Child node iterator.</summary>
- class xml_node_iterator : public xml_iterator<xml_node,long,xml_node*,xml_node&>
- {
- protected:
- forward_class<xml_node> _wrap; //Wrapper for xml_node.
- public:
- xml_node_iterator() : _wrap(), xml_iterator<xml_node,long,xml_node*,xml_node&>() {} //Default constructor.
- xml_node_iterator(xml_node_struct* vref,long sscr = 0) : _wrap(), xml_iterator<xml_node,long,xml_node*,xml_node&>(vref,sscr) { } //Initializing constructor.
- xml_node_iterator(const xml_node_iterator& r) : _wrap(), xml_iterator<xml_node,long,xml_node*,xml_node&>(r) { } //Copy constructor.
- virtual bool good() //Internal validity.
- {
- if
- (
- _vref != 0 && //Pointing to some node.
- _vref->child != 0 && //The node has an array of children.
- _vref->children > 0 //There are 1 or more children in the array.
- )
- return true;
- return false;
- }
- virtual bool oob() //Out of bounds check.
- {
- if
- (
- !good() || //There is no data over which to iterate.
- _sscr < 0 || //Subscript is out of range.
- _sscr >= (long)_vref->children
- )
- return true;
- return false;
- }
- //<summary>Pointer dereference for current xml_node.<summary>
- //<returns>
- // Reference to the internal xml_node object, which wraps the
- // xml_node_struct corresponding to the node at the
- // current subscript.
- //</returns>
- virtual xml_node& operator*()
- {
- if(!oob()) _wrap->attach(_vref->child[_sscr]);
- else _wrap->attach(NULL);
- return (xml_node&)_wrap;
- }
- virtual xml_node* operator->() //Member selection for current xml_node.
- {
- if(!oob()) _wrap->attach(_vref->child[_sscr]);
- else _wrap->attach(NULL);
- return (xml_node*)_wrap;
- }
- };
-
- //<summary>Attribute iterator.</summary>
- class xml_attribute_iterator : public xml_iterator<xml_attribute,long,xml_attribute*,xml_attribute&>
- {
- protected:
- forward_class<xml_attribute> _wrap;
- public:
- xml_attribute_iterator() : _wrap(), xml_iterator<xml_attribute,long,xml_attribute*,xml_attribute&>() {} //Default constructor.
- xml_attribute_iterator(xml_node_struct* vref,long sscr = 0) : _wrap(), xml_iterator<xml_attribute,long,xml_attribute*,xml_attribute&>(vref,sscr) { } //Initializing constructor.
- xml_attribute_iterator(const xml_attribute_iterator& r) : _wrap(), xml_iterator<xml_attribute,long,xml_attribute*,xml_attribute&>(r) { } //Copy constructor.
- virtual bool good() //Internal validity check.
- {
- if
- (
- _vref != 0 && //Pointing to some node.
- _vref->attribute != 0 && //The node has an array of children.
- _vref->attributes > 0 //There are 1 or more children in the array.
- )
- return true;
- return false;
- }
- virtual bool oob() //Out of bounds check.
- {
- if
- (
- !good() || //There is no data over which to iterate.
- _sscr < 0 || //Subscript is out of range.
- _sscr >= (long)_vref->attributes //For 'end'
- )
- return true;
- return false;
- }
- //<summary>Pointer dereference for current xml_attribute.</summary>
- //<returns>
- // Reference to the internal xml_attribute object, which wraps the
- // xml_attribute_struct corresponding to the attribute at the
- // current subscript.
- //</returns>
- virtual xml_attribute& operator*()
- {
- if(!oob()) _wrap->attach(_vref->attribute[_sscr]);
- else _wrap->attach(NULL);
- return (xml_attribute&)_wrap;
- }
- //<summary>Member selection for current xml_attribute.</summary>
- //<returns></returns>
- virtual xml_attribute* operator->()
- {
- if(!oob()) _wrap->attach(_vref->attribute[_sscr]);
- else _wrap->attach(NULL);
- return (xml_attribute*)_wrap;
- }
- };
-
- //<summary>Base iterator type (for child nodes). Same as 'child_iterator'.</summary>
- typedef xml_node_iterator iterator;
- //<summary>Base iterator type (for child nodes). Same as 'iterator'.</summary>
- typedef xml_node_iterator child_iterator;
- //<summary>Base iterator type (for sibling nodes). Same as 'iterator'.</summary>
- typedef xml_node_iterator sibling_iterator;
- //<summary>Attribute iterator type.</summary>
- typedef xml_attribute_iterator attribute_iterator;
-
- //<summary>Access the begin iterator for this node's collection of child nodes.</summary>
- //<returns>The begin iterator for this node's collection of child nodes.</returns>
- //<remarks>Same as 'children_begin'.</remarks>
- iterator begin(){ return iterator(_root,0); }
- //<summary>Access the end iterator for this node's collection of child nodes.</summary>
- //<returns>The end iterator for this node's collection of child nodes.</returns>
- //<remarks>Same as 'children_end'.</remarks>
- iterator end(){ return iterator(_root,_root->children); }
- //<summary>Erase the given node from node's collection of child nodes.</summary>
- //<returns>The begin iterator for this node's collection of child nodes.</returns>
- //<remarks>Same as 'children_erase'.</remarks>
- iterator erase(iterator where){ remove_child((unsigned int)where.subscript()); return iterator(_root,0); }
-
- //<summary>Access the begin iterator for this node's collection of child nodes.</summary>
- //<returns>The begin iterator for this node's collection of child nodes.</returns>
- //<remarks>Same as 'begin'.</remarks>
- child_iterator children_begin(){ return child_iterator(_root,0); }
- //<summary>Access the end iterator for this node's collection of child nodes.</summary>
- //<returns>The end iterator for this node's collection of child nodes.</returns>
- //<remarks>Same as 'end'.</remarks>
- child_iterator children_end(){ return child_iterator(_root,_root->children); }
- //<summary>Erase the given node from node's collection of child nodes.</summary>
- //<returns>The begin iterator for this node's collection of child nodes.</returns>
- //<remarks>Same as 'erase'.</remarks>
- child_iterator children_erase(child_iterator where){ remove_child((unsigned int)where.subscript()); return child_iterator(_root,0); }
-
- //<summary>Access the begin iterator for this node's collection of attributes.</summary>
- //<returns>The begin iterator for this node's collection of attributes.</returns>
- attribute_iterator attributes_begin(){ return attribute_iterator(_root,0); }
- //<summary>Access the end iterator for this node's collection of attributes.</summary>
- //<returns>The end iterator for this node's collection of attributes.</returns>
- attribute_iterator attributes_end(){ return attribute_iterator(_root,_root->attributes); }
- //<summary>Erase the given attribute from node's collection of attributes.</summary>
- //<returns>The begin iterator for this node's collection of attributes.</returns>
- attribute_iterator attributes_erase(attribute_iterator where){ remove_attribute((unsigned int)where.subscript()); return attribute_iterator(_root,0); }
-
- //<summary>Access the begin iterator for this node's collection of siblings.</summary>
- //<returns>The begin iterator for this node's collection of siblings.</returns>
- sibling_iterator siblings_begin(){ if(!empty()) return sibling_iterator(_root->parent,0); return sibling_iterator(); }
- //<summary>Access the end iterator for this node's collection of siblings.</summary>
- //<returns>The end iterator for this node's collection of siblings.</returns>
- sibling_iterator siblings_end(){ if(!empty()) return sibling_iterator(_root->parent,_root->parent->children); return sibling_iterator(); }
- //<summary>Erase the given sibling from node's collection of siblings.</summary>
- //<returns>The begin iterator for this node's collection of siblings.</returns>
- sibling_iterator siblings_erase(sibling_iterator where){ parent().remove_child((unsigned int)where.subscript()); return iterator(_root->parent,0); }
+ //<summary>Child node iterator.</summary>
+ class xml_node_iterator : public xml_iterator<xml_node,long,xml_node*,xml_node&>
+ {
+ protected:
+ forward_class<xml_node> _wrap; //Wrapper for xml_node.
+ public:
+ xml_node_iterator() : _wrap(), xml_iterator<xml_node,long,xml_node*,xml_node&>() {} //Default constructor.
+ xml_node_iterator(xml_node_struct* vref,long sscr = 0) : _wrap(), xml_iterator<xml_node,long,xml_node*,xml_node&>(vref,sscr) { } //Initializing constructor.
+ xml_node_iterator(const xml_node_iterator& r) : _wrap(), xml_iterator<xml_node,long,xml_node*,xml_node&>(r) { } //Copy constructor.
+ virtual bool good() //Internal validity.
+ {
+ if
+ (
+ _vref != 0 && //Pointing to some node.
+ _vref->child != 0 && //The node has an array of children.
+ _vref->children > 0 //There are 1 or more children in the array.
+ )
+ return true;
+ return false;
+ }
+ virtual bool oob() //Out of bounds check.
+ {
+ if
+ (
+ !good() || //There is no data over which to iterate.
+ _sscr < 0 || //Subscript is out of range.
+ _sscr >= (long)_vref->children
+ )
+ return true;
+ return false;
+ }
+ //<summary>Pointer dereference for current xml_node.<summary>
+ //<returns>
+ // Reference to the internal xml_node object, which wraps the
+ // xml_node_struct corresponding to the node at the
+ // current subscript.
+ //</returns>
+ virtual xml_node& operator*()
+ {
+ if(!oob()) _wrap->attach(_vref->child[_sscr]);
+ else _wrap->attach(NULL);
+ return (xml_node&)_wrap;
+ }
+ virtual xml_node* operator->() //Member selection for current xml_node.
+ {
+ if(!oob()) _wrap->attach(_vref->child[_sscr]);
+ else _wrap->attach(NULL);
+ return (xml_node*)_wrap;
+ }
+ };
+
+ //<summary>Attribute iterator.</summary>
+ class xml_attribute_iterator : public xml_iterator<xml_attribute,long,xml_attribute*,xml_attribute&>
+ {
+ protected:
+ forward_class<xml_attribute> _wrap;
+ public:
+ xml_attribute_iterator() : _wrap(), xml_iterator<xml_attribute,long,xml_attribute*,xml_attribute&>() {} //Default constructor.
+ xml_attribute_iterator(xml_node_struct* vref,long sscr = 0) : _wrap(), xml_iterator<xml_attribute,long,xml_attribute*,xml_attribute&>(vref,sscr) { } //Initializing constructor.
+ xml_attribute_iterator(const xml_attribute_iterator& r) : _wrap(), xml_iterator<xml_attribute,long,xml_attribute*,xml_attribute&>(r) { } //Copy constructor.
+ virtual bool good() //Internal validity check.
+ {
+ if
+ (
+ _vref != 0 && //Pointing to some node.
+ _vref->attribute != 0 && //The node has an array of children.
+ _vref->attributes > 0 //There are 1 or more children in the array.
+ )
+ return true;
+ return false;
+ }
+ virtual bool oob() //Out of bounds check.
+ {
+ if
+ (
+ !good() || //There is no data over which to iterate.
+ _sscr < 0 || //Subscript is out of range.
+ _sscr >= (long)_vref->attributes //For 'end'
+ )
+ return true;
+ return false;
+ }
+ //<summary>Pointer dereference for current xml_attribute.</summary>
+ //<returns>
+ // Reference to the internal xml_attribute object, which wraps the
+ // xml_attribute_struct corresponding to the attribute at the
+ // current subscript.
+ //</returns>
+ virtual xml_attribute& operator*()
+ {
+ if(!oob()) _wrap->attach(_vref->attribute[_sscr]);
+ else _wrap->attach(NULL);
+ return (xml_attribute&)_wrap;
+ }
+ //<summary>Member selection for current xml_attribute.</summary>
+ //<returns></returns>
+ virtual xml_attribute* operator->()
+ {
+ if(!oob()) _wrap->attach(_vref->attribute[_sscr]);
+ else _wrap->attach(NULL);
+ return (xml_attribute*)_wrap;
+ }
+ };
+
+ //<summary>Base iterator type (for child nodes). Same as 'child_iterator'.</summary>
+ typedef xml_node_iterator iterator;
+ //<summary>Base iterator type (for child nodes). Same as 'iterator'.</summary>
+ typedef xml_node_iterator child_iterator;
+ //<summary>Base iterator type (for sibling nodes). Same as 'iterator'.</summary>
+ typedef xml_node_iterator sibling_iterator;
+ //<summary>Attribute iterator type.</summary>
+ typedef xml_attribute_iterator attribute_iterator;
+
+ //<summary>Access the begin iterator for this node's collection of child nodes.</summary>
+ //<returns>The begin iterator for this node's collection of child nodes.</returns>
+ //<remarks>Same as 'children_begin'.</remarks>
+ iterator begin(){ return iterator(_root,0); }
+ //<summary>Access the end iterator for this node's collection of child nodes.</summary>
+ //<returns>The end iterator for this node's collection of child nodes.</returns>
+ //<remarks>Same as 'children_end'.</remarks>
+ iterator end(){ return iterator(_root,_root->children); }
+ //<summary>Erase the given node from node's collection of child nodes.</summary>
+ //<returns>The begin iterator for this node's collection of child nodes.</returns>
+ //<remarks>Same as 'children_erase'.</remarks>
+ iterator erase(iterator where){ remove_child((unsigned int)where.subscript()); return iterator(_root,0); }
+
+ //<summary>Access the begin iterator for this node's collection of child nodes.</summary>
+ //<returns>The begin iterator for this node's collection of child nodes.</returns>
+ //<remarks>Same as 'begin'.</remarks>
+ child_iterator children_begin(){ return child_iterator(_root,0); }
+ //<summary>Access the end iterator for this node's collection of child nodes.</summary>
+ //<returns>The end iterator for this node's collection of child nodes.</returns>
+ //<remarks>Same as 'end'.</remarks>
+ child_iterator children_end(){ return child_iterator(_root,_root->children); }
+ //<summary>Erase the given node from node's collection of child nodes.</summary>
+ //<returns>The begin iterator for this node's collection of child nodes.</returns>
+ //<remarks>Same as 'erase'.</remarks>
+ child_iterator children_erase(child_iterator where){ remove_child((unsigned int)where.subscript()); return child_iterator(_root,0); }
+
+ //<summary>Access the begin iterator for this node's collection of attributes.</summary>
+ //<returns>The begin iterator for this node's collection of attributes.</returns>
+ attribute_iterator attributes_begin(){ return attribute_iterator(_root,0); }
+ //<summary>Access the end iterator for this node's collection of attributes.</summary>
+ //<returns>The end iterator for this node's collection of attributes.</returns>
+ attribute_iterator attributes_end(){ return attribute_iterator(_root,_root->attributes); }
+ //<summary>Erase the given attribute from node's collection of attributes.</summary>
+ //<returns>The begin iterator for this node's collection of attributes.</returns>
+ attribute_iterator attributes_erase(attribute_iterator where){ remove_attribute((unsigned int)where.subscript()); return attribute_iterator(_root,0); }
+
+ //<summary>Access the begin iterator for this node's collection of siblings.</summary>
+ //<returns>The begin iterator for this node's collection of siblings.</returns>
+ sibling_iterator siblings_begin(){ if(!empty()) return sibling_iterator(_root->parent,0); return sibling_iterator(); }
+ //<summary>Access the end iterator for this node's collection of siblings.</summary>
+ //<returns>The end iterator for this node's collection of siblings.</returns>
+ sibling_iterator siblings_end(){ if(!empty()) return sibling_iterator(_root->parent,_root->parent->children); return sibling_iterator(); }
+ //<summary>Erase the given sibling from node's collection of siblings.</summary>
+ //<returns>The begin iterator for this node's collection of siblings.</returns>
+ sibling_iterator siblings_erase(sibling_iterator where){ parent().remove_child((unsigned int)where.subscript()); return iterator(_root->parent,0); }
 
 //Overloaded Operators
 public:
 
- operator xml_node_struct*(){ return _root; } //Cast as xml_node_struct pointer.
- operator void*(){ return (void*)_root; } //Cast root as void*.
- xml_node& operator=(const xml_node& r){ _root = r._root; return *this; } //Assign to xml_node_struct pointer.
- bool operator==(const xml_node& r){ return (_root == r._root); } //True if this has the same internal xml_node_struct pointer value.
- xml_node operator[](unsigned int i){ return child(i); } //Access the child at subscript.
+ operator xml_node_struct*(){ return _root; } //Cast as xml_node_struct pointer.
+ operator void*(){ return (void*)_root; } //Cast root as void*.
+ xml_node& operator=(const xml_node& r){ _root = r._root; return *this; } //Assign to xml_node_struct pointer.
+ bool operator==(const xml_node& r){ return (_root == r._root); } //True if this has the same internal xml_node_struct pointer value.
+ xml_node operator[](unsigned int i){ return child(i); } //Access the child at subscript.
 
 //Node Classification
 public:
 
- bool empty() { return (_root == 0 || _root->type == node_null); } //Node pointer is null, or type is node_null. Same as type_null.
- bool type_null() { return empty(); } //Node pointer is null, or type is node_null. Same as empty.
- bool type_document() { return (_root && _root == _root->parent && _root->type == node_document); } //Node is tree root.
- bool type_element() { return (_root && _root->type == node_element); } //Node is an element.
- bool type_comment() { return (_root && _root->type == node_comment); } //Node is a comment.
- bool type_pcdata() { return (_root && _root->type == node_pcdata); } //Node is PCDATA.
- bool type_cdata() { return (_root && _root->type == node_cdata); } //Node is CDATA.
- bool type_include() { return (_root && _root->type == node_include); } //Node is INCLUDE.
- bool type_pi() { return (_root && _root->type == node_pi); } //Node is a processing instruction.
- bool type_doctype() { return (_root && _root->type == node_doctype); } //Node is DOCTYPE.
- bool type_dtd_item() { return (_root && _root->type > node_doctype); } //Node is NODE_DTD_*.
- bool type_dtd_attlist() { return (_root && _root->type == node_dtd_attlist); } //Node is node_dtd_attlist.
- bool type_dtd_element() { return (_root && _root->type == node_dtd_element); } //Node is node_dtd_element.
- bool type_dtd_entity() { return (_root && _root->type == node_dtd_entity); } //Node is node_dtd_entity.
- bool type_dtd_notation() { return (_root && _root->type == node_dtd_notation); } //Node is node_dtd_notation.
+ bool empty() { return (_root == 0 || _root->type == node_null); } //Node pointer is null, or type is node_null. Same as type_null.
+ bool type_null() { return empty(); } //Node pointer is null, or type is node_null. Same as empty.
+ bool type_document() { return (_root && _root == _root->parent && _root->type == node_document); } //Node is tree root.
+ bool type_element() { return (_root && _root->type == node_element); } //Node is an element.
+ bool type_comment() { return (_root && _root->type == node_comment); } //Node is a comment.
+ bool type_pcdata() { return (_root && _root->type == node_pcdata); } //Node is PCDATA.
+ bool type_cdata() { return (_root && _root->type == node_cdata); } //Node is CDATA.
+ bool type_include() { return (_root && _root->type == node_include); } //Node is INCLUDE.
+ bool type_pi() { return (_root && _root->type == node_pi); } //Node is a processing instruction.
+ bool type_doctype() { return (_root && _root->type == node_doctype); } //Node is DOCTYPE.
+ bool type_dtd_item() { return (_root && _root->type > node_doctype); } //Node is NODE_DTD_*.
+ bool type_dtd_attlist() { return (_root && _root->type == node_dtd_attlist); } //Node is node_dtd_attlist.
+ bool type_dtd_element() { return (_root && _root->type == node_dtd_element); } //Node is node_dtd_element.
+ bool type_dtd_entity() { return (_root && _root->type == node_dtd_entity); } //Node is node_dtd_entity.
+ bool type_dtd_notation() { return (_root && _root->type == node_dtd_notation); } //Node is node_dtd_notation.
 
 //Member Inventory
 public:
 
- bool has_value() { return (!empty() && _root->value != 0); } //Node has data (comment, CDATA or PCDATA).
- bool has_child_nodes() { return (!empty() && children() > 0); } //Node has 1 or more children.
- bool has_attributes() { return (!empty() && attributes() > 0); } //Node has 1 or more attributes.
- bool has_siblings() { return (!empty() && siblings() > 0); } //Node has one or more siblings.
- bool has_name() { return (!empty() && _root->name != 0); } //Node has a name.
- bool has_name(const std::string& name) const { return has_name(name.c_str()); } //Node is named 'name'.
- bool has_attribute(const std::string& name) { return has_attribute(name.c_str()); } //Node has an attribute named 'name'.
+ bool has_value() { return (!empty() && _root->value != 0); } //Node has data (comment, CDATA or PCDATA).
+ bool has_child_nodes() { return (!empty() && children() > 0); } //Node has 1 or more children.
+ bool has_attributes() { return (!empty() && attributes() > 0); } //Node has 1 or more attributes.
+ bool has_siblings() { return (!empty() && siblings() > 0); } //Node has one or more siblings.
+ bool has_name() { return (!empty() && _root->name != 0); } //Node has a name.
+ bool has_name(const std::string& name) const { return has_name(name.c_str()); } //Node is named 'name'.
+ bool has_attribute(const std::string& name) { return has_attribute(name.c_str()); } //Node has an attribute named 'name'.
 #ifdef PUGOPT_NONSEG
- bool has_name(const TCHAR* name) const { return (name && _root && _root->name && _tcsncmp(_root->name,name,_root->name_size)==0); } //Node is named 'name'.
+ bool has_name(const TCHAR* name) const { return (name && _root && _root->name && _tcsncmp(_root->name,name,_root->name_size)==0); } //Node is named 'name'.
 #else
- bool has_name(const TCHAR* name) const { return (name && _root && _root->name && strcmpwild(name,_root->name)==0); } //Node is named 'name'.
+ bool has_name(const TCHAR* name) const { return (name && _root && _root->name && strcmpwild(name,_root->name)==0); } //Node is named 'name'.
 #endif
- bool has_attribute(const TCHAR* name){ return (mapto_attribute_idx(name) > -1); } //Node has an attribute named name.
+ bool has_attribute(const TCHAR* name){ return (mapto_attribute_idx(name) > -1); } //Node has an attribute named name.
 
 //Member Accessors
 public:
 
 #ifdef PUGOPT_NONSEG
 
- //<summary>Access node name if any.</summary>
- //<returns>Name, or dummy value if the no name.</returns>
- //<remarks>Only returns up to 'PUGDEF_ELEM_NAME_SIZE' chars of name.</remarks>
- const TCHAR* name()
- {
- static TCHAR temp[PUGDEF_ELEM_NAME_SIZE] = {0};
- if(has_name())
- {
- _tcsncpy(temp,_root->name,_root->name_size);
- temp[_root->name_size<PUGDEF_ELEM_NAME_SIZE?_root->name_size:(PUGDEF_ELEM_NAME_SIZE-1)] = 0;
- return temp;
- }
- return _T("");
- }
- unsigned int name_size(){ return (has_name()) ? _root->name_size : 0; } //Get node name length if any, else 0.
- unsigned int value_size(){ return (has_value()) ? _root->value_size : 0; } //Get node value length if any, else 0.
- inline bool matches_attribute_name(const TCHAR* name,const unsigned int namelen,const int i) const { return (_tcsncmp(name,_root->attribute[i]->name,max(namelen,_root->attribute[i]->name_size))==0); } //There is an attribute at 'i' named 'name'.
- inline bool matches_child_name(const TCHAR* name,const unsigned int namelen,const int i) const { return (_tcsncmp(name,_root->child[i]->name,max(namelen,_root->child[i]->name_size))==0); } //There is a child at 'i' named 'name'.
- inline bool matches_name(const TCHAR* name,const unsigned int namelen,xml_node_struct* node) const { return (_tcsncmp(name,node->name,max(namelen,node->name_size))==0); } //This is named 'name'.
- inline bool matches_value(const TCHAR* data,const unsigned int datalen,xml_node_struct* node) const { return (_tcsncmp(data,node->value,max(datalen,node->value_size))==0); } //This is valued 'value'.
- inline bool matches_attribute_name(const TCHAR* name,const unsigned int namelen,xml_attribute_struct* attr) const { return (_tcsncmp(name,attr->name,max(namelen,attr->name_size))==0); } //The given attribute is named 'name'.
- inline bool matches_attribute_name_value(const TCHAR* value,const unsigned int valulen,xml_attribute_struct* attr) const { return (_tcsncmp(value,attr->value,max(valulen,attr->value_size))==0); } //The given attribute is valued 'value'.
-#else
- const TCHAR* name(){ return (has_name()) ? _root->name : _T(""); } //Access pointer to node name if any, else empty string.
- inline bool matches_attribute_name(const TCHAR* name,const unsigned int i) const { return (strcmpwild(name,_root->attribute[i]->name)==0); } //There is an attribute at 'i' named 'name'.
- inline bool matches_child_name(const TCHAR* name,const unsigned int i) const { return (strcmpwild(name,_root->child[i]->name)==0); } //There is a child at 'i' named 'name'.
- inline bool matches_name(const TCHAR* name,xml_node_struct* node) const { return (strcmpwild(name,node->name)==0); } //This is named 'name'.
- inline bool matches_value(const TCHAR* data,xml_node_struct* node) const { return (strcmpwild(data,node->value)==0); } //This is valued 'value'.
- inline bool matches_attribute_name(const TCHAR* attribute,xml_attribute_struct* attr) const { return (strcmpwild(attribute,attr->name)==0); } //The given attribute is named 'name'.
- inline bool matches_attribute_name_value(const TCHAR* value,xml_attribute_struct* attr) const { return (strcmpwild(value,attr->value)==0); } //The given attribute is valued 'value'.
-#endif
- xml_node_type type() const { return (_root) ? (xml_node_type)_root->type : node_null; } //Access node entity type.
- const TCHAR* value() { return (has_value()) ? _root->value : _T(""); } //Access pointer to data if any, else empty string.
- unsigned int children() const { return _root->children; } //Access node's child count.
- xml_node child(unsigned int i){ return (i < children()) ? xml_node(_root->child[i]) : xml_node(); } //Access child node at subscript as xml_node or xml_node(NULL) if bad subscript.
- unsigned int attributes() const { return _root->attributes; } //Access node's attribute count.
- xml_attribute attribute(unsigned int i){ return (i < attributes()) ? xml_attribute(_root->attribute[i]) : xml_attribute(); } //Access attribute at subscript if any, else empty attribute.
- //<summary>Access or create the attribute having 'name'.</summary>
- //<param name="name">Name of attribute to access/create.</param>
- //<returns>Reference to xml_attribute wrapper.</returns>
- xml_attribute attribute(const std::string& name){ return attribute(name.c_str()); }
- //<summary>Access or create the attribute having 'name'.</summary>
- //<param name="name">Name of attribute to access/create.</param>
- //<returns>Reference to xml_attribute wrapper.</returns>
- xml_attribute attribute(const TCHAR* name)
- {
- xml_attribute_struct* attr = mapto_attribute_ptr(name);
- if(!attr) attr = append_attribute(name,_T(""));
- return xml_attribute(attr);
- }
- const unsigned int siblings(){ return (!type_document()) ? _root->parent->children : 0; } //Access node's sibling count (parent's child count).
- xml_node sibling(unsigned int i){ return (!type_document() && i < siblings()) ? xml_node(_root->parent->child[i]) : xml_node(); } //Access sibling node at subscript as xml_node or xml_node(NULL) if bad subscript.
- xml_node parent(){ return (!type_document()) ? xml_node(_root->parent) : xml_node(); } //Access node's parent if any, else xml_node(NULL)
-
- //<summary>Return the first child that has data's data. If none, return NULL.</summary>
- //<param name="value">Returns a copy of the data.</param>
- //<param name="valuelen">Specifies the maximum number of characters to copy into value.</param>
- //<returns>Pointer to value if exists, else NULL.</returns>
- //<remarks>
- // Used to get the PCDATA for the current element. This handles elements
- // like: &lt;LINE&gt;&lt;STAGEDIR&gt;Aside&lt;/STAGEDIR&gt;Thy father,
- // Pompey, would ne'er have&lt;/LINE&gt;, where 'this' points to &lt;LINE&gt;.
- //</remarks>
- TCHAR* child_value(TCHAR* value,const unsigned int valuelen)const
- {
- if(_root->children)
- {
- for(register unsigned int i=0; i < _root->children; ++i)
- {
- xml_node_struct* node = _root->child[i];
- if(node->value)
- {
- const unsigned int n =
+ //<summary>Access node name if any.</summary>
+ //<returns>Name, or dummy value if the no name.</returns>
+ //<remarks>Only returns up to 'PUGDEF_ELEM_NAME_SIZE' chars of name.</remarks>
+ const TCHAR* name()
+ {
+ static TCHAR temp[PUGDEF_ELEM_NAME_SIZE] = {0};
+ if(has_name())
+ {
+ _tcsncpy(temp,_root->name,_root->name_size);
+ temp[_root->name_size<PUGDEF_ELEM_NAME_SIZE?_root->name_size:(PUGDEF_ELEM_NAME_SIZE-1)] = 0;
+ return temp;
+ }
+ return _T("");
+ }
+ unsigned int name_size(){ return (has_name()) ? _root->name_size : 0; } //Get node name length if any, else 0.
+ unsigned int value_size(){ return (has_value()) ? _root->value_size : 0; } //Get node value length if any, else 0.
+ inline bool matches_attribute_name(const TCHAR* name,const unsigned int namelen,const int i) const { return (_tcsncmp(name,_root->attribute[i]->name,(std::max)(namelen,_root->attribute[i]->name_size))==0); } //There is an attribute at 'i' named 'name'.
+ inline bool matches_child_name(const TCHAR* name,const unsigned int namelen,const int i) const { return (_tcsncmp(name,_root->child[i]->name,(std::max)(namelen,_root->child[i]->name_size))==0); } //There is a child at 'i' named 'name'.
+ inline bool matches_name(const TCHAR* name,const unsigned int namelen,xml_node_struct* node) const { return (_tcsncmp(name,node->name,(std::max)(namelen,node->name_size))==0); } //This is named 'name'.
+ inline bool matches_value(const TCHAR* data,const unsigned int datalen,xml_node_struct* node) const { return (_tcsncmp(data,node->value,(std::max)(datalen,node->value_size))==0); } //This is valued 'value'.
+ inline bool matches_attribute_name(const TCHAR* name,const unsigned int namelen,xml_attribute_struct* attr) const { return (_tcsncmp(name,attr->name,(std::max)(namelen,attr->name_size))==0); } //The given attribute is named 'name'.
+ inline bool matches_attribute_name_value(const TCHAR* value,const unsigned int valulen,xml_attribute_struct* attr) const { return (_tcsncmp(value,attr->value,(std::max)(valulen,attr->value_size))==0); } //The given attribute is valued 'value'.
+#else
+ const TCHAR* name(){ return (has_name()) ? _root->name : _T(""); } //Access pointer to node name if any, else empty string.
+ inline bool matches_attribute_name(const TCHAR* name,const unsigned int i) const { return (strcmpwild(name,_root->attribute[i]->name)==0); } //There is an attribute at 'i' named 'name'.
+ inline bool matches_child_name(const TCHAR* name,const unsigned int i) const { return (strcmpwild(name,_root->child[i]->name)==0); } //There is a child at 'i' named 'name'.
+ inline bool matches_name(const TCHAR* name,xml_node_struct* node) const { return (strcmpwild(name,node->name)==0); } //This is named 'name'.
+ inline bool matches_value(const TCHAR* data,xml_node_struct* node) const { return (strcmpwild(data,node->value)==0); } //This is valued 'value'.
+ inline bool matches_attribute_name(const TCHAR* attribute,xml_attribute_struct* attr) const { return (strcmpwild(attribute,attr->name)==0); } //The given attribute is named 'name'.
+ inline bool matches_attribute_name_value(const TCHAR* value,xml_attribute_struct* attr) const { return (strcmpwild(value,attr->value)==0); } //The given attribute is valued 'value'.
+#endif
+ xml_node_type type() const { return (_root) ? (xml_node_type)_root->type : node_null; } //Access node entity type.
+ const TCHAR* value() { return (has_value()) ? _root->value : _T(""); } //Access pointer to data if any, else empty string.
+ unsigned int children() const { return _root->children; } //Access node's child count.
+ xml_node child(unsigned int i){ return (i < children()) ? xml_node(_root->child[i]) : xml_node(); } //Access child node at subscript as xml_node or xml_node(NULL) if bad subscript.
+ unsigned int attributes() const { return _root->attributes; } //Access node's attribute count.
+ xml_attribute attribute(unsigned int i){ return (i < attributes()) ? xml_attribute(_root->attribute[i]) : xml_attribute(); } //Access attribute at subscript if any, else empty attribute.
+ //<summary>Access or create the attribute having 'name'.</summary>
+ //<param name="name">Name of attribute to access/create.</param>
+ //<returns>Reference to xml_attribute wrapper.</returns>
+ xml_attribute attribute(const std::string& name){ return attribute(name.c_str()); }
+ //<summary>Access or create the attribute having 'name'.</summary>
+ //<param name="name">Name of attribute to access/create.</param>
+ //<returns>Reference to xml_attribute wrapper.</returns>
+ xml_attribute attribute(const TCHAR* name)
+ {
+ xml_attribute_struct* attr = mapto_attribute_ptr(name);
+ if(!attr) attr = append_attribute(name,_T(""));
+ return xml_attribute(attr);
+ }
+ const unsigned int siblings(){ return (!type_document()) ? _root->parent->children : 0; } //Access node's sibling count (parent's child count).
+ xml_node sibling(unsigned int i){ return (!type_document() && i < siblings()) ? xml_node(_root->parent->child[i]) : xml_node(); } //Access sibling node at subscript as xml_node or xml_node(NULL) if bad subscript.
+ xml_node parent(){ return (!type_document()) ? xml_node(_root->parent) : xml_node(); } //Access node's parent if any, else xml_node(NULL)
+
+ //<summary>Return the first child that has data's data. If none, return NULL.</summary>
+ //<param name="value">Returns a copy of the data.</param>
+ //<param name="valuelen">Specifies the maximum number of characters to copy into value.</param>
+ //<returns>Pointer to value if exists, else NULL.</returns>
+ //<remarks>
+ // Used to get the PCDATA for the current element. This handles elements
+ // like: &lt;LINE&gt;&lt;STAGEDIR&gt;Aside&lt;/STAGEDIR&gt;Thy father,
+ // Pompey, would ne'er have&lt;/LINE&gt;, where 'this' points to &lt;LINE&gt;.
+ //</remarks>
+ TCHAR* child_value(TCHAR* value,const unsigned int valuelen)const
+ {
+ if(_root->children)
+ {
+ for(register unsigned int i=0; i < _root->children; ++i)
+ {
+ xml_node_struct* node = _root->child[i];
+ if(node->value)
+ {
+ const unsigned int n =
 #ifdef PUGOPT_NONSEG
- (std::min)(valuelen,node->value_size);
+ (std::min)(valuelen,node->value_size);
 #else
                         (std::min)(valuelen,unsigned(_tcslen(node->value)));
 #endif
- _tcsncpy(value,node->value,n);
- value[n] = 0;
- break;
- }
- }
- return value;
- }
- return NULL;
- }
+ _tcsncpy(value,node->value,n);
+ value[n] = 0;
+ break;
+ }
+ }
+ return value;
+ }
+ return NULL;
+ }
 
 //Name-To-Object Mapping
 public:
 
- //<summary>Map an attribute name to a pointer to that attribute, if found.</summary>
- //<param name="name">Reference to name of attribute to find.</param>
- //<returns>Pointer to attribute, or NULL if not found.</returns>
- //<remarks>Implement your own hash table if you have a great many attributes.</remarks>
- xml_attribute_struct* mapto_attribute_ptr(const std::string& name){ return mapto_attribute_ptr(name.c_str()); }
-
- //<summary>Map an attribute name to a pointer to that attribute, if found.</summary>
- //<param name="name">Pointer to name of attribute to find.</param>
- //<returns>Pointer to attribute, or NULL if not found.</returns>
- //<remarks>Implement your own hash table if you have a great many attributes.</remarks>
- xml_attribute_struct* mapto_attribute_ptr(const TCHAR* name)
- {
- if(!_root || !name) return NULL;
- register unsigned int n = _root->attributes;
-#ifdef PUGOPT_NONSEG
- const int namelen = _tcslen(name);
-#endif
- for(register unsigned int i=0; i<n; ++i)
-#ifdef PUGOPT_NONSEG
- if(matches_attribute_name(name,namelen,i))
-#else
- if(matches_attribute_name(name,i))
-#endif
- return _root->attribute[i];
- return NULL;
- }
-
- //<summary>Map an attribute name to the index of that attribute, if found.</summary>
- //<param name="name">Pointer to name of attribute to find.</param>
- //<returns>Index of attribute, or -1 if not found.</returns>
- //<remarks>Implement your own hash table if you have a great many attributes.</remarks>
- int mapto_attribute_idx(const TCHAR* name)
- {
- if(!_root || !name) return -1;
- register unsigned int n = _root->attributes;
-#ifdef PUGOPT_NONSEG
- const int namelen = _tcslen(name);
-#endif
- for(register unsigned int i=0; i<n; ++i)
-#ifdef PUGOPT_NONSEG
- if(matches_attribute_name(name,namelen,i))
-#else
- if(matches_attribute_name(name,i))
-#endif
- return i;
- return -1;
- }
-
- //<summary>Map a child name to a pointer to the first instance, if found.</summary>
- //<param name="name">Reference to name of child to find.</param>
- //<returns>Index of child, or -1 if not found.</returns>
- //<remarks>Implement your own hash table if you have a great many children.</remarks>
- xml_node_struct* mapto_child_ptr(const std::string& name){ return mapto_child_ptr(name.c_str()); }
-
- //<summary>Map a child name to a pointer to the first instance, if found.</summary>
- //<param name="name">Pointer to name of child to find.</param>
- //<returns>Index of child, or -1 if not found.</returns>
- //<remarks>Implement your own hash table if you have a great many children.</remarks>
- xml_node_struct* mapto_child_ptr(const TCHAR* name)
- {
- if(!_root || !name) return NULL;
- register unsigned int n = _root->children;
-#ifdef PUGOPT_NONSEG
- const int namelen = _tcslen(name);
-#endif
- for(register unsigned int i=0; i<n; ++i)
- {
- if
- (
- _root->child[i]->name &&
-#ifdef PUGOPT_NONSEG
- matches_child_name(name,namelen,i)
-#else
- matches_child_name(name,i)
-#endif
- )
- return _root->child[i];
- }
- return NULL;
- }
-
- //<summary>Map a child name to the index of the first instance, if found.</summary>
- //<param name="name">Reference to name of child to find.</param>
- //<returns>Index of child, or -1 if not found.</returns>
- //<remarks>Implement your own hash table if you have a great many children.</remarks>
- int mapto_child_idx(const std::string& name){ return mapto_child_idx(name.c_str()); }
-
- //<summary>Map a child name to the index of the first instance, if found.</summary>
- //<param name="name">Pointer to name of child to find.</param>
- //<returns>Index of child, or -1 if not found.</returns>
- //<remarks>Implement your own hash table if you have a great many children.</remarks>
- int mapto_child_idx(const TCHAR* name)
- {
- if(!_root || !name) return -1;
- register unsigned int n = _root->children;
-#ifdef PUGOPT_NONSEG
- const int namelen = _tcslen(name);
-#endif
- for(register unsigned int i=0; i<n; ++i)
- {
- if
- (
- _root->child[i]->name &&
-#ifdef PUGOPT_NONSEG
- matches_child_name(name,namelen,i)
-#else
- matches_child_name(name,i)
-#endif
- )
- return i;
- }
- return -1;
- }
+ //<summary>Map an attribute name to a pointer to that attribute, if found.</summary>
+ //<param name="name">Reference to name of attribute to find.</param>
+ //<returns>Pointer to attribute, or NULL if not found.</returns>
+ //<remarks>Implement your own hash table if you have a great many attributes.</remarks>
+ xml_attribute_struct* mapto_attribute_ptr(const std::string& name){ return mapto_attribute_ptr(name.c_str()); }
+
+ //<summary>Map an attribute name to a pointer to that attribute, if found.</summary>
+ //<param name="name">Pointer to name of attribute to find.</param>
+ //<returns>Pointer to attribute, or NULL if not found.</returns>
+ //<remarks>Implement your own hash table if you have a great many attributes.</remarks>
+ xml_attribute_struct* mapto_attribute_ptr(const TCHAR* name)
+ {
+ if(!_root || !name) return NULL;
+ register unsigned int n = _root->attributes;
+#ifdef PUGOPT_NONSEG
+ const int namelen = _tcslen(name);
+#endif
+ for(register unsigned int i=0; i<n; ++i)
+#ifdef PUGOPT_NONSEG
+ if(matches_attribute_name(name,namelen,i))
+#else
+ if(matches_attribute_name(name,i))
+#endif
+ return _root->attribute[i];
+ return NULL;
+ }
+
+ //<summary>Map an attribute name to the index of that attribute, if found.</summary>
+ //<param name="name">Pointer to name of attribute to find.</param>
+ //<returns>Index of attribute, or -1 if not found.</returns>
+ //<remarks>Implement your own hash table if you have a great many attributes.</remarks>
+ int mapto_attribute_idx(const TCHAR* name)
+ {
+ if(!_root || !name) return -1;
+ register unsigned int n = _root->attributes;
+#ifdef PUGOPT_NONSEG
+ const int namelen = _tcslen(name);
+#endif
+ for(register unsigned int i=0; i<n; ++i)
+#ifdef PUGOPT_NONSEG
+ if(matches_attribute_name(name,namelen,i))
+#else
+ if(matches_attribute_name(name,i))
+#endif
+ return i;
+ return -1;
+ }
+
+ //<summary>Map a child name to a pointer to the first instance, if found.</summary>
+ //<param name="name">Reference to name of child to find.</param>
+ //<returns>Index of child, or -1 if not found.</returns>
+ //<remarks>Implement your own hash table if you have a great many children.</remarks>
+ xml_node_struct* mapto_child_ptr(const std::string& name){ return mapto_child_ptr(name.c_str()); }
+
+ //<summary>Map a child name to a pointer to the first instance, if found.</summary>
+ //<param name="name">Pointer to name of child to find.</param>
+ //<returns>Index of child, or -1 if not found.</returns>
+ //<remarks>Implement your own hash table if you have a great many children.</remarks>
+ xml_node_struct* mapto_child_ptr(const TCHAR* name)
+ {
+ if(!_root || !name) return NULL;
+ register unsigned int n = _root->children;
+#ifdef PUGOPT_NONSEG
+ const int namelen = _tcslen(name);
+#endif
+ for(register unsigned int i=0; i<n; ++i)
+ {
+ if
+ (
+ _root->child[i]->name &&
+#ifdef PUGOPT_NONSEG
+ matches_child_name(name,namelen,i)
+#else
+ matches_child_name(name,i)
+#endif
+ )
+ return _root->child[i];
+ }
+ return NULL;
+ }
+
+ //<summary>Map a child name to the index of the first instance, if found.</summary>
+ //<param name="name">Reference to name of child to find.</param>
+ //<returns>Index of child, or -1 if not found.</returns>
+ //<remarks>Implement your own hash table if you have a great many children.</remarks>
+ int mapto_child_idx(const std::string& name){ return mapto_child_idx(name.c_str()); }
+
+ //<summary>Map a child name to the index of the first instance, if found.</summary>
+ //<param name="name">Pointer to name of child to find.</param>
+ //<returns>Index of child, or -1 if not found.</returns>
+ //<remarks>Implement your own hash table if you have a great many children.</remarks>
+ int mapto_child_idx(const TCHAR* name)
+ {
+ if(!_root || !name) return -1;
+ register unsigned int n = _root->children;
+#ifdef PUGOPT_NONSEG
+ const int namelen = _tcslen(name);
+#endif
+ for(register unsigned int i=0; i<n; ++i)
+ {
+ if
+ (
+ _root->child[i]->name &&
+#ifdef PUGOPT_NONSEG
+ matches_child_name(name,namelen,i)
+#else
+ matches_child_name(name,i)
+#endif
+ )
+ return i;
+ }
+ return -1;
+ }
 
 //Traversal Helpers
 public:
 
- //<summary>Find all elements having the given name.</summary>
- //<param name="name">Reference to name of child to find.</param>
- //<param name="found">Reference to xml_node_list or pointer_array to receive the matching elements.
- void all_elements_by_name(const std::string& name,pointer_array& found){ all_elements_by_name(name.c_str(),found); }
-
- //<summary>Find all elements having the given name.</summary>
- //<param name="name">Pointer to name of child to find.</param>
- //<param name="found">Reference to xml_node_list or pointer_array to receive the matching elements.</param>
- void all_elements_by_name(const TCHAR* name,pointer_array& found)
- {
- if(empty() || !name) return; //Invalid node, so fail.
- if(_root->children > 0) //Has children.
- {
-#ifdef PUGOPT_NONSEG
- const unsigned int namelen = _tcslen(name);
-#endif
- register unsigned int n = _root->children; //For each child.
- for(register unsigned int i=0; i<n; ++i)
- {
- if
- (
- _root->child[i] && //There is a child at i.
- _root->child[i]->name && //The child has a name.
-#ifdef PUGOPT_NONSEG
- matches_child_name(name,namelen,i)
-#else
- matches_child_name(name,i)
-#endif
- )
- found.push_back(_root->child[i]); //push_back it to the array.
- if(_root->child[i]->children) //If there are children.
- {
- xml_node subsearch(_root->child[i]); //Wrap it up for ease.
- subsearch.all_elements_by_name(name,found); //Find any matching children.
- }
- }
- }
- }
-
- //<summary>
- // Recursively-implemented depth-first find the first matching element.
- // Use for shallow drill-downs.
- //</summary>
- //<param name="name">Const reference to name of element to find.</param>
- //<returns>Valid xml_node if such element named 'name' is found.</returns>
- //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
- xml_node first_element_by_name(const std::string& name){ return first_element_by_name(name.c_str()); }
-
- //<summary>
- // Recursively-implemented depth-first find the first matching element.
- // Use for shallow drill-downs.
- //</summary>
- //<param name="name">Pointer to name of element to find.</param>
- //<returns>Valid xml_node if such element named 'name' is found.</returns>
- //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
- xml_node first_element_by_name(const TCHAR* name)
- {
- if(empty() || !name) return xml_node(); //Invalid node, so fail.
- if(_root->children > 0) //Has children.
- {
- register unsigned int n = _root->children; //For each child.
-#ifdef PUGOPT_NONSEG
- const int namelen = _tcslen(name);
-#endif
- for(register unsigned int i=0; i<n; ++i)
- {
- if
- (
- _root->child[i]->name &&
-#ifdef PUGOPT_NONSEG
- matches_child_name(name,namelen,i)
-#else
- matches_child_name(name,i)
-#endif
- )
- return xml_node(_root->child[i]);
- else if(_root->child[i]->children)
- {
- xml_node subsearch(_root->child[i]); //Wrap it up for ease.
- xml_node found = subsearch.first_element_by_name(name);
- if(!found.empty()) return found; //Found.
- }
- }
- }
- return xml_node(); //Not found.
- }
-
- //<summary>
- // Recursively-implemented depth-first find the first matching element
- // also having matching PCDATA.
- //</summary>
- //<param name="name">Reference to name of element to find.</param>
- //<param name="value">Reference to PCDATA to find.</param>
- //<returns>Valid xml_node if such element named 'name' is found with PCDATA 'value'.</returns>
- //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
- xml_node first_element_by_value(const std::string& name,const std::string& value){ return first_element_by_value(name.c_str(),value.c_str()); }
-
- //<summary>
- // Recursively-implemented depth-first find the first matching element
- // also having matching PCDATA.
- //</summary>
- //<param name="name">Pointer to name of element to find.</param>
- //<param name="value">Pointer to PCDATA to find.</param>
- //<returns>Valid xml_node if such element named 'name' is found with PCDATA 'value'.</returns>
- //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
- xml_node first_element_by_value(const TCHAR* name,const TCHAR* value)
- {
- if(empty() || !name || !value) return xml_node(); //Invalid node, so fail.
- if(_root->children > 0) //Has children.
- {
- register unsigned int n = _root->children; //For each child.
-#ifdef PUGOPT_NONSEG
- const unsigned int namelen = _tcslen(name);
- const unsigned int valulen = _tcslen(value);
-#endif
- for(register unsigned int i=0; i<n; ++i)
- {
- if
- (
- _root->child[i] && //There is a child at i.
- _root->child[i]->name && //The child has a name.
-#ifdef PUGOPT_NONSEG
- matches_child_name(name,namelen,i)
-#else
- matches_child_name(name,i)
-#endif
- )
- {
- register unsigned int m = _root->child[i]->children; //For each child of child.
- for(register unsigned int j=0; j<m; ++j)
- {
- if
- (
- _root->child[i]->child[j] && //There is a child at j.
- _root->child[i]->child[j]->type == node_pcdata && //It is of the PCDATA type.
- _root->child[i]->child[j]->value && //It has data.
-#ifdef PUGOPT_NONSEG
- matches_value(value,valulen,_root->child[i]->child[j])
-#else
- matches_value(value,_root->child[i]->child[j])
-#endif
- )
- return xml_node(_root->child[i]); //Wrap it up and return.
- }
- }
- else if(_root->child[i] && _root->child[i]->children) //The child has children.
- {
- xml_node subsearch(_root->child[i]); //Wrap it up for ease.
- xml_node found = subsearch.first_element_by_value(name,value); //Search any children.
- if(!found.empty()) return found; //Found.
- }
- }
- }
- return xml_node(); //Not found.
- }
-
- //<summary>
- // Recursively-implemented depth-first find the first matching element
- // also having matching attribute.
- //</summary>
- //<param name="name">Reference to name of element to find.</param>
- //<param name="attr_name">Reference to name of attribute to find.</param>
- //<param name="attr_value">Reference to attribute value to find.</param>
- //<returns>Valid xml_node if such element named 'name' is found.</returns>
- //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
- xml_node first_element_by_attribute(const std::string& name,const std::string& attr_name,const std::string& attr_value){ return first_element_by_attribute(name.c_str(),attr_name.c_str(),attr_value.c_str()); }
-
- //<summary>
- // Recursively-implemented depth-first find the first matching element
- // also having matching attribute.
- //</summary>
- //<param name="name">Pointer to name of element to find.</param>
- //<param name="attr_name">Pointer to name of attribute to find.</param>
- //<param name="attr_value">Pointer to attribute value to find.</param>
- //<returns>Valid xml_node if such element named 'name' is found.</returns>
- //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
- xml_node first_element_by_attribute(const TCHAR* name,const TCHAR* attr_name,const TCHAR* attr_value)
- {
- if(empty() || !name || !attr_name || !attr_value) return xml_node(); //Invalid data, so fail.
- if(_root->children > 0) //Has children.
- {
-#ifdef PUGOPT_NONSEG
- const unsigned int namelen = _tcslen(name);
- const unsigned int attrlen = _tcslen(attr_name);
- const unsigned int valulen = _tcslen(attr_value);
-#endif
- register unsigned int n = _root->children; //For each child.
- for(register unsigned int i=0; i<n; ++i)
- {
- if
- (
- _root->child[i] && //There is a child at i.
- _root->child[i]->name && //The child has a name.
-#ifdef PUGOPT_NONSEG
- matches_name(name,namelen,_root->child[i])
-#else
- matches_name(name,_root->child[i])
-#endif
- )
- {
- register unsigned int m = _root->child[i]->attributes; //For each attribute of child.
- for(register unsigned int j=0; j<m; ++j)
- {
- if
- (
- _root->child[i]->attribute[j] && //There is an attribute at j.
- _root->child[i]->attribute[j]->name && //The attribute has a name.
-#ifdef PUGOPT_NONSEG
- matches_attribute_name(attr_name,attrlen,_root->child[i]->attribute[j]) &&
-#else
- matches_attribute_name(attr_name,_root->child[i]->attribute[j]) &&
-#endif
- _root->child[i]->attribute[j]->value && //The attribute has a value.
-#ifdef PUGOPT_NONSEG
- matches_attribute_name_value(attr_value,valulen,_root->child[i]->attribute[j])
-#else
- matches_attribute_name_value(attr_value,_root->child[i]->attribute[j])
-#endif
- )
- return xml_node(_root->child[i]); //Wrap it up and return.
- }
- }
- else if(_root->child[i] && _root->child[i]->children)
- {
- xml_node subsearch(_root->child[i]); //Wrap it up for ease.
- xml_node found = subsearch.first_element_by_attribute(name,attr_name,attr_value); //Search any children.
- if(!found.empty()) return found; //Found.
- }
- }
- }
- return xml_node(); //Not found.
- }
-
- //<summary>
- // Recursively-implemented depth-first find the first matching entity.
- // Use for shallow drill-downs.
- //</summary>
- //<param name="name">Pointer to name of element to find.</param>
- //<returns>Valid xml_node if such element named 'name' is found.</returns>
- //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
- xml_node first_node(xml_node_type type)
- {
- if(!_root) return xml_node();
- if(_root->children > 0) //Has children.
- {
- register unsigned int n = _root->children; //For each child.
- for(register unsigned int i=0; i<n; ++i)
- {
- if(_root->child[i]->type==type)
- return xml_node(_root->child[i]);
- else if(_root->child[i]->children)
- {
- xml_node subsearch(_root->child[i]);
- xml_node found = subsearch.first_node(type);
- if(!found.empty()) return found; //Found.
- }
- }
- }
- return xml_node(); //Not found.
- }
-
- //<summary>Move to the absolute root of the document tree.</summary>
- //<returns>True if the current node is valid.</returns>
- //<remarks>Member '_root' may now point to absolute root of the document.</remarks>
- bool moveto_root()
- {
- if(empty()) return false; //Nowhere to go.
- while(!type_document()) _root = _root->parent; //Keep stepping out until we hit the root.
- return true; //Success.
- }
-
- //<summary>Move to the current node's parent.</summary>
- //<returns>true if there is a parent and cursor is not parent, and cursor points thereto.</returns>
- //<remarks>'_root' may now point to parent.</remarks>
- bool moveto_parent()
- {
- if(empty() || type_document()) return false; //Invalid, or at the root (has no parent).
- _root = _root->parent; //Move to parent.
- return true; //Success.
- }
-
- //<summary>
- // Move to the current node's sibling at subscript. Equivalent to
- // 'moveto_child' following 'moveto_parent'.
- //</summary>
- //<param name="i">Subscript of sibling to move cursor to.</param>
- //<returns>True if valid subscript, and cursor points thereto.</returns>
- //<remarks>If matching co-node was found, '_root' points thereto.</remarks>
- bool moveto_sibling(unsigned int i)
- {
- if(empty()) return false; //Nowhere to go.
- xml_node_struct* restore = _root; //Save position in case invalid subscript & we want to restore.
- if(moveto_parent()) //Try to move to parent.
- {
- if(i < children()) //Subscript is in range. (Assume parent *does* have children.)
- {
- _root = _root->child[i]; //Move to child at subscript ('sibling').
- return true; //Success.
- }
- }
- _root = restore; //Bad subscript, or parent move; restore.
- return false;
- }
-
- //<summary>Move to the current node's first sibling matching given name.</summary>
- //<param name="name">Element name of sibling to move to.</param>
- //<returns>True if sibling was found, and cursor points thereto.</returns>
- //<remarks>If matching co-node was found, '_root' points thereto.</remarks>
- bool moveto_first_sibling(const std::string& name){ return moveto_first_sibling(name.c_str()); }
-
- //<summary>Move to the current node's first sibling matching given name.</summary>
- //<param name="name">Element name of sibling to move to.</param>
- //<returns>True if sibling was found, and cursor points thereto.</returns>
- //<remarks>If matching co-node was found, '_root' points thereto.</remarks>
- bool moveto_first_sibling(const TCHAR* name)
- {
- if(empty() || !name) return false; //Nowhere to go, or nothing to find.
- xml_node_struct* restore = _root; //Save position in case invalid subscript & we want to restore.
- if(moveto_parent()) //Try to move to parent.
- {
-#ifdef PUGOPT_NONSEG
- const unsigned int namelen = _tcslen(name);
-#endif
- register unsigned int n = children(); //Search for matching name
- for(register unsigned int i=0; i<n; ++i)
- {
- //NF 24 Jan 2003 Changed to get child(i) just once per iteration.
- xml_node node = child(i); //Access child node at subscript as xml_node or xml_node(NULL) if bad subscript.
- if(node.type_element()||node.type_pi()) //Other types won't have names.
- {
-#ifdef PUGOPT_NONSEG
- if(_tcsncmp(name,node.name(),max(namelen,node.name_size()))==0) //Do names match?
-#else
- if(strcmpwild(name,node.name())==0) //Do names match?
-#endif
- {
- _root = node; //Move there.
- return true; //Success.
- }
- }
- }
- }
- _root = restore; //Failed to locate any such sibling; restore position.
- return false;
- }
-
- //<summary>Move to the current node's child at subscript.</summary>
- //<param name="i">Subscript of child to move cursor to.</param>
- //<returns>true if valid subscript, and cursor points thereto.</returns>
- //<remarks>If matching sub-node was found, '_root' points thereto.</remarks>
- bool moveto_child(unsigned int i)
- {
- if(empty()) return false; //Null, so no children.
- if(has_child_nodes() && i < children()) //Has children and subscript is in bounds.
- {
- _root = child(i); //Move to the child at i.
- return true; //Success.
- }
- return false; //Failure.
- }
-
- //<summary>Move to the current node's child matching given name.</summary>
- //<param name="name">Element name of child to move to if found.</param>
- //<returns>True if child was found, and cursor points thereto.</returns>
- //<remarks>If matching sub-node was found, '_root' points thereto.</remarks>
- bool moveto_child(const std::string& name){ return moveto_child(name.c_str()); }
-
- //<summary>Move to the current node's child matching given name.</summary>
- //<param name="name">Element name of child to move to if found.</param>
- //<returns>True if child was found, and cursor points thereto.</returns>
- //<remarks>If matching sub-node was found, '_root' points thereto.</remarks>
- bool moveto_child(const TCHAR* name)
- {
- if(empty() || !name || !has_child_nodes()) return false; //The node is null, a name was not specified, or node has no children.
-#ifdef PUGOPT_NONSEG
- const unsigned int namelen = _tcslen(name);
-#endif
- register unsigned int n = children(); //For each child.
- for(register unsigned int i=0; i<n; ++i)
- {
- //NF 24 Jan 2003: Changed to get child(i) just once per iteration.
- xml_node node = child(i); //Access child node at subscript as xml_node or xml_node(NULL) if bad subscript.
-#ifdef PUGOPT_NONSEG
- if(_tcsncmp(name,node.name(),max(namelen,node.name_size()))==0) //Do names match?
-#else
- if(strcmpwild(name,node.name())==0) //If the name is identical with 'name'.
-#endif
- {
- _root = node; //Move to it.
- return true; //Success.
- }
- }
- return false; //Failure.
- }
-
- //<summary>Move to the current node's next sibling by position and name.</summary>
- //<param name="name">Name of sibling to move to if found.</param>
- //<returns>True if there is a next sibling, and cursor points thereto.</returns>
- bool moveto_next_sibling(const std::string& name){ return moveto_next_sibling(name.c_str()); }
-
- //<summary>Move to the current node's next sibling by position and name.</summary>
- //<param name="name">Name of sibling to move to if found.</param>
- //<returns>True if there is a next sibling, and cursor points thereto.</returns>
- bool moveto_next_sibling(const TCHAR* name)
- {
- if(empty() || type_document() || !_root->parent || !name) return false; //Null, or at root, or no name, so there are no valid matches.
-#ifdef PUGOPT_NONSEG
- const unsigned int namelen = _tcslen(name);
-#endif
- register unsigned int n = _root->parent->children; //For each child of parent.
- for(register unsigned int i=0; i<(n-1); ++i)
- {
- if
- (
- _root->parent->child[i] && //There is a child at i.
- _root->parent->child[i] == _root && //The child is identical with this node.
- i < (n-1) //This is not the last child.
- )
- {
- for(++i; i<n; ++i) //For each following child.
- {
- if
- (
- _root->parent->child[i] && //There is a child at i.
- _root->parent->child[i]->name && //The child's name is not null.
-#ifdef PUGOPT_NONSEG
- matches_name(name,namelen,_root->parent->child[i])
-#else
- matches_name(name,_root->parent->child[i])
-#endif
- )
- {
- moveto_sibling(i); //Move to it.
- return true; //Success.
- }
- }
- }
- }
- return false; //Failure.
- }
-
- //<summary>Move to the current node's next sibling by position.</summary>
- //<returns>True if there is a next sibling, and cursor points thereto.</returns>
- bool moveto_next_sibling()
- {
- if(empty() || type_document() || !_root->parent) return false; //Null or at root, so there are no valid siblings.
- register unsigned int n = _root->parent->children; //For each child of parent (each sibling).
- for(register unsigned int i=0; i<(n-1); ++i)
- {
- if
- (
- _root->parent->child[i] && //There is a child at i.
- _root->parent->child[i] == _root && //The child is identical with this node.
- i < (n-1) //This is not the last child.
- )
- {
- for(++i; i<n; ++i) //For each following child.
- {
- if(_root->parent->child[i]) //There is a child at i.
- {
- moveto_sibling(i); //Move to it.
- return true; //Success.
- }
- }
- }
- }
- return false; //Failure.
- }
-
- //<summary>Compile the absolute node path from root as a text string.</summary>
- //<param name="delimiter">Delimiter string to insert between element names.</param>
- //<returns>Path string (e.g. with '/' as delimiter, '/document/.../this'.</returns>
- std::string path(const TCHAR* delimiter = _T("/"))
- {
- TCHAR* path = NULL; //Current path.
- TCHAR* temp; //Temporary pointer.
- xml_node cursor = *this; //Make a copy.
-#ifdef PUGOPT_NONSEG
- unsigned int destlen = 0;
- strcatgrown_impl(&path,cursor.name(),destlen,cursor.name_size()); //Get this name.
-#else
- strcatgrow(&path,cursor.name()); //Get this name.
-#endif
- while(cursor.moveto_parent() && !cursor.type_document()) //Loop to parent (stopping on actual root because it has no name).
- {
- temp = NULL; //Mark as null so 'strcatgrow' will allocate memory.
-#ifdef PUGOPT_NONSEG
- destlen = 0;
- strcatgrown_impl(&temp,cursor.name(),destlen,cursor.name_size()); //Append next element name.
-#else
- strcatgrow(&temp,cursor.name()); //Append next element name.
-#endif
- strcatgrow(&temp,delimiter); //Append delimiter.
- strcatgrow(&temp,path); //Append current path.
- free(path); //Free the old path.
- path = temp; //Set path as new string.
- }
- temp = NULL;
- strcatgrow(&temp,delimiter); //Prepend final delimiter.
- strcatgrow(&temp,path); //Append current path.
- free(path); //Free the old path.
- std::string returns = temp; //Set path as new string.
- free(temp);
- return returns; //Return the path;
- }
-
- //<summary>Search for a node by path.</summary>
- //<param name="path">
- // Path string; e.g. './foo/bar' (relative to node), '/foo/bar' (relative
- // to root), '../foo/bar' (pop relative position).
- //</param>
- //<param name="delimiter">Delimiter string to use in tokenizing path.</param>
- //<returns>Matching node, or xml_node(NULL) if not found.</returns>
- xml_node first_element_by_path(const std::string& path,const std::string& delimiter = _T("/")){ return first_element_by_path(path.c_str(),delimiter.c_str()); }
-
- //<summary>Search for a node by path.</summary>
- //<param name="path">
- // Path string; e.g. './foo/bar' (relative to node), '/foo/bar' (relative
- // to root), '../foo/bar' (pop relative to position).
- //</param>
- //<param name="delimiter">Delimiter string to use in tokenizing path.</param>
- //<returns>Matching node, or xml_node(NULL) if not found.</returns>
- //<remarks>To-do: Support XPath-style queries.</remarks>
- xml_node first_element_by_path(const TCHAR* path,const TCHAR* delimiter = _T("/"))
- {
- if(!path) return xml_node();
- TCHAR* temp = NULL;
- pointer_array path_segments; //Array of path segments.
- xml_node found = *this; //Current search context.
- strcatgrow(&temp,path);
- TCHAR* name = _tcstok(temp,delimiter);
- while(name) //Tokenize the whole path.
- {
- path_segments.push_back((void*)name); //push_back it to array.
- name = _tcstok(NULL,delimiter); //Get the next token,
- }
- register unsigned int n = path_segments.size();
- if(n == 0) return xml_node(); //Return null node if no path segments.
- if(path[0]==delimiter[0]) found.moveto_root(); //Absolute path; e.g. '/foo/bar'
- for(register unsigned int i = 0; i<n; ++i) //For each path segment.
- {
- name = (TCHAR*)path_segments.at(i);
- if(name)
- {
- if(*name==_T('.')) //Is '.' or '..'
- {
- if(_tcscmp(name,_T(".."))==0) found.moveto_parent(); //Pop.
- else continue; //Ignore '.' since it is redundant if path is './path'.
- }
- else
- {
- register unsigned int j, m = found.children(); //For each child.
- for(j=0; j<m; ++j)
- {
- if(found.child(j).has_name(name)) //Name matches?
- {
- found = found.child(j); //Move to this child.
- goto NEXT_ELEM; //Search next path segment.
- }
- }
- if(found.moveto_next_sibling(found.name())) //Find next sibling having same name.
- {
- if(i > 0) --i; //Try the previous path segment.
- goto NEXT_ELEM;
- }
- else //Move to parent to search further.
- {
- if(!found.type_document() && found.moveto_parent() && !found.type_document()) //Not root and stepped to parent and parent is not root.
- {
- if(i > 0) --i; //Try the previous path segment.
- if(found.moveto_next_sibling(found.name())) //Try to find next sibling having same name.
- {
- if(i > 0) --i; //Try the previous path segment.
- goto NEXT_ELEM;
- }
- }
- }
- }
- }
+ //<summary>Find all elements having the given name.</summary>
+ //<param name="name">Reference to name of child to find.</param>
+ //<param name="found">Reference to xml_node_list or pointer_array to receive the matching elements.
+ void all_elements_by_name(const std::string& name,pointer_array& found){ all_elements_by_name(name.c_str(),found); }
+
+ //<summary>Find all elements having the given name.</summary>
+ //<param name="name">Pointer to name of child to find.</param>
+ //<param name="found">Reference to xml_node_list or pointer_array to receive the matching elements.</param>
+ void all_elements_by_name(const TCHAR* name,pointer_array& found)
+ {
+ if(empty() || !name) return; //Invalid node, so fail.
+ if(_root->children > 0) //Has children.
+ {
+#ifdef PUGOPT_NONSEG
+ const unsigned int namelen = _tcslen(name);
+#endif
+ register unsigned int n = _root->children; //For each child.
+ for(register unsigned int i=0; i<n; ++i)
+ {
+ if
+ (
+ _root->child[i] && //There is a child at i.
+ _root->child[i]->name && //The child has a name.
+#ifdef PUGOPT_NONSEG
+ matches_child_name(name,namelen,i)
+#else
+ matches_child_name(name,i)
+#endif
+ )
+ found.push_back(_root->child[i]); //push_back it to the array.
+ if(_root->child[i]->children) //If there are children.
+ {
+ xml_node subsearch(_root->child[i]); //Wrap it up for ease.
+ subsearch.all_elements_by_name(name,found); //Find any matching children.
+ }
+ }
+ }
+ }
+
+ //<summary>
+ // Recursively-implemented depth-first find the first matching element.
+ // Use for shallow drill-downs.
+ //</summary>
+ //<param name="name">Const reference to name of element to find.</param>
+ //<returns>Valid xml_node if such element named 'name' is found.</returns>
+ //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
+ xml_node first_element_by_name(const std::string& name){ return first_element_by_name(name.c_str()); }
+
+ //<summary>
+ // Recursively-implemented depth-first find the first matching element.
+ // Use for shallow drill-downs.
+ //</summary>
+ //<param name="name">Pointer to name of element to find.</param>
+ //<returns>Valid xml_node if such element named 'name' is found.</returns>
+ //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
+ xml_node first_element_by_name(const TCHAR* name)
+ {
+ if(empty() || !name) return xml_node(); //Invalid node, so fail.
+ if(_root->children > 0) //Has children.
+ {
+ register unsigned int n = _root->children; //For each child.
+#ifdef PUGOPT_NONSEG
+ const int namelen = _tcslen(name);
+#endif
+ for(register unsigned int i=0; i<n; ++i)
+ {
+ if
+ (
+ _root->child[i]->name &&
+#ifdef PUGOPT_NONSEG
+ matches_child_name(name,namelen,i)
+#else
+ matches_child_name(name,i)
+#endif
+ )
+ return xml_node(_root->child[i]);
+ else if(_root->child[i]->children)
+ {
+ xml_node subsearch(_root->child[i]); //Wrap it up for ease.
+ xml_node found = subsearch.first_element_by_name(name);
+ if(!found.empty()) return found; //Found.
+ }
+ }
+ }
+ return xml_node(); //Not found.
+ }
+
+ //<summary>
+ // Recursively-implemented depth-first find the first matching element
+ // also having matching PCDATA.
+ //</summary>
+ //<param name="name">Reference to name of element to find.</param>
+ //<param name="value">Reference to PCDATA to find.</param>
+ //<returns>Valid xml_node if such element named 'name' is found with PCDATA 'value'.</returns>
+ //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
+ xml_node first_element_by_value(const std::string& name,const std::string& value){ return first_element_by_value(name.c_str(),value.c_str()); }
+
+ //<summary>
+ // Recursively-implemented depth-first find the first matching element
+ // also having matching PCDATA.
+ //</summary>
+ //<param name="name">Pointer to name of element to find.</param>
+ //<param name="value">Pointer to PCDATA to find.</param>
+ //<returns>Valid xml_node if such element named 'name' is found with PCDATA 'value'.</returns>
+ //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
+ xml_node first_element_by_value(const TCHAR* name,const TCHAR* value)
+ {
+ if(empty() || !name || !value) return xml_node(); //Invalid node, so fail.
+ if(_root->children > 0) //Has children.
+ {
+ register unsigned int n = _root->children; //For each child.
+#ifdef PUGOPT_NONSEG
+ const unsigned int namelen = _tcslen(name);
+ const unsigned int valulen = _tcslen(value);
+#endif
+ for(register unsigned int i=0; i<n; ++i)
+ {
+ if
+ (
+ _root->child[i] && //There is a child at i.
+ _root->child[i]->name && //The child has a name.
+#ifdef PUGOPT_NONSEG
+ matches_child_name(name,namelen,i)
+#else
+ matches_child_name(name,i)
+#endif
+ )
+ {
+ register unsigned int m = _root->child[i]->children; //For each child of child.
+ for(register unsigned int j=0; j<m; ++j)
+ {
+ if
+ (
+ _root->child[i]->child[j] && //There is a child at j.
+ _root->child[i]->child[j]->type == node_pcdata && //It is of the PCDATA type.
+ _root->child[i]->child[j]->value && //It has data.
+#ifdef PUGOPT_NONSEG
+ matches_value(value,valulen,_root->child[i]->child[j])
+#else
+ matches_value(value,_root->child[i]->child[j])
+#endif
+ )
+ return xml_node(_root->child[i]); //Wrap it up and return.
+ }
+ }
+ else if(_root->child[i] && _root->child[i]->children) //The child has children.
+ {
+ xml_node subsearch(_root->child[i]); //Wrap it up for ease.
+ xml_node found = subsearch.first_element_by_value(name,value); //Search any children.
+ if(!found.empty()) return found; //Found.
+ }
+ }
+ }
+ return xml_node(); //Not found.
+ }
+
+ //<summary>
+ // Recursively-implemented depth-first find the first matching element
+ // also having matching attribute.
+ //</summary>
+ //<param name="name">Reference to name of element to find.</param>
+ //<param name="attr_name">Reference to name of attribute to find.</param>
+ //<param name="attr_value">Reference to attribute value to find.</param>
+ //<returns>Valid xml_node if such element named 'name' is found.</returns>
+ //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
+ xml_node first_element_by_attribute(const std::string& name,const std::string& attr_name,const std::string& attr_value){ return first_element_by_attribute(name.c_str(),attr_name.c_str(),attr_value.c_str()); }
+
+ //<summary>
+ // Recursively-implemented depth-first find the first matching element
+ // also having matching attribute.
+ //</summary>
+ //<param name="name">Pointer to name of element to find.</param>
+ //<param name="attr_name">Pointer to name of attribute to find.</param>
+ //<param name="attr_value">Pointer to attribute value to find.</param>
+ //<returns>Valid xml_node if such element named 'name' is found.</returns>
+ //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
+ xml_node first_element_by_attribute(const TCHAR* name,const TCHAR* attr_name,const TCHAR* attr_value)
+ {
+ if(empty() || !name || !attr_name || !attr_value) return xml_node(); //Invalid data, so fail.
+ if(_root->children > 0) //Has children.
+ {
+#ifdef PUGOPT_NONSEG
+ const unsigned int namelen = _tcslen(name);
+ const unsigned int attrlen = _tcslen(attr_name);
+ const unsigned int valulen = _tcslen(attr_value);
+#endif
+ register unsigned int n = _root->children; //For each child.
+ for(register unsigned int i=0; i<n; ++i)
+ {
+ if
+ (
+ _root->child[i] && //There is a child at i.
+ _root->child[i]->name && //The child has a name.
+#ifdef PUGOPT_NONSEG
+ matches_name(name,namelen,_root->child[i])
+#else
+ matches_name(name,_root->child[i])
+#endif
+ )
+ {
+ register unsigned int m = _root->child[i]->attributes; //For each attribute of child.
+ for(register unsigned int j=0; j<m; ++j)
+ {
+ if
+ (
+ _root->child[i]->attribute[j] && //There is an attribute at j.
+ _root->child[i]->attribute[j]->name && //The attribute has a name.
+#ifdef PUGOPT_NONSEG
+ matches_attribute_name(attr_name,attrlen,_root->child[i]->attribute[j]) &&
+#else
+ matches_attribute_name(attr_name,_root->child[i]->attribute[j]) &&
+#endif
+ _root->child[i]->attribute[j]->value && //The attribute has a value.
+#ifdef PUGOPT_NONSEG
+ matches_attribute_name_value(attr_value,valulen,_root->child[i]->attribute[j])
+#else
+ matches_attribute_name_value(attr_value,_root->child[i]->attribute[j])
+#endif
+ )
+ return xml_node(_root->child[i]); //Wrap it up and return.
+ }
+ }
+ else if(_root->child[i] && _root->child[i]->children)
+ {
+ xml_node subsearch(_root->child[i]); //Wrap it up for ease.
+ xml_node found = subsearch.first_element_by_attribute(name,attr_name,attr_value); //Search any children.
+ if(!found.empty()) return found; //Found.
+ }
+ }
+ }
+ return xml_node(); //Not found.
+ }
+
+ //<summary>
+ // Recursively-implemented depth-first find the first matching entity.
+ // Use for shallow drill-downs.
+ //</summary>
+ //<param name="name">Pointer to name of element to find.</param>
+ //<returns>Valid xml_node if such element named 'name' is found.</returns>
+ //<remarks>xml_node may be invalid if not found; test with 'empty'.</remarks>
+ xml_node first_node(xml_node_type type)
+ {
+ if(!_root) return xml_node();
+ if(_root->children > 0) //Has children.
+ {
+ register unsigned int n = _root->children; //For each child.
+ for(register unsigned int i=0; i<n; ++i)
+ {
+ if(_root->child[i]->type==type)
+ return xml_node(_root->child[i]);
+ else if(_root->child[i]->children)
+ {
+ xml_node subsearch(_root->child[i]);
+ xml_node found = subsearch.first_node(type);
+ if(!found.empty()) return found; //Found.
+ }
+ }
+ }
+ return xml_node(); //Not found.
+ }
+
+ //<summary>Move to the absolute root of the document tree.</summary>
+ //<returns>True if the current node is valid.</returns>
+ //<remarks>Member '_root' may now point to absolute root of the document.</remarks>
+ bool moveto_root()
+ {
+ if(empty()) return false; //Nowhere to go.
+ while(!type_document()) _root = _root->parent; //Keep stepping out until we hit the root.
+ return true; //Success.
+ }
+
+ //<summary>Move to the current node's parent.</summary>
+ //<returns>true if there is a parent and cursor is not parent, and cursor points thereto.</returns>
+ //<remarks>'_root' may now point to parent.</remarks>
+ bool moveto_parent()
+ {
+ if(empty() || type_document()) return false; //Invalid, or at the root (has no parent).
+ _root = _root->parent; //Move to parent.
+ return true; //Success.
+ }
+
+ //<summary>
+ // Move to the current node's sibling at subscript. Equivalent to
+ // 'moveto_child' following 'moveto_parent'.
+ //</summary>
+ //<param name="i">Subscript of sibling to move cursor to.</param>
+ //<returns>True if valid subscript, and cursor points thereto.</returns>
+ //<remarks>If matching co-node was found, '_root' points thereto.</remarks>
+ bool moveto_sibling(unsigned int i)
+ {
+ if(empty()) return false; //Nowhere to go.
+ xml_node_struct* restore = _root; //Save position in case invalid subscript & we want to restore.
+ if(moveto_parent()) //Try to move to parent.
+ {
+ if(i < children()) //Subscript is in range. (Assume parent *does* have children.)
+ {
+ _root = _root->child[i]; //Move to child at subscript ('sibling').
+ return true; //Success.
+ }
+ }
+ _root = restore; //Bad subscript, or parent move; restore.
+ return false;
+ }
+
+ //<summary>Move to the current node's first sibling matching given name.</summary>
+ //<param name="name">Element name of sibling to move to.</param>
+ //<returns>True if sibling was found, and cursor points thereto.</returns>
+ //<remarks>If matching co-node was found, '_root' points thereto.</remarks>
+ bool moveto_first_sibling(const std::string& name){ return moveto_first_sibling(name.c_str()); }
+
+ //<summary>Move to the current node's first sibling matching given name.</summary>
+ //<param name="name">Element name of sibling to move to.</param>
+ //<returns>True if sibling was found, and cursor points thereto.</returns>
+ //<remarks>If matching co-node was found, '_root' points thereto.</remarks>
+ bool moveto_first_sibling(const TCHAR* name)
+ {
+ if(empty() || !name) return false; //Nowhere to go, or nothing to find.
+ xml_node_struct* restore = _root; //Save position in case invalid subscript & we want to restore.
+ if(moveto_parent()) //Try to move to parent.
+ {
+#ifdef PUGOPT_NONSEG
+ const unsigned int namelen = _tcslen(name);
+#endif
+ register unsigned int n = children(); //Search for matching name
+ for(register unsigned int i=0; i<n; ++i)
+ {
+ //NF 24 Jan 2003 Changed to get child(i) just once per iteration.
+ xml_node node = child(i); //Access child node at subscript as xml_node or xml_node(NULL) if bad subscript.
+ if(node.type_element()||node.type_pi()) //Other types won't have names.
+ {
+#ifdef PUGOPT_NONSEG
+ if(_tcsncmp(name,node.name(),(std::max)(namelen,node.name_size()))==0) //Do names match?
+#else
+ if(strcmpwild(name,node.name())==0) //Do names match?
+#endif
+ {
+ _root = node; //Move there.
+ return true; //Success.
+ }
+ }
+ }
+ }
+ _root = restore; //Failed to locate any such sibling; restore position.
+ return false;
+ }
+
+ //<summary>Move to the current node's child at subscript.</summary>
+ //<param name="i">Subscript of child to move cursor to.</param>
+ //<returns>true if valid subscript, and cursor points thereto.</returns>
+ //<remarks>If matching sub-node was found, '_root' points thereto.</remarks>
+ bool moveto_child(unsigned int i)
+ {
+ if(empty()) return false; //Null, so no children.
+ if(has_child_nodes() && i < children()) //Has children and subscript is in bounds.
+ {
+ _root = child(i); //Move to the child at i.
+ return true; //Success.
+ }
+ return false; //Failure.
+ }
+
+ //<summary>Move to the current node's child matching given name.</summary>
+ //<param name="name">Element name of child to move to if found.</param>
+ //<returns>True if child was found, and cursor points thereto.</returns>
+ //<remarks>If matching sub-node was found, '_root' points thereto.</remarks>
+ bool moveto_child(const std::string& name){ return moveto_child(name.c_str()); }
+
+ //<summary>Move to the current node's child matching given name.</summary>
+ //<param name="name">Element name of child to move to if found.</param>
+ //<returns>True if child was found, and cursor points thereto.</returns>
+ //<remarks>If matching sub-node was found, '_root' points thereto.</remarks>
+ bool moveto_child(const TCHAR* name)
+ {
+ if(empty() || !name || !has_child_nodes()) return false; //The node is null, a name was not specified, or node has no children.
+#ifdef PUGOPT_NONSEG
+ const unsigned int namelen = _tcslen(name);
+#endif
+ register unsigned int n = children(); //For each child.
+ for(register unsigned int i=0; i<n; ++i)
+ {
+ //NF 24 Jan 2003: Changed to get child(i) just once per iteration.
+ xml_node node = child(i); //Access child node at subscript as xml_node or xml_node(NULL) if bad subscript.
+#ifdef PUGOPT_NONSEG
+ if(_tcsncmp(name,node.name(),(std::max)(namelen,node.name_size()))==0) //Do names match?
+#else
+ if(strcmpwild(name,node.name())==0) //If the name is identical with 'name'.
+#endif
+ {
+ _root = node; //Move to it.
+ return true; //Success.
+ }
+ }
+ return false; //Failure.
+ }
+
+ //<summary>Move to the current node's next sibling by position and name.</summary>
+ //<param name="name">Name of sibling to move to if found.</param>
+ //<returns>True if there is a next sibling, and cursor points thereto.</returns>
+ bool moveto_next_sibling(const std::string& name){ return moveto_next_sibling(name.c_str()); }
+
+ //<summary>Move to the current node's next sibling by position and name.</summary>
+ //<param name="name">Name of sibling to move to if found.</param>
+ //<returns>True if there is a next sibling, and cursor points thereto.</returns>
+ bool moveto_next_sibling(const TCHAR* name)
+ {
+ if(empty() || type_document() || !_root->parent || !name) return false; //Null, or at root, or no name, so there are no valid matches.
+#ifdef PUGOPT_NONSEG
+ const unsigned int namelen = _tcslen(name);
+#endif
+ register unsigned int n = _root->parent->children; //For each child of parent.
+ for(register unsigned int i=0; i<(n-1); ++i)
+ {
+ if
+ (
+ _root->parent->child[i] && //There is a child at i.
+ _root->parent->child[i] == _root && //The child is identical with this node.
+ i < (n-1) //This is not the last child.
+ )
+ {
+ for(++i; i<n; ++i) //For each following child.
+ {
+ if
+ (
+ _root->parent->child[i] && //There is a child at i.
+ _root->parent->child[i]->name && //The child's name is not null.
+#ifdef PUGOPT_NONSEG
+ matches_name(name,namelen,_root->parent->child[i])
+#else
+ matches_name(name,_root->parent->child[i])
+#endif
+ )
+ {
+ moveto_sibling(i); //Move to it.
+ return true; //Success.
+ }
+ }
+ }
+ }
+ return false; //Failure.
+ }
+
+ //<summary>Move to the current node's next sibling by position.</summary>
+ //<returns>True if there is a next sibling, and cursor points thereto.</returns>
+ bool moveto_next_sibling()
+ {
+ if(empty() || type_document() || !_root->parent) return false; //Null or at root, so there are no valid siblings.
+ register unsigned int n = _root->parent->children; //For each child of parent (each sibling).
+ for(register unsigned int i=0; i<(n-1); ++i)
+ {
+ if
+ (
+ _root->parent->child[i] && //There is a child at i.
+ _root->parent->child[i] == _root && //The child is identical with this node.
+ i < (n-1) //This is not the last child.
+ )
+ {
+ for(++i; i<n; ++i) //For each following child.
+ {
+ if(_root->parent->child[i]) //There is a child at i.
+ {
+ moveto_sibling(i); //Move to it.
+ return true; //Success.
+ }
+ }
+ }
+ }
+ return false; //Failure.
+ }
+
+ //<summary>Compile the absolute node path from root as a text string.</summary>
+ //<param name="delimiter">Delimiter string to insert between element names.</param>
+ //<returns>Path string (e.g. with '/' as delimiter, '/document/.../this'.</returns>
+ std::string path(const TCHAR* delimiter = _T("/"))
+ {
+ TCHAR* path = NULL; //Current path.
+ TCHAR* temp; //Temporary pointer.
+ xml_node cursor = *this; //Make a copy.
+#ifdef PUGOPT_NONSEG
+ unsigned int destlen = 0;
+ strcatgrown_impl(&path,cursor.name(),destlen,cursor.name_size()); //Get this name.
+#else
+ strcatgrow(&path,cursor.name()); //Get this name.
+#endif
+ while(cursor.moveto_parent() && !cursor.type_document()) //Loop to parent (stopping on actual root because it has no name).
+ {
+ temp = NULL; //Mark as null so 'strcatgrow' will allocate memory.
+#ifdef PUGOPT_NONSEG
+ destlen = 0;
+ strcatgrown_impl(&temp,cursor.name(),destlen,cursor.name_size()); //Append next element name.
+#else
+ strcatgrow(&temp,cursor.name()); //Append next element name.
+#endif
+ strcatgrow(&temp,delimiter); //Append delimiter.
+ strcatgrow(&temp,path); //Append current path.
+ free(path); //Free the old path.
+ path = temp; //Set path as new string.
+ }
+ temp = NULL;
+ strcatgrow(&temp,delimiter); //Prepend final delimiter.
+ strcatgrow(&temp,path); //Append current path.
+ free(path); //Free the old path.
+ std::string returns = temp; //Set path as new string.
+ free(temp);
+ return returns; //Return the path;
+ }
+
+ //<summary>Search for a node by path.</summary>
+ //<param name="path">
+ // Path string; e.g. './foo/bar' (relative to node), '/foo/bar' (relative
+ // to root), '../foo/bar' (pop relative position).
+ //</param>
+ //<param name="delimiter">Delimiter string to use in tokenizing path.</param>
+ //<returns>Matching node, or xml_node(NULL) if not found.</returns>
+ xml_node first_element_by_path(const std::string& path,const std::string& delimiter = _T("/")){ return first_element_by_path(path.c_str(),delimiter.c_str()); }
+
+ //<summary>Search for a node by path.</summary>
+ //<param name="path">
+ // Path string; e.g. './foo/bar' (relative to node), '/foo/bar' (relative
+ // to root), '../foo/bar' (pop relative to position).
+ //</param>
+ //<param name="delimiter">Delimiter string to use in tokenizing path.</param>
+ //<returns>Matching node, or xml_node(NULL) if not found.</returns>
+ //<remarks>To-do: Support XPath-style queries.</remarks>
+ xml_node first_element_by_path(const TCHAR* path,const TCHAR* delimiter = _T("/"))
+ {
+ if(!path) return xml_node();
+ TCHAR* temp = NULL;
+ pointer_array path_segments; //Array of path segments.
+ xml_node found = *this; //Current search context.
+ strcatgrow(&temp,path);
+ TCHAR* name = _tcstok(temp,delimiter);
+ while(name) //Tokenize the whole path.
+ {
+ path_segments.push_back((void*)name); //push_back it to array.
+ name = _tcstok(NULL,delimiter); //Get the next token,
+ }
+ register unsigned int n = path_segments.size();
+ if(n == 0) return xml_node(); //Return null node if no path segments.
+ if(path[0]==delimiter[0]) found.moveto_root(); //Absolute path; e.g. '/foo/bar'
+ for(register unsigned int i = 0; i<n; ++i) //For each path segment.
+ {
+ name = (TCHAR*)path_segments.at(i);
+ if(name)
+ {
+ if(*name==_T('.')) //Is '.' or '..'
+ {
+ if(_tcscmp(name,_T(".."))==0) found.moveto_parent(); //Pop.
+ else continue; //Ignore '.' since it is redundant if path is './path'.
+ }
+ else
+ {
+ register unsigned int j, m = found.children(); //For each child.
+ for(j=0; j<m; ++j)
+ {
+ if(found.child(j).has_name(name)) //Name matches?
+ {
+ found = found.child(j); //Move to this child.
+ goto NEXT_ELEM; //Search next path segment.
+ }
+ }
+ if(found.moveto_next_sibling(found.name())) //Find next sibling having same name.
+ {
+ if(i > 0) --i; //Try the previous path segment.
+ goto NEXT_ELEM;
+ }
+ else //Move to parent to search further.
+ {
+ if(!found.type_document() && found.moveto_parent() && !found.type_document()) //Not root and stepped to parent and parent is not root.
+ {
+ if(i > 0) --i; //Try the previous path segment.
+ if(found.moveto_next_sibling(found.name())) //Try to find next sibling having same name.
+ {
+ if(i > 0) --i; //Try the previous path segment.
+ goto NEXT_ELEM;
+ }
+ }
+ }
+ }
+ }
 NEXT_ELEM:;
- if(found.type_document()) //Can't move up any higher, so fail.
- {
- free(temp); //Got to free this.
- return xml_node(); //Return null node.
- }
- }
- free(temp); //Got to free this.
- return found; //Return the matching node.
- }
-
- //<summary>Recursively traverse the tree.</summary>
- //<param name="walker">Reference to tree walker derived from xml_tree_walker.</param>
- //<returns>True if traversal was not halted by xml_tree_walker::for_each() callback.</returns>
- bool traverse(xml_tree_walker& walker)
- {
- if(walker.depth() == 0 && !walker.begin(*this)) return false; //Send the callback for begin traverse if depth is zero.
- if(!empty()) //Don't traveres if this is a null node.
- {
- walker.push(); //Increment the walker depth counter.
- register unsigned int n = _root->children; //For each child.
- for(register unsigned int i=0; i<n; ++i)
- {
- if(_root->child[i]) //There is a child at i.
- {
- xml_node subsearch(_root->child[i]); //Wrap it.
- if(!(walker.for_each(subsearch) && subsearch.traverse(walker)))
- return false; //Traversal was aborted.
- }
- }
- walker.pop(); //Decrement the walker depth counter.
- }
- if(walker.depth() == 0 && !walker.end(*this)) return false; //Send the callback for end traverse if depth is zero.
- return true;
- }
+ if(found.type_document()) //Can't move up any higher, so fail.
+ {
+ free(temp); //Got to free this.
+ return xml_node(); //Return null node.
+ }
+ }
+ free(temp); //Got to free this.
+ return found; //Return the matching node.
+ }
+
+ //<summary>Recursively traverse the tree.</summary>
+ //<param name="walker">Reference to tree walker derived from xml_tree_walker.</param>
+ //<returns>True if traversal was not halted by xml_tree_walker::for_each() callback.</returns>
+ bool traverse(xml_tree_walker& walker)
+ {
+ if(walker.depth() == 0 && !walker.begin(*this)) return false; //Send the callback for begin traverse if depth is zero.
+ if(!empty()) //Don't traveres if this is a null node.
+ {
+ walker.push(); //Increment the walker depth counter.
+ register unsigned int n = _root->children; //For each child.
+ for(register unsigned int i=0; i<n; ++i)
+ {
+ if(_root->child[i]) //There is a child at i.
+ {
+ xml_node subsearch(_root->child[i]); //Wrap it.
+ if(!(walker.for_each(subsearch) && subsearch.traverse(walker)))
+ return false; //Traversal was aborted.
+ }
+ }
+ walker.pop(); //Decrement the walker depth counter.
+ }
+ if(walker.depth() == 0 && !walker.end(*this)) return false; //Send the callback for end traverse if depth is zero.
+ return true;
+ }
 
 //Editorial Helpers
 public:
 
- //<summary>Set element name.</summary>
- //<param name="new_name">New element name.</param>
- //<returns>Success.</returns>
- bool name(const std::string& new_name){ return name(new_name.c_str()); }
-
- //<summary>Set element name.</summary>
- //<param name="new_name">New element name.</param>
- //<returns>Success.</returns>
- bool name(const TCHAR* new_name)
- {
- if((type_element() || type_pi()) && new_name)
-#ifdef PUGOPT_NONSEG
- return strcpyinsitu(&_root->name,new_name,&_root->name_insitu,_root->name_size );
-#else
- return strcpyinsitu(&_root->name,new_name,&_root->name_insitu);
-#endif
- return false;
- }
-
- //<summary>Set node data.</summary>
- //<param name="value">New data (PCDATA, CDATA, or comment) value.</param>
- //<returns>Success.</returns>
- bool value(const std::string& new_value){ return value(new_value.c_str()); }
-
- //<summary>Set node data.</summary>
- //<param name="value">New data (PCDATA, CDATA, or comment) value.</param>
- //<returns>Success.</returns>
- bool value(const TCHAR* new_value)
- {
- if((type_pcdata() || type_cdata() || type_comment()) && new_value)
-#ifdef PUGOPT_NONSEG
- return strcpyinsitu(&_root->value,new_value,&_root->value_insitu,_root->value_size);
-#else
- return strcpyinsitu(&_root->value,new_value,&_root->value_insitu);
-#endif
- return false;
- }
-
- //<summary>Remove attribute at the given subscript.</summary>
- //<param name="i">Subscript.</param>
- //<returns>Success.</returns>
- bool remove_attribute(unsigned int i)
- {
- unsigned int n = _root->attributes;
- if(i < n)
- {
- xml_attribute_struct* temp = _root->attribute[i];
- --n;
- for(unsigned int j=i; j<n; ++j)
- _root->attribute[j] = _root->attribute[j+1];
- _root->attribute[n] = NULL;
- if(!temp->name_insitu) free(temp->name);
- if(!temp->value_insitu) free(temp->value);
- free(temp);
- --_root->attributes;
- return true;
- }
- return false;
- }
-
- //<summary>Remove attribute having the given name.</summary>
- //<param name="name">Name of attribute to delete.</param>
- //<returns>Success.</returns>
- bool remove_attribute(const std::string& name){ return remove_attribute(name.c_str()); }
-
- //<summary>Remove attribute having the given name.</summary>
- //<param name="name">Name of attribute to delete.</param>
- //<returns>Success.</returns>
- bool remove_attribute(const TCHAR* name)
- {
- int i = mapto_attribute_idx(name);
- if(i > -1) return remove_attribute((unsigned int)i);
- return false;
- }
-
- //<summary>Append a new attribute to the node list of attributes.</summary>
- //<param name="name">Name.</param>
- //<param name="value">Value thereof.</param>
- //<returns>Attribute structure wrapper.</returns>
- //<remarks>Pointer space may be grown, memory for name/value members allocated.</remarks>
- xml_attribute append_attribute(const std::string& name,const std::string& value){ return append_attribute(name.c_str(),value.c_str()); }
-
- //<summary>Append a new attribute to the node list of attributes.</summary>
- //<param name="name">Name.</param>
- //<param name="value">Value thereof.</param>
- //<returns>Attribute structure wrapper.</returns>
- //<remarks>Pointer space may be grown, memory for name/value members allocated.</remarks>
- xml_attribute append_attribute(const TCHAR* name,const TCHAR* value)
- {
- if(!name || !value) return xml_attribute(); //We must have both to proceed.
- xml_attribute_struct* p = pug::append_attribute(_root,1); //Append/allocate a new attribute structure.
- if(p) //If append/allocate succeeded.
- {
-#ifdef PUGOPT_NONSEG
- strcatgrown(&p->name,name,p->name_size); //Append the name.
- strcatgrown(&p->value,value,p->value_size); //Append the name.
-#else
- strcatgrow(&p->name,name); //Append the name.
- strcatgrow(&p->value,value); //Append the name.
-#endif
- p->name_insitu = p->value_insitu = false; //Mark as not part of original parse string.
- return xml_attribute(p); //Success.
- }
- return xml_attribute(); //Failure; return an empty.
- }
-
- //<summary>Append a new attribute of type long to the node list of attributes.</summary>
- //<param name="name">Name.</param>
- //<param name="value">Value thereof.</param>
- //<returns>Attribute structure wrapper.</returns>
- //<remarks>Pointer space may be grown, memory for name/value members allocated.</remarks>
- xml_attribute append_attribute(const TCHAR* name,long value)
- {
- if(!name) return false;
- TCHAR temp[32] = {0};
- _stprintf(temp,_T("%ld"),value);
- return append_attribute(name,temp);
- }
-
- //<summary>Append a new attribute of type double to the node list of attributes.</summary>
- //<param name="name">Name.</param>
- //<param name="value">Value thereof.</param>
- //<returns>Attribute structure wrapper.</returns>
- //<remarks>Pointer space may be grown, memory for name/value members allocated.</remarks>
- xml_attribute append_attribute(const TCHAR* name,double value)
- {
- if(!name) return false;
- TCHAR temp[32] = {0};
- _stprintf(temp,_T("%lf"),value);
- return append_attribute(name,temp);
- }
-
- //<summary>Append a new attribute of type bool to the node list of attributes.</summary>
- //<param name="name">Name.</param>
- //<param name="value">Value thereof.</param>
- //<returns>Attribute structure wrapper.</returns>
- //<remarks>Pointer space may be grown, memory for name/value members allocated.</remarks>
- xml_attribute append_attribute(const TCHAR* name,bool value)
- {
- if(!name) return false;
- return append_attribute(name,((value)?_T("true"):_T("false")));
- }
-
- //<summary>Set the current node entity type.</summary>
- //<param name="new_type">New type to set.</param>
- //<returns>Previous type.</returns>
- //<remarks>If has children and now is not node_element, children are obscured.</remarks>
- xml_node_type type(xml_node_type new_type)
- {
- xml_node_type prev = _root->type; //Save old type.
- _root->type = new_type; //Set new type.
- return prev; //Return old type.
- }
-
- //<summary>
- // Allocate & append a child node of the given type at the end of the
- // current node array of children.
- //</summary>
- //<param name="type">New child node type.</param>
- //<returns>xml_node wrapping the new child.</returns>
- //<remarks>Pointer space may be grown. An xml_node_struct structure is allocated.</remarks>
- xml_node append_child(xml_node_type type)
- {
- if(type_document()||type_element()) //Don't do anything if not an node_element or root.
- {
- xml_node_struct* p = pug::append_node(_root,1,type); //Append the node.
- if(p)
- {
- p->name_insitu = p->value_insitu = false;
- return xml_node(p); //If we have it, return wrapped.
- }
- }
- return xml_node(); //Return dummy.
- }
-
- //<summary>Allocate & insert a child node of the given type at subscript.</summary>
- //<param name="i">Subscript at which to insert.</param>
- //<param name="type">New child node type.</param>
- //<returns>xml_node wrapping the new child.</returns>
- //<remarks>
- // Pointer space may be grown. An xml_node_struct structure is allocated,
- // and existing children are shifted in their array position.
- //</remarks>
- xml_node insert_child(unsigned int i,xml_node_type type)
- {
- if(!type_element()) return xml_node(); //Don't do anything if not an node_element.
- unsigned int n = _root->children; //Get count of existing children.
- if(type_element() && i >= n) return append_child(type); //If subscript at end of array then just append.
- else if(type_element() && i < n)
- {
- xml_node_struct* p = pug::append_node(_root,1,type); //Append the new node (by default at last array position).
- if(p) //Ensure we have it.
- {
- register int m = (i-1); //Stop at i.
- for(register int j=(n-1); j>m; --j) //Starting at one less than end of array, reverse loop to i.
- _root->child[j+1] = _root->child[j]; //Shift node to right.
- _root->child[i] = p; //Set node at subscript to new node.
- return xml_node(p); //Return new node.
- }
- }
- return xml_node(); //Return dummy.
- }
-
- //<summary>Delete the child node at the given subscript.</summary>
- //<param name="i">Subscript.</param>
- //<returns>Success.</returns>
- //<remarks>Shifts child array element positions. Frees entire tree under child to be deleted.</remarks>
- bool remove_child(unsigned int i)
- {
- unsigned int n = _root->children;
- if(i < n) //Ensure subscript is in bounds.
- {
- xml_node_struct* p = _root->child[i]; //Keep a pointer to this node so we can free it.
- --n;
- unsigned int j;
+ //<summary>Set element name.</summary>
+ //<param name="new_name">New element name.</param>
+ //<returns>Success.</returns>
+ bool name(const std::string& new_name){ return name(new_name.c_str()); }
+
+ //<summary>Set element name.</summary>
+ //<param name="new_name">New element name.</param>
+ //<returns>Success.</returns>
+ bool name(const TCHAR* new_name)
+ {
+ if((type_element() || type_pi()) && new_name)
+#ifdef PUGOPT_NONSEG
+ return strcpyinsitu(&_root->name,new_name,&_root->name_insitu,_root->name_size );
+#else
+ return strcpyinsitu(&_root->name,new_name,&_root->name_insitu);
+#endif
+ return false;
+ }
+
+ //<summary>Set node data.</summary>
+ //<param name="value">New data (PCDATA, CDATA, or comment) value.</param>
+ //<returns>Success.</returns>
+ bool value(const std::string& new_value){ return value(new_value.c_str()); }
+
+ //<summary>Set node data.</summary>
+ //<param name="value">New data (PCDATA, CDATA, or comment) value.</param>
+ //<returns>Success.</returns>
+ bool value(const TCHAR* new_value)
+ {
+ if((type_pcdata() || type_cdata() || type_comment()) && new_value)
+#ifdef PUGOPT_NONSEG
+ return strcpyinsitu(&_root->value,new_value,&_root->value_insitu,_root->value_size);
+#else
+ return strcpyinsitu(&_root->value,new_value,&_root->value_insitu);
+#endif
+ return false;
+ }
+
+ //<summary>Remove attribute at the given subscript.</summary>
+ //<param name="i">Subscript.</param>
+ //<returns>Success.</returns>
+ bool remove_attribute(unsigned int i)
+ {
+ unsigned int n = _root->attributes;
+ if(i < n)
+ {
+ xml_attribute_struct* temp = _root->attribute[i];
+ --n;
+ for(unsigned int j=i; j<n; ++j)
+ _root->attribute[j] = _root->attribute[j+1];
+ _root->attribute[n] = NULL;
+ if(!temp->name_insitu) free(temp->name);
+ if(!temp->value_insitu) free(temp->value);
+ free(temp);
+ --_root->attributes;
+ return true;
+ }
+ return false;
+ }
+
+ //<summary>Remove attribute having the given name.</summary>
+ //<param name="name">Name of attribute to delete.</param>
+ //<returns>Success.</returns>
+ bool remove_attribute(const std::string& name){ return remove_attribute(name.c_str()); }
+
+ //<summary>Remove attribute having the given name.</summary>
+ //<param name="name">Name of attribute to delete.</param>
+ //<returns>Success.</returns>
+ bool remove_attribute(const TCHAR* name)
+ {
+ int i = mapto_attribute_idx(name);
+ if(i > -1) return remove_attribute((unsigned int)i);
+ return false;
+ }
+
+ //<summary>Append a new attribute to the node list of attributes.</summary>
+ //<param name="name">Name.</param>
+ //<param name="value">Value thereof.</param>
+ //<returns>Attribute structure wrapper.</returns>
+ //<remarks>Pointer space may be grown, memory for name/value members allocated.</remarks>
+ xml_attribute append_attribute(const std::string& name,const std::string& value){ return append_attribute(name.c_str(),value.c_str()); }
+
+ //<summary>Append a new attribute to the node list of attributes.</summary>
+ //<param name="name">Name.</param>
+ //<param name="value">Value thereof.</param>
+ //<returns>Attribute structure wrapper.</returns>
+ //<remarks>Pointer space may be grown, memory for name/value members allocated.</remarks>
+ xml_attribute append_attribute(const TCHAR* name,const TCHAR* value)
+ {
+ if(!name || !value) return xml_attribute(); //We must have both to proceed.
+ xml_attribute_struct* p = pug::append_attribute(_root,1); //Append/allocate a new attribute structure.
+ if(p) //If append/allocate succeeded.
+ {
+#ifdef PUGOPT_NONSEG
+ strcatgrown(&p->name,name,p->name_size); //Append the name.
+ strcatgrown(&p->value,value,p->value_size); //Append the name.
+#else
+ strcatgrow(&p->name,name); //Append the name.
+ strcatgrow(&p->value,value); //Append the name.
+#endif
+ p->name_insitu = p->value_insitu = false; //Mark as not part of original parse string.
+ return xml_attribute(p); //Success.
+ }
+ return xml_attribute(); //Failure; return an empty.
+ }
+
+ //<summary>Append a new attribute of type long to the node list of attributes.</summary>
+ //<param name="name">Name.</param>
+ //<param name="value">Value thereof.</param>
+ //<returns>Attribute structure wrapper.</returns>
+ //<remarks>Pointer space may be grown, memory for name/value members allocated.</remarks>
+ xml_attribute append_attribute(const TCHAR* name,long value)
+ {
+ if(!name) return false;
+ TCHAR temp[32] = {0};
+ _stprintf(temp,_T("%ld"),value);
+ return append_attribute(name,temp);
+ }
+
+ //<summary>Append a new attribute of type double to the node list of attributes.</summary>
+ //<param name="name">Name.</param>
+ //<param name="value">Value thereof.</param>
+ //<returns>Attribute structure wrapper.</returns>
+ //<remarks>Pointer space may be grown, memory for name/value members allocated.</remarks>
+ xml_attribute append_attribute(const TCHAR* name,double value)
+ {
+ if(!name) return false;
+ TCHAR temp[32] = {0};
+ _stprintf(temp,_T("%lf"),value);
+ return append_attribute(name,temp);
+ }
+
+ //<summary>Append a new attribute of type bool to the node list of attributes.</summary>
+ //<param name="name">Name.</param>
+ //<param name="value">Value thereof.</param>
+ //<returns>Attribute structure wrapper.</returns>
+ //<remarks>Pointer space may be grown, memory for name/value members allocated.</remarks>
+ xml_attribute append_attribute(const TCHAR* name,bool value)
+ {
+ if(!name) return false;
+ return append_attribute(name,((value)?_T("true"):_T("false")));
+ }
+
+ //<summary>Set the current node entity type.</summary>
+ //<param name="new_type">New type to set.</param>
+ //<returns>Previous type.</returns>
+ //<remarks>If has children and now is not node_element, children are obscured.</remarks>
+ xml_node_type type(xml_node_type new_type)
+ {
+ xml_node_type prev = _root->type; //Save old type.
+ _root->type = new_type; //Set new type.
+ return prev; //Return old type.
+ }
+
+ //<summary>
+ // Allocate & append a child node of the given type at the end of the
+ // current node array of children.
+ //</summary>
+ //<param name="type">New child node type.</param>
+ //<returns>xml_node wrapping the new child.</returns>
+ //<remarks>Pointer space may be grown. An xml_node_struct structure is allocated.</remarks>
+ xml_node append_child(xml_node_type type)
+ {
+ if(type_document()||type_element()) //Don't do anything if not an node_element or root.
+ {
+ xml_node_struct* p = pug::append_node(_root,1,type); //Append the node.
+ if(p)
+ {
+ p->name_insitu = p->value_insitu = false;
+ return xml_node(p); //If we have it, return wrapped.
+ }
+ }
+ return xml_node(); //Return dummy.
+ }
+
+ //<summary>Allocate & insert a child node of the given type at subscript.</summary>
+ //<param name="i">Subscript at which to insert.</param>
+ //<param name="type">New child node type.</param>
+ //<returns>xml_node wrapping the new child.</returns>
+ //<remarks>
+ // Pointer space may be grown. An xml_node_struct structure is allocated,
+ // and existing children are shifted in their array position.
+ //</remarks>
+ xml_node insert_child(unsigned int i,xml_node_type type)
+ {
+ if(!type_element()) return xml_node(); //Don't do anything if not an node_element.
+ unsigned int n = _root->children; //Get count of existing children.
+ if(type_element() && i >= n) return append_child(type); //If subscript at end of array then just append.
+ else if(type_element() && i < n)
+ {
+ xml_node_struct* p = pug::append_node(_root,1,type); //Append the new node (by default at last array position).
+ if(p) //Ensure we have it.
+ {
+ register int m = (i-1); //Stop at i.
+ for(register int j=(n-1); j>m; --j) //Starting at one less than end of array, reverse loop to i.
+ _root->child[j+1] = _root->child[j]; //Shift node to right.
+ _root->child[i] = p; //Set node at subscript to new node.
+ return xml_node(p); //Return new node.
+ }
+ }
+ return xml_node(); //Return dummy.
+ }
+
+ //<summary>Delete the child node at the given subscript.</summary>
+ //<param name="i">Subscript.</param>
+ //<returns>Success.</returns>
+ //<remarks>Shifts child array element positions. Frees entire tree under child to be deleted.</remarks>
+ bool remove_child(unsigned int i)
+ {
+ unsigned int n = _root->children;
+ if(i < n) //Ensure subscript is in bounds.
+ {
+ xml_node_struct* p = _root->child[i]; //Keep a pointer to this node so we can free it.
+ --n;
+ unsigned int j;
             for(j=i; j<n; ++j) //Shift everything left from this point on.
- _root->child[j] = _root->child[j+1];
- _root->child[j] = NULL; //Mark the last element null.
- --_root->children; //One less children.
- p->parent = p; //This ensures we only free this node when calling 'free_node'.
- pug::free_node(p); //Free the node tree.
- return true; //Success.
- }
- return false; //Failure.
- }
-
- //Stream/Output Helpers
-public:
-
- //<summary>
- // Stream output. Recursively writes the internal xml_node_struct structure
- // to the given stream.
- //</summary>
- //<param name="os">Reference to output stream.</param>
- //<param name="indent_char">Char to use for indent.</param>
- //<param name="breaks">Use linebreaks?</param>
- //<remarks>String data is written to stream.</remarks>
- void outer_xml(std::basic_ostream<TCHAR,std::char_traits<TCHAR> >& os,TCHAR indent_char = _T('\t'),bool breaks = true)
- {
- if(empty()) return; //Make sure there is something to output.
- indent_stack indent(indent_char); //Prepare the indent.
- if(type_document()) //If this is the root, we don't want to output the root itself.
- {
- register unsigned int n = _root->children; //Output each child of the root.
- for(register unsigned int i=0; i<n; ++i)
- pug::outer_xml(os,indent,_root->child[i],breaks);
- }
- else pug::outer_xml(os,indent,_root,breaks); //Output the node.
- }
-
- //<summary>
- // Stream output operator. Wraps 'outer_xml'. Recursively writes
- // the given node to the given stream.
- //</summary>
- //<param name="os">Reference to output stream.</param>
- //<param name="xml_node">Reference to tree node.</param>
- //<returns>Reference to output stream.</returns>
- //<remarks>String data is written to stream.</remarks>
- friend std::basic_ostream<TCHAR,std::char_traits<TCHAR> >& operator<<(std::basic_ostream<TCHAR,std::char_traits<TCHAR> >& os,xml_node node)
- {
- if(!os.good()) return os;
- if((os.flags()|std::ostream::skipws) == std::ostream::skipws)
- node.outer_xml(os,0,false); //Skipping whitespace; suppress indents & linebreaks.
- else node.outer_xml(os); //Default options.
- return os;
- }
+ _root->child[j] = _root->child[j+1];
+ _root->child[j] = NULL; //Mark the last element null.
+ --_root->children; //One less children.
+ p->parent = p; //This ensures we only free this node when calling 'free_node'.
+ pug::free_node(p); //Free the node tree.
+ return true; //Success.
+ }
+ return false; //Failure.
+ }
+
+ //Stream/Output Helpers
+public:
+
+ //<summary>
+ // Stream output. Recursively writes the internal xml_node_struct structure
+ // to the given stream.
+ //</summary>
+ //<param name="os">Reference to output stream.</param>
+ //<param name="indent_char">Char to use for indent.</param>
+ //<param name="breaks">Use linebreaks?</param>
+ //<remarks>String data is written to stream.</remarks>
+ void outer_xml(std::basic_ostream<TCHAR,std::char_traits<TCHAR> >& os,TCHAR indent_char = _T('\t'),bool breaks = true)
+ {
+ if(empty()) return; //Make sure there is something to output.
+ indent_stack indent(indent_char); //Prepare the indent.
+ if(type_document()) //If this is the root, we don't want to output the root itself.
+ {
+ register unsigned int n = _root->children; //Output each child of the root.
+ for(register unsigned int i=0; i<n; ++i)
+ pug::outer_xml(os,indent,_root->child[i],breaks);
+ }
+ else pug::outer_xml(os,indent,_root,breaks); //Output the node.
+ }
+
+ //<summary>
+ // Stream output operator. Wraps 'outer_xml'. Recursively writes
+ // the given node to the given stream.
+ //</summary>
+ //<param name="os">Reference to output stream.</param>
+ //<param name="xml_node">Reference to tree node.</param>
+ //<returns>Reference to output stream.</returns>
+ //<remarks>String data is written to stream.</remarks>
+ friend std::basic_ostream<TCHAR,std::char_traits<TCHAR> >& operator<<(std::basic_ostream<TCHAR,std::char_traits<TCHAR> >& os,xml_node node)
+ {
+ if(!os.good()) return os;
+ if((os.flags()|std::ostream::skipws) == std::ostream::skipws)
+ node.outer_xml(os,0,false); //Skipping whitespace; suppress indents & linebreaks.
+ else node.outer_xml(os); //Default options.
+ return os;
+ }
 };
 
 
@@ -3509,359 +3509,359 @@
 //Internal Data Members
 protected:
 
- xml_node_struct* _xmldoc; //Pointer to current XML document tree root.
- long _growby; //Attribute & child pointer space growth increment.
- bool _autdel; //Delete the tree on destruct?
- TCHAR* _buffer; //Pointer to in-memory buffer (for 'parse_file').
- TCHAR* _strpos; //Where parsing left off (for 'parse_file').
- unsigned long _optmsk; //Parser options.
+ xml_node_struct* _xmldoc; //Pointer to current XML document tree root.
+ long _growby; //Attribute & child pointer space growth increment.
+ bool _autdel; //Delete the tree on destruct?
+ TCHAR* _buffer; //Pointer to in-memory buffer (for 'parse_file').
+ TCHAR* _strpos; //Where parsing left off (for 'parse_file').
+ unsigned long _optmsk; //Parser options.
 #ifdef PUGOPT_MEMFIL
- HANDLE _mmfile; //File handle.
- HANDLE _mmfmap; //Handle which maps the file.
- void* _mmaddr; //Base address of map.
- size_t _mfsize; //Size of memory-mapped file.
- bool _addeos; //True if we had to add a 0 to then end of the file.
+ HANDLE _mmfile; //File handle.
+ HANDLE _mmfmap; //Handle which maps the file.
+ void* _mmaddr; //Base address of map.
+ size_t _mfsize; //Size of memory-mapped file.
+ bool _addeos; //True if we had to add a 0 to then end of the file.
 #endif
 
 //Construction/Destruction
 public:
 
- //<summary>Constructor.</summary>
- //<param name="optmsk">Options mask.</param>
- //<param name="autdel">Delete tree on destruct?</param>
- //<param name="growby">Parser pointer space growth increment.</param>
- //<remarks>Root node structure is allocated.</remarks>
- xml_parser(unsigned long optmsk = parse_default,bool autdel = true,long growby = parse_grow):
- _xmldoc(0),
- _growby(growby),
- _autdel(autdel),
- _optmsk(optmsk),
- _buffer(0),
- _strpos(0)
+ //<summary>Constructor.</summary>
+ //<param name="optmsk">Options mask.</param>
+ //<param name="autdel">Delete tree on destruct?</param>
+ //<param name="growby">Parser pointer space growth increment.</param>
+ //<remarks>Root node structure is allocated.</remarks>
+ xml_parser(unsigned long optmsk = parse_default,bool autdel = true,long growby = parse_grow):
+ _xmldoc(0),
+ _growby(growby),
+ _autdel(autdel),
+ _optmsk(optmsk),
+ _buffer(0),
+ _strpos(0)
 #ifdef PUGOPT_MEMFIL
- ,
- _mmfile(0),
- _mmfmap(0),
- _mmaddr(0),
- _mfsize(0),
- _addeos(false)
-#endif
- {
- }
-
- //<summary>Direct parse constructor.</summary>
- //<param name="xmlstr">
- // XML-formatted string to parse. Note: String must persist for the
- // life of the tree. String is zero-segmented, but not freed.
- //</param>
- //<param name="optmsk">Parser options.</param>
- //<param name="autdel">Delete tree on destruct?</param>
- //<param name="growby">Parser pointer space growth increment.</param>
- //<remarks>Root node structure is allocated, string is parsed & tree may be grown.</remarks>
- xml_parser(TCHAR* xmlstr,unsigned long optmsk = parse_default,bool autdel = true,long growby = parse_grow) :
- _xmldoc(0),
- _growby(growby),
- _autdel(autdel),
- _optmsk(optmsk),
- _buffer(0),
- _strpos(0)
+ ,
+ _mmfile(0),
+ _mmfmap(0),
+ _mmaddr(0),
+ _mfsize(0),
+ _addeos(false)
+#endif
+ {
+ }
+
+ //<summary>Direct parse constructor.</summary>
+ //<param name="xmlstr">
+ // XML-formatted string to parse. Note: String must persist for the
+ // life of the tree. String is zero-segmented, but not freed.
+ //</param>
+ //<param name="optmsk">Parser options.</param>
+ //<param name="autdel">Delete tree on destruct?</param>
+ //<param name="growby">Parser pointer space growth increment.</param>
+ //<remarks>Root node structure is allocated, string is parsed & tree may be grown.</remarks>
+ xml_parser(TCHAR* xmlstr,unsigned long optmsk = parse_default,bool autdel = true,long growby = parse_grow) :
+ _xmldoc(0),
+ _growby(growby),
+ _autdel(autdel),
+ _optmsk(optmsk),
+ _buffer(0),
+ _strpos(0)
 #ifdef PUGOPT_MEMFIL
- ,
- _mmfile(0),
- _mmfmap(0),
- _mmaddr(0),
- _mfsize(0),
- _addeos(false)
-#endif
- {
- parse(xmlstr,_optmsk); //Parse it.
- }
-
- //<summary>Destructor.</summary>
- //<remarks>Tree memory and string memory may be freed.</remarks>
- virtual ~xml_parser()
- {
- if(_autdel && _xmldoc) free_node(_xmldoc);
- if(_buffer) free(_buffer);
+ ,
+ _mmfile(0),
+ _mmfmap(0),
+ _mmaddr(0),
+ _mfsize(0),
+ _addeos(false)
+#endif
+ {
+ parse(xmlstr,_optmsk); //Parse it.
+ }
+
+ //<summary>Destructor.</summary>
+ //<remarks>Tree memory and string memory may be freed.</remarks>
+ virtual ~xml_parser()
+ {
+ if(_autdel && _xmldoc) free_node(_xmldoc);
+ if(_buffer) free(_buffer);
 #ifdef PUGOPT_MEMFIL
- close_memfile();
+ close_memfile();
 #endif
- }
+ }
 
 //Accessors/Operators
 public:
 
- operator xml_node_struct*() { return _xmldoc; } //Cast as xml_node_struct pointer to root.
- operator xml_node() { return xml_node(_xmldoc); } //Cast as xml_node (same as document).
- xml_node document(){ return xml_node(_xmldoc); } //Returns the root wrapped by an xml_node.
+ operator xml_node_struct*() { return _xmldoc; } //Cast as xml_node_struct pointer to root.
+ operator xml_node() { return xml_node(_xmldoc); } //Cast as xml_node (same as document).
+ xml_node document(){ return xml_node(_xmldoc); } //Returns the root wrapped by an xml_node.
 
 //Miscellaneous
 public:
 
- //<summary>Allocate a new, empty root.</summary>
- //<remarks>Tree memory and string memory may be freed.</remarks>
- void create()
- {
- clear(); //Free any allocated memory.
- _xmldoc = new_node(node_document); //Allocate a new root.
- _xmldoc->parent = _xmldoc; //Point to self.
- }
-
- //<summary>Clear any existing tree or string.</summary>
- //<remarks>Tree memory and string memory may be freed.</remarks>
- void clear()
- {
- if(_xmldoc){ free_node(_xmldoc); _xmldoc = 0; }
- if(_buffer){ free(_buffer); _buffer = 0; }
+ //<summary>Allocate a new, empty root.</summary>
+ //<remarks>Tree memory and string memory may be freed.</remarks>
+ void create()
+ {
+ clear(); //Free any allocated memory.
+ _xmldoc = new_node(node_document); //Allocate a new root.
+ _xmldoc->parent = _xmldoc; //Point to self.
+ }
+
+ //<summary>Clear any existing tree or string.</summary>
+ //<remarks>Tree memory and string memory may be freed.</remarks>
+ void clear()
+ {
+ if(_xmldoc){ free_node(_xmldoc); _xmldoc = 0; }
+ if(_buffer){ free(_buffer); _buffer = 0; }
 #ifdef PUGOPT_MEMFIL
- close_memfile();
+ close_memfile();
 #endif
- }
+ }
 
 #ifdef PUGOPT_MEMFIL
 
 //Memory-Mapped File Support
 protected:
 
- //<summary>Closes any existing memory-mapped file.</summary>
- void close_memfile()
- {
- if(_mmaddr != 0)
- {
- UnmapViewOfFile(_mmaddr);
- _mmaddr = 0;
- }
- if(_mmfmap != 0)
- {
- CloseHandle(_mmfmap);
- _mmfmap = 0;
- }
- if(_mmfile != 0)
- {
- if(_addeos) //Remove the 0 we added to the end of the file.
- {
- SetFilePointer(_mmfile,_mfsize,NULL,FILE_BEGIN);
- SetEndOfFile(_mmfile);
- _addeos = false;
- }
- CloseHandle(_mmfile);
- _mmfile = 0;
- }
- _mfsize = 0;
- }
+ //<summary>Closes any existing memory-mapped file.</summary>
+ void close_memfile()
+ {
+ if(_mmaddr != 0)
+ {
+ UnmapViewOfFile(_mmaddr);
+ _mmaddr = 0;
+ }
+ if(_mmfmap != 0)
+ {
+ CloseHandle(_mmfmap);
+ _mmfmap = 0;
+ }
+ if(_mmfile != 0)
+ {
+ if(_addeos) //Remove the 0 we added to the end of the file.
+ {
+ SetFilePointer(_mmfile,_mfsize,NULL,FILE_BEGIN);
+ SetEndOfFile(_mmfile);
+ _addeos = false;
+ }
+ CloseHandle(_mmfile);
+ _mmfile = 0;
+ }
+ _mfsize = 0;
+ }
 
 public:
 
 #endif
 
- //<summary>Attach an externally-generated root to the parser.</summary>
- //<param name="root">Pointer to node structure.</param>
- //<returns>Pointer to old root if any.</returns>
- //<remarks>New root may be deleted on dtor if autodelete set.</remarks>
- xml_node_struct* attach(xml_node_struct* root)
- {
- xml_node_struct* t = _xmldoc; //Save this root.
- _xmldoc = root; //Assign.
- _xmldoc->parent = _xmldoc; //Ensure we are the root.
- return t; //Return the old root if any.
- }
-
- //<summary>Detach the current root from the parser.</summary>
- //<returns>Pointer to old root, if any.</returns>
- xml_node_struct* detach()
- {
- xml_node_struct* t = _xmldoc; //Save this root.
- _xmldoc = 0; //So we don't delete later on if autodelete set.
- return t; //Return the old root if any.
- }
-
- //<summary>Get parser optsions mask.</summary>
- //<returns>Options mask.</returns>
- unsigned long options(){ return _optmsk; }
-
- //<summary>Set parser options mask.</summary>
- //<param name="optmsk">Options mask to set.</param>
- //<returns>Old options mask.</returns>
- unsigned long options(unsigned long optmsk)
- {
- unsigned long prev = _optmsk;
- _optmsk = optmsk;
- return prev;
- }
-
- //<summary>Get pointer space growth size increment.</summary>
- //<returns>Grow size.</returns>
- unsigned long growby(){ return _growby; }
-
- //<summary>Set pointer space growth size increment.</summary>
- //<param name="grow">Grow size to set.</param>
- //<returns>Old size.</returns>
- unsigned long growby(long grow)
- {
- long prev = _growby;
- _growby = grow;
- return prev;
- }
-
- //<summary>Get parse file buffer last string position.</summary>
- //<returns>Last string position.</returns>
- //<remarks>
- // Use after parse_file, with parse_dtd_only set in order to recommence
- // parse of document body.
- //</remarks>
- TCHAR* strpos()
- {
- return _strpos;
- }
+ //<summary>Attach an externally-generated root to the parser.</summary>
+ //<param name="root">Pointer to node structure.</param>
+ //<returns>Pointer to old root if any.</returns>
+ //<remarks>New root may be deleted on dtor if autodelete set.</remarks>
+ xml_node_struct* attach(xml_node_struct* root)
+ {
+ xml_node_struct* t = _xmldoc; //Save this root.
+ _xmldoc = root; //Assign.
+ _xmldoc->parent = _xmldoc; //Ensure we are the root.
+ return t; //Return the old root if any.
+ }
+
+ //<summary>Detach the current root from the parser.</summary>
+ //<returns>Pointer to old root, if any.</returns>
+ xml_node_struct* detach()
+ {
+ xml_node_struct* t = _xmldoc; //Save this root.
+ _xmldoc = 0; //So we don't delete later on if autodelete set.
+ return t; //Return the old root if any.
+ }
+
+ //<summary>Get parser optsions mask.</summary>
+ //<returns>Options mask.</returns>
+ unsigned long options(){ return _optmsk; }
+
+ //<summary>Set parser options mask.</summary>
+ //<param name="optmsk">Options mask to set.</param>
+ //<returns>Old options mask.</returns>
+ unsigned long options(unsigned long optmsk)
+ {
+ unsigned long prev = _optmsk;
+ _optmsk = optmsk;
+ return prev;
+ }
+
+ //<summary>Get pointer space growth size increment.</summary>
+ //<returns>Grow size.</returns>
+ unsigned long growby(){ return _growby; }
+
+ //<summary>Set pointer space growth size increment.</summary>
+ //<param name="grow">Grow size to set.</param>
+ //<returns>Old size.</returns>
+ unsigned long growby(long grow)
+ {
+ long prev = _growby;
+ _growby = grow;
+ return prev;
+ }
+
+ //<summary>Get parse file buffer last string position.</summary>
+ //<returns>Last string position.</returns>
+ //<remarks>
+ // Use after parse_file, with parse_dtd_only set in order to recommence
+ // parse of document body.
+ //</remarks>
+ TCHAR* strpos()
+ {
+ return _strpos;
+ }
 
 //Parsing Helpers
 public:
 
- //<summary>Parse the given XML string in-situ.</summary>
- //<param name="s">Pointer to XML-formatted string.</param>
- //<param name="optmsk">Parser options mask.</param>
- //<returns>Last string position or null.</returns>
- //<remarks>Input string is zero-segmented.</remarks>
- TCHAR* parse(TCHAR* s,unsigned long optmsk = parse_noset)
- {
- if(!s) return s;
- clear(); //Free any allocated memory.
- _xmldoc = new_node(node_document); //Allocate a new root.
- _xmldoc->parent = _xmldoc; //Point to self.
- if(optmsk != parse_noset) _optmsk = optmsk;
- return pug::parse(s,_xmldoc,_growby,_optmsk); //Parse the input string.
- }
+ //<summary>Parse the given XML string in-situ.</summary>
+ //<param name="s">Pointer to XML-formatted string.</param>
+ //<param name="optmsk">Parser options mask.</param>
+ //<returns>Last string position or null.</returns>
+ //<remarks>Input string is zero-segmented.</remarks>
+ TCHAR* parse(TCHAR* s,unsigned long optmsk = parse_noset)
+ {
+ if(!s) return s;
+ clear(); //Free any allocated memory.
+ _xmldoc = new_node(node_document); //Allocate a new root.
+ _xmldoc->parent = _xmldoc; //Point to self.
+ if(optmsk != parse_noset) _optmsk = optmsk;
+ return pug::parse(s,_xmldoc,_growby,_optmsk); //Parse the input string.
+ }
 
- /*
+ /*
     //<summary>Load into memory and parse the contents of the file at the given path.</summary>
- //<param name="path">File path.</param>
- //<param name="optmsk">Parser options.</param>
- //<returns>Success if the file was loaded.</returns>
- //<remarks>
- // The file contents is loaded and stored in the member '_buffer' until
- // freed by calling 'Parse', 'parse_file', 'clear' or '~xml_parser'.
- //</remarks>
- bool parse_file(const TCHAR* path,unsigned long optmsk = parse_noset)
- {
- if(!path) return false;
- clear(); //clear any existing data.
- unsigned long bytes;
- if(optmsk != parse_noset) _optmsk = optmsk;
- if(load_file(path,&_buffer,&bytes) && bytes > 0)
- {
- _xmldoc = pug::new_node(node_document);
- _xmldoc->parent = _xmldoc; //Point to self.
- TCHAR* s = pug::parse(_buffer,_xmldoc,_growby,_optmsk);
- _strpos = s;
- return true;
- }
- return false;
- }
+ //<param name="path">File path.</param>
+ //<param name="optmsk">Parser options.</param>
+ //<returns>Success if the file was loaded.</returns>
+ //<remarks>
+ // The file contents is loaded and stored in the member '_buffer' until
+ // freed by calling 'Parse', 'parse_file', 'clear' or '~xml_parser'.
+ //</remarks>
+ bool parse_file(const TCHAR* path,unsigned long optmsk = parse_noset)
+ {
+ if(!path) return false;
+ clear(); //clear any existing data.
+ unsigned long bytes;
+ if(optmsk != parse_noset) _optmsk = optmsk;
+ if(load_file(path,&_buffer,&bytes) && bytes > 0)
+ {
+ _xmldoc = pug::new_node(node_document);
+ _xmldoc->parent = _xmldoc; //Point to self.
+ TCHAR* s = pug::parse(_buffer,_xmldoc,_growby,_optmsk);
+ _strpos = s;
+ return true;
+ }
+ return false;
+ }
     */
 
 #ifdef PUGOPT_MEMFIL
 
- //<summary>Parse the contents of the file at the given path, using a memory-mapped file.</summary>
- //<param name="path">File path.</param>
- //<param name="optmsk">Parser options.</param>
- //<returns>
- // True (1) if the file was parsed successfully, false (0) if open failed,
- // and -1 if an exception occured.
- //</returns>
- //<remarks>
- // The file contents are available until closed by calling 'parse',
- // 'parse_file', 'clear' or '~xml_parser'.
- //</remarks>
- int parse_mmfile(const TCHAR* path,unsigned long optmsk = parse_noset)
- {
- int status = 0;
- if(path)
- {
- clear(); //Clear any existing data.
- if(optmsk != parse_noset) _optmsk = optmsk;
- assert((optmsk & parse_wnorm) == 0); //Normalization isn't implemented for memory-mapped files, as of 23 Jan 2003.
- const bool readonly = (optmsk & (parse_dtd|parse_dtd_only)) == 0;
- if(open_mmfile(path,readonly,false))
- {
- //If the file has a 0 at the end we are ok to proceed, otherwise add one.
- if
- (
- (
- *(((TCHAR*)_mmaddr) + _mfsize) == 0
- ||
- (
- _mfsize > 0 &&
- *(((TCHAR*)_mmaddr) + _mfsize - 1) == 0
- )
- )
- ||
- open_mmfile(path,false,true) //Re-open and add 0 at EOF.
- )
- {
- try
- {
- _xmldoc = new_node(node_document);
- _xmldoc->parent = _xmldoc; //Point to self.
- TCHAR* s = pug::parse((TCHAR*)_mmaddr,_xmldoc,_growby,_optmsk);
- _strpos = s;
- status = 1;
- }
- catch(...)
- {
- status = -1;
- assert(false);
- }
- }
- }
- }
- return status;
- }
+ //<summary>Parse the contents of the file at the given path, using a memory-mapped file.</summary>
+ //<param name="path">File path.</param>
+ //<param name="optmsk">Parser options.</param>
+ //<returns>
+ // True (1) if the file was parsed successfully, false (0) if open failed,
+ // and -1 if an exception occured.
+ //</returns>
+ //<remarks>
+ // The file contents are available until closed by calling 'parse',
+ // 'parse_file', 'clear' or '~xml_parser'.
+ //</remarks>
+ int parse_mmfile(const TCHAR* path,unsigned long optmsk = parse_noset)
+ {
+ int status = 0;
+ if(path)
+ {
+ clear(); //Clear any existing data.
+ if(optmsk != parse_noset) _optmsk = optmsk;
+ assert((optmsk & parse_wnorm) == 0); //Normalization isn't implemented for memory-mapped files, as of 23 Jan 2003.
+ const bool readonly = (optmsk & (parse_dtd|parse_dtd_only)) == 0;
+ if(open_mmfile(path,readonly,false))
+ {
+ //If the file has a 0 at the end we are ok to proceed, otherwise add one.
+ if
+ (
+ (
+ *(((TCHAR*)_mmaddr) + _mfsize) == 0
+ ||
+ (
+ _mfsize > 0 &&
+ *(((TCHAR*)_mmaddr) + _mfsize - 1) == 0
+ )
+ )
+ ||
+ open_mmfile(path,false,true) //Re-open and add 0 at EOF.
+ )
+ {
+ try
+ {
+ _xmldoc = new_node(node_document);
+ _xmldoc->parent = _xmldoc; //Point to self.
+ TCHAR* s = pug::parse((TCHAR*)_mmaddr,_xmldoc,_growby,_optmsk);
+ _strpos = s;
+ status = 1;
+ }
+ catch(...)
+ {
+ status = -1;
+ assert(false);
+ }
+ }
+ }
+ }
+ return status;
+ }
 
 protected:
 
- //<summary>Opens the specified memory-mapped file.</summary>
- //<param name="path">File path.</param>
- //<param name="readonly">True to open the file for read-only access.</param>
- //<param name="addeos">True to add a 0 to the end of the file.</param>
- //<returns>Success if the file was opened.</returns>
- bool open_mmfile(const TCHAR* path,const bool readonly,const bool addeos)
- {
- clear(); //Close any existing MMF and clear any existing data.
- assert(_mmfile == NULL && _mmfile == NULL && _mmaddr == NULL);
- _addeos = false;
- _mmfile = CreateFile(path,readonly?GENERIC_READ:GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); //Open read-only, no share, no security attrs, ..., no template.
- if(_mmfile != INVALID_HANDLE_VALUE)
- {
- _mfsize = ::GetFileSize(_mmfile,NULL);
- _mmfmap = CreateFileMapping(_mmfile,NULL,readonly?PAGE_READONLY:PAGE_READWRITE,0,_mfsize+(addeos?sizeof(TCHAR):0),NULL); //Create map: handle, no security attr, read|read/write, larger if addeos, anonymous.
- if(_mmfmap != NULL)
- {
- assert(_mmaddr == NULL);
- _mmaddr = MapViewOfFile(_mmfmap,readonly?FILE_MAP_READ:FILE_MAP_WRITE,0,0,0); //Map the view: handle, read|read/write, start at beginning, map entire file.
- if(_mmaddr != NULL)
- {
- if(addeos) //Add a terminating 0 to the end of the file for 'parse()'.
- {
- assert(!readonly);
- *(((TCHAR*)_mmaddr) + _mfsize) = 0;
- _addeos = true;
- }
- }
- else
- {
- CloseHandle(_mmfmap);
- CloseHandle(_mmfile);
- _mmfile = _mmfmap = 0;
- }
- }
- else
- {
- CloseHandle(_mmfile);
- _mmfile = 0;
- }
- }
- return (_mmaddr != NULL);
- }
+ //<summary>Opens the specified memory-mapped file.</summary>
+ //<param name="path">File path.</param>
+ //<param name="readonly">True to open the file for read-only access.</param>
+ //<param name="addeos">True to add a 0 to the end of the file.</param>
+ //<returns>Success if the file was opened.</returns>
+ bool open_mmfile(const TCHAR* path,const bool readonly,const bool addeos)
+ {
+ clear(); //Close any existing MMF and clear any existing data.
+ assert(_mmfile == NULL && _mmfile == NULL && _mmaddr == NULL);
+ _addeos = false;
+ _mmfile = CreateFile(path,readonly?GENERIC_READ:GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); //Open read-only, no share, no security attrs, ..., no template.
+ if(_mmfile != INVALID_HANDLE_VALUE)
+ {
+ _mfsize = ::GetFileSize(_mmfile,NULL);
+ _mmfmap = CreateFileMapping(_mmfile,NULL,readonly?PAGE_READONLY:PAGE_READWRITE,0,_mfsize+(addeos?sizeof(TCHAR):0),NULL); //Create map: handle, no security attr, read|read/write, larger if addeos, anonymous.
+ if(_mmfmap != NULL)
+ {
+ assert(_mmaddr == NULL);
+ _mmaddr = MapViewOfFile(_mmfmap,readonly?FILE_MAP_READ:FILE_MAP_WRITE,0,0,0); //Map the view: handle, read|read/write, start at beginning, map entire file.
+ if(_mmaddr != NULL)
+ {
+ if(addeos) //Add a terminating 0 to the end of the file for 'parse()'.
+ {
+ assert(!readonly);
+ *(((TCHAR*)_mmaddr) + _mfsize) = 0;
+ _addeos = true;
+ }
+ }
+ else
+ {
+ CloseHandle(_mmfmap);
+ CloseHandle(_mmfile);
+ _mmfile = _mmfmap = 0;
+ }
+ }
+ else
+ {
+ CloseHandle(_mmfile);
+ _mmfile = 0;
+ }
+ }
+ return (_mmaddr != NULL);
+ }
 
 #endif
 
@@ -3872,18 +3872,18 @@
 class xml_node_list: public pointer_array
 {
 public:
- xml_node_list(unsigned int grow = 4) : pointer_array(grow) { }
- virtual ~xml_node_list(){ }
+ xml_node_list(unsigned int grow = 4) : pointer_array(grow) { }
+ virtual ~xml_node_list(){ }
 public:
- xml_node at(long i){ return xml_node((xml_node_struct*)pointer_array::at((unsigned int)i)); } //Access xml_node at subscript.
- xml_node operator[](long i){ return xml_node((xml_node_struct*)pointer_array::at((unsigned int)i)); } //Access xml_node at subscript.
- friend std::ostream& operator<<(std::ostream& os,xml_node_list& list) //Output helper.
- {
- if(!os.good()) return os;
- unsigned int n = list.size();
- for(unsigned int i=0; i<n; ++i) os << list[i];
- return os;
- }
+ xml_node at(long i){ return xml_node((xml_node_struct*)pointer_array::at((unsigned int)i)); } //Access xml_node at subscript.
+ xml_node operator[](long i){ return xml_node((xml_node_struct*)pointer_array::at((unsigned int)i)); } //Access xml_node at subscript.
+ friend std::ostream& operator<<(std::ostream& os,xml_node_list& list) //Output helper.
+ {
+ if(!os.good()) return os;
+ unsigned int n = list.size();
+ for(unsigned int i=0; i<n; ++i) os << list[i];
+ return os;
+ }
 };
 
 

Modified: trunk/libs/property_tree/test/test_json_parser.cpp
==============================================================================
--- trunk/libs/property_tree/test/test_json_parser.cpp (original)
+++ trunk/libs/property_tree/test/test_json_parser.cpp 2009-05-21 10:38:00 EDT (Thu, 21 May 2009)
@@ -192,11 +192,11 @@
 
 const char *ok_data_10 =
     "{\n"
- " \"glossary\": {\n"
- " \"title\": \"example glossary\",\n"
- " \"GlossDiv\": {\n"
- " \"title\": \"S\",\n"
- " \"GlossList\": [{\n"
+ " \"glossary\": {\n"
+ " \"title\": \"example glossary\",\n"
+ " \"GlossDiv\": {\n"
+ " \"title\": \"S\",\n"
+ " \"GlossList\": [{\n"
     " \"ID\": \"SGML\",\n"
     " \"SortAs\": \"SGML\",\n"
     " \"GlossTerm\": \"Standard Generalized Markup Language\",\n"

Modified: trunk/libs/property_tree/test/xml_parser_test_data.hpp
==============================================================================
--- trunk/libs/property_tree/test/xml_parser_test_data.hpp (original)
+++ trunk/libs/property_tree/test/xml_parser_test_data.hpp 2009-05-21 10:38:00 EDT (Thu, 21 May 2009)
@@ -35,442 +35,442 @@
     "\n"
     "<!-- Last edited: 27 May 1999 by bent -->\n"
     "<header><?Pub Dtl?>\n"
- " <title>XML Linking Language (XLink)</title>\n"
- " <version>Version 1.0</version>\n"
- " <w3c-designation>WD-xlink-19990527</w3c-designation>\n"
- " <w3c-doctype>World Wide Web Consortium Working Draft</w3c-doctype>\n"
- " <pubdate><day>29</day><month>May</month><year>1999</year></pubdate>\n"
- " <notice>\n"
- " <p>This draft is for public discussion.</p>\n"
- " </notice>\n"
- " <publoc><loc href=\"http://www.w3.org/XML/Group/1999/05/WD-xlink-current\">http://www.w3.org/XML/Group/1999/05/WD-xlink-current></publoc>\n"
- " <prevlocs>\n"
- " <!--Check: was it actually August?-->\n"
- " <loc href=\"
http://www.w3.org/XML/Group/1999/05/WD-xlink-19990527\">http://www.w3.org/XML/Group/1999/05/WD-xlink-19990527>\n"
- " <loc href=\"
http://www.w3.org/XML/Group/1999/05/WD-xlink-19990505\">http://www.w3.org/XML/Group/1999/05/WD-xlink-19990505>\n"
- " <loc href=\"
http://www.w3.org/TR/1998/WD-xlink-19980303\">http://www.w3.org/TR/1998/WD-xlink-19980303>\n"
- " <loc href=\"
http://www.w3.org/TR/WD-xml-link-970630\">http://www.w3.org/TR/WD-xml-link-970630></prevlocs>\n"
- "\n"
- " <authlist>\n"
- " <!--Updated author hrefs dorchard-->\n"
- " <!-- Update Steve's email - bent --> \n"
- " <author>\n"
- " <name>Steve DeRose</name>\n"
- " <affiliation>Inso Corp. and Brown University</affiliation>\n"
- " <email href=\"mailto:Steven_DeRose_at_[hidden]\">Steven_DeRose_at_[hidden]</email>\n"
- " </author>\n"
- " <author>\n"
- " <name>David Orchard</name>\n"
- " <affiliation>IBM Corp.</affiliation>\n"
- " <email href=\"mailto:dorchard_at_[hidden]\">dorchard_at_[hidden]</email>\n"
- " </author>\n"
- " <author>\n"
- " <name>Ben Trafford</name>\n"
- " <affiliation>Invited Expert</affiliation>\n"
- " <email href=\"mailto:bent_at_[hidden]\">bent_at_[hidden]</email>\n"
- " </author>\n"
- " <!-- I suggest we move Eve and Tim down to the Acknowledgements section. We\n"
- " also ought to add Gabe Beged-Dov there, as well. bent\n"
- " how shall we cite Tim? sjd What about with an Acknowledgments section?\n"
- " -elm <AUTHOR> <NAME>Tim Bray</NAME> <AFFILIATION>Textuality</AFFILIATION>\n"
- " <EMAIL>tbray_at_[hidden]</EMAIL> </AUTHOR>-->\n"
- " </authlist>\n"
- "\n"
- " <status>\n"
- " <p>This is a W3C Working Draft for review by W3C members and other interested parties. It is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use W3C Working Drafts as reference material or to cite them as other than \"work in progress\". A list of current W3C working drafts can be found at <loc href=\"
http://www.w3.org/TR\">http://www.w3.org/TR>.</p>\n"
- " <p><emph>Note:</emph> Since working drafts are subject to frequent change, you are advised to reference the above URI, rather than the URIs for working drafts themselves. Some of the work remaining is described in <specref ref=\"unfinished\"/>. </p>\n"
- " <p>This work is part of the W3C XML Activity (for current status, see <loc href=\"
http://www.w3.org/MarkUp/SGML/Activity\">http://www.w3.org/XML/Activity </loc>). For information about the XPointer language which is expected to be used with XLink, see <loc href=\"http://www.w3.org/MarkUp/SGML/Activity\">http://www.w3.org/TR/WD-xptr>.\n"
- " </p>\n"
- " <p>See <loc href=\"
http://www.w3.org/TR/NOTE-xlink-principles\">http://www.w3.org/TR/NOTE-xlink-principles </loc> for additional background on the design principles informing XLink.</p>\n"
- " <p>Also see <loc href=\"http://www.w3.org/TR/NOTE-xlink-req/\">http://www.w3.org/TR/NOTE-xlink-req/> for the XLink requirements that this document attempts to satisfy.</p>\n"
- " </status>\n"
- "\n"
- " <abstract>\n"
- " <!-- edited the abstract for further clarity - bent -->\n"
- " <p>This specification defines constructs that may be inserted into XML DTDs, schemas and document instances to describe links between objects. It uses XML syntax to create structures that can describe the simple unidirectional hyperlinks of today's HTML as well as more sophisticated links.</p>\n"
- " </abstract>\n"
- "\n"
- " <pubstmt>\n"
- " <p>Burlington, Seekonk, et al.: World-Wide Web Consortium, XML Working Group, 1998.</p>\n"
- " </pubstmt>\n"
- "\n"
- " <sourcedesc>\n"
- " <p>Created in electronic form.</p>\n"
- " </sourcedesc>\n"
- "\n"
- " <langusage>\n"
- " <language id=\"en\">English</language>\n"
- " <language id=\"ebnf\">Extended Backus-Naur Form (formal grammar)</language>\n"
- " </langusage>\n"
- "\n"
- " <revisiondesc>\n"
- " <slist>\n"
- " <sitem>1997-01-15 : Skeleton draft by TB</sitem>\n"
- " <sitem>1997-01-24 : Fleshed out by sjd</sitem>\n"
- " <sitem>1997-04-08 : Substantive draft</sitem>\n"
- " <sitem>1997-06-30 : Public draft</sitem>\n"
- " <sitem>1997-08-01 : Public draft</sitem>\n"
- " <sitem>1997-08-05 : Prose/organization work by sjd</sitem>\n"
- " <sitem>1997-10-14: Conformance and design principles; a bit of cleanup by elm</sitem>\n"
- " <sitem>1997-11-07: Update for editorial issues per issues doc, by sjd.</sitem>\n"
- " <sitem>1997-12-01: Update for editorial issues per issues doc in preparation for F2F meeting, by sjd.</sitem>\n"
- " <sitem>1998-01-13: Editorial cleanup, addition of new design principles, by elm.</sitem>\n"
- " <sitem>1998-02-27: Splitting out of XLink and XPointer, by elm.</sitem>\n"
- " <sitem>1998-03-03: Moved most of the XPointer locator stuff here. elm</sitem>\n"
- " <sitem>1999-04-24: Editorial rewrites to represent new ideas on XLink, especially the inclusion of arcs. bent</sitem>\n"
- " <sitem>1999-05-05: Prose/organization work by dorchard. Moved much of the semantics section around, from: locators, link semantics, remote resource semantics, local resource semantics; to: resource semantics, locators, behavior semantics, link semantics, arc semantics</sitem>\n"
- " <sitem>1999-05-12: Prose/organization work. Re-organized some of the sections, removed XML constructs from the document, added descriptive prose, edited document text for clarity. Rewrote the link recognition section. bent</sitem>\n"
- " <sitem>1999-05-17: Further prose work. Added non-normative examples. Clarified arcs. bent</sitem>\n"
- " <sitem>1999-05-23: Edited for grammar and clarity. bent</sitem>\n"
- " <sitem>1999-05-27: Final once-over before sending to group. Fixed sjd's email address. bent</sitem>\n"
- " </slist>\n"
- " </revisiondesc>\n"
+ " <title>XML Linking Language (XLink)</title>\n"
+ " <version>Version 1.0</version>\n"
+ " <w3c-designation>WD-xlink-19990527</w3c-designation>\n"
+ " <w3c-doctype>World Wide Web Consortium Working Draft</w3c-doctype>\n"
+ " <pubdate><day>29</day><month>May</month><year>1999</year></pubdate>\n"
+ " <notice>\n"
+ " <p>This draft is for public discussion.</p>\n"
+ " </notice>\n"
+ " <publoc><loc href=\"
http://www.w3.org/XML/Group/1999/05/WD-xlink-current\">http://www.w3.org/XML/Group/1999/05/WD-xlink-current></publoc>\n"
+ " <prevlocs>\n"
+ " <!--Check: was it actually August?-->\n"
+ " <loc href=\"
http://www.w3.org/XML/Group/1999/05/WD-xlink-19990527\">http://www.w3.org/XML/Group/1999/05/WD-xlink-19990527>\n"
+ " <loc href=\"
http://www.w3.org/XML/Group/1999/05/WD-xlink-19990505\">http://www.w3.org/XML/Group/1999/05/WD-xlink-19990505>\n"
+ " <loc href=\"
http://www.w3.org/TR/1998/WD-xlink-19980303\">http://www.w3.org/TR/1998/WD-xlink-19980303>\n"
+ " <loc href=\"
http://www.w3.org/TR/WD-xml-link-970630\">http://www.w3.org/TR/WD-xml-link-970630></prevlocs>\n"
+ "\n"
+ " <authlist>\n"
+ " <!--Updated author hrefs dorchard-->\n"
+ " <!-- Update Steve's email - bent --> \n"
+ " <author>\n"
+ " <name>Steve DeRose</name>\n"
+ " <affiliation>Inso Corp. and Brown University</affiliation>\n"
+ " <email href=\"mailto:Steven_DeRose_at_[hidden]\">Steven_DeRose_at_[hidden]</email>\n"
+ " </author>\n"
+ " <author>\n"
+ " <name>David Orchard</name>\n"
+ " <affiliation>IBM Corp.</affiliation>\n"
+ " <email href=\"mailto:dorchard_at_[hidden]\">dorchard_at_[hidden]</email>\n"
+ " </author>\n"
+ " <author>\n"
+ " <name>Ben Trafford</name>\n"
+ " <affiliation>Invited Expert</affiliation>\n"
+ " <email href=\"mailto:bent_at_[hidden]\">bent_at_[hidden]</email>\n"
+ " </author>\n"
+ " <!-- I suggest we move Eve and Tim down to the Acknowledgements section. We\n"
+ " also ought to add Gabe Beged-Dov there, as well. bent\n"
+ " how shall we cite Tim? sjd What about with an Acknowledgments section?\n"
+ " -elm <AUTHOR> <NAME>Tim Bray</NAME> <AFFILIATION>Textuality</AFFILIATION>\n"
+ " <EMAIL>tbray_at_[hidden]</EMAIL> </AUTHOR>-->\n"
+ " </authlist>\n"
+ "\n"
+ " <status>\n"
+ " <p>This is a W3C Working Draft for review by W3C members and other interested parties. It is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use W3C Working Drafts as reference material or to cite them as other than \"work in progress\". A list of current W3C working drafts can be found at <loc href=\"
http://www.w3.org/TR\">http://www.w3.org/TR>.</p>\n"
+ " <p><emph>Note:</emph> Since working drafts are subject to frequent change, you are advised to reference the above URI, rather than the URIs for working drafts themselves. Some of the work remaining is described in <specref ref=\"unfinished\"/>. </p>\n"
+ " <p>This work is part of the W3C XML Activity (for current status, see <loc href=\"
http://www.w3.org/MarkUp/SGML/Activity\">http://www.w3.org/XML/Activity </loc>). For information about the XPointer language which is expected to be used with XLink, see <loc href=\"http://www.w3.org/MarkUp/SGML/Activity\">http://www.w3.org/TR/WD-xptr>.\n"
+ " </p>\n"
+ " <p>See <loc href=\"
http://www.w3.org/TR/NOTE-xlink-principles\">http://www.w3.org/TR/NOTE-xlink-principles </loc> for additional background on the design principles informing XLink.</p>\n"
+ " <p>Also see <loc href=\"http://www.w3.org/TR/NOTE-xlink-req/\">http://www.w3.org/TR/NOTE-xlink-req/> for the XLink requirements that this document attempts to satisfy.</p>\n"
+ " </status>\n"
+ "\n"
+ " <abstract>\n"
+ " <!-- edited the abstract for further clarity - bent -->\n"
+ " <p>This specification defines constructs that may be inserted into XML DTDs, schemas and document instances to describe links between objects. It uses XML syntax to create structures that can describe the simple unidirectional hyperlinks of today's HTML as well as more sophisticated links.</p>\n"
+ " </abstract>\n"
+ "\n"
+ " <pubstmt>\n"
+ " <p>Burlington, Seekonk, et al.: World-Wide Web Consortium, XML Working Group, 1998.</p>\n"
+ " </pubstmt>\n"
+ "\n"
+ " <sourcedesc>\n"
+ " <p>Created in electronic form.</p>\n"
+ " </sourcedesc>\n"
+ "\n"
+ " <langusage>\n"
+ " <language id=\"en\">English</language>\n"
+ " <language id=\"ebnf\">Extended Backus-Naur Form (formal grammar)</language>\n"
+ " </langusage>\n"
+ "\n"
+ " <revisiondesc>\n"
+ " <slist>\n"
+ " <sitem>1997-01-15 : Skeleton draft by TB</sitem>\n"
+ " <sitem>1997-01-24 : Fleshed out by sjd</sitem>\n"
+ " <sitem>1997-04-08 : Substantive draft</sitem>\n"
+ " <sitem>1997-06-30 : Public draft</sitem>\n"
+ " <sitem>1997-08-01 : Public draft</sitem>\n"
+ " <sitem>1997-08-05 : Prose/organization work by sjd</sitem>\n"
+ " <sitem>1997-10-14: Conformance and design principles; a bit of cleanup by elm</sitem>\n"
+ " <sitem>1997-11-07: Update for editorial issues per issues doc, by sjd.</sitem>\n"
+ " <sitem>1997-12-01: Update for editorial issues per issues doc in preparation for F2F meeting, by sjd.</sitem>\n"
+ " <sitem>1998-01-13: Editorial cleanup, addition of new design principles, by elm.</sitem>\n"
+ " <sitem>1998-02-27: Splitting out of XLink and XPointer, by elm.</sitem>\n"
+ " <sitem>1998-03-03: Moved most of the XPointer locator stuff here. elm</sitem>\n"
+ " <sitem>1999-04-24: Editorial rewrites to represent new ideas on XLink, especially the inclusion of arcs. bent</sitem>\n"
+ " <sitem>1999-05-05: Prose/organization work by dorchard. Moved much of the semantics section around, from: locators, link semantics, remote resource semantics, local resource semantics; to: resource semantics, locators, behavior semantics, link semantics, arc semantics</sitem>\n"
+ " <sitem>1999-05-12: Prose/organization work. Re-organized some of the sections, removed XML constructs from the document, added descriptive prose, edited document text for clarity. Rewrote the link recognition section. bent</sitem>\n"
+ " <sitem>1999-05-17: Further prose work. Added non-normative examples. Clarified arcs. bent</sitem>\n"
+ " <sitem>1999-05-23: Edited for grammar and clarity. bent</sitem>\n"
+ " <sitem>1999-05-27: Final once-over before sending to group. Fixed sjd's email address. bent</sitem>\n"
+ " </slist>\n"
+ " </revisiondesc>\n"
     "</header>\n"
     "\n"
     "<body>\n"
- " <div1><?Pub Dtl?>\n"
- " <head>Introduction</head>\n"
- " <p>This specification defines constructs that may be inserted into XML DTDs, schemas, and document instances to describe links between objects. A <termref def=\"dt-link\">link</termref>, as the term is used here, is an explicit relationship between two or more data objects or portions of data objects. This specification is concerned with the syntax used to assert link existence and describe link characteristics. Implicit (unasserted) relationships, for example that of one word to the next or that of a word in a text to its entry in an on-line dictionary are obviously important, but outside its scope.</p>\n"
- " <p>Links are asserted by <xtermref href=\"WD-xml-lang.html#dt-element\">elements </xtermref> contained in <xtermref href=\"WD-xml-lang.html#dt-xml-doc\">XML document instances</xtermref>. The simplest case is very like an HTML <code>A</code> link, and has these characteristics:\n"
- " <ulist>\n"
- " <item><p>The link is expressed at one of its ends (similar to the <code>A</code> element in some document)</p></item>\n"
- " <item><p>Users can only initiate travel from that end to the other</p></item>\n"
- " <item><p>The link's effect on windows, frames, go-back lists, stylesheets in use, and so on is mainly determined by browsers, not by the link itself. For example, traveral of <code>A</code> links normally replaces the current view, perhaps with a user option to open a new window.</p></item>\n"
- " <item><p>The link goes to only one destination (although a server may have great freedom in finding or dynamically creating that destination).</p></item>\n"
- " </ulist>\n"
- " </p>\n"
- " <p>While this set of characteristics is already very powerful and obviously has proven itself highly useful and effective, each of these assumptions also limits the range of hypertext functionality. The linking model defined here provides ways to create links that go beyond each of these specific characteristics, thus providing features previously available mostly in dedicated hypermedia systems.\n"
- " </p>\n"
+ " <div1><?Pub Dtl?>\n"
+ " <head>Introduction</head>\n"
+ " <p>This specification defines constructs that may be inserted into XML DTDs, schemas, and document instances to describe links between objects. A <termref def=\"dt-link\">link</termref>, as the term is used here, is an explicit relationship between two or more data objects or portions of data objects. This specification is concerned with the syntax used to assert link existence and describe link characteristics. Implicit (unasserted) relationships, for example that of one word to the next or that of a word in a text to its entry in an on-line dictionary are obviously important, but outside its scope.</p>\n"
+ " <p>Links are asserted by <xtermref href=\"WD-xml-lang.html#dt-element\">elements </xtermref> contained in <xtermref href=\"WD-xml-lang.html#dt-xml-doc\">XML document instances</xtermref>. The simplest case is very like an HTML <code>A</code> link, and has these characteristics:\n"
+ " <ulist>\n"
+ " <item><p>The link is expressed at one of its ends (similar to the <code>A</code> element in some document)</p></item>\n"
+ " <item><p>Users can only initiate travel from that end to the other</p></item>\n"
+ " <item><p>The link's effect on windows, frames, go-back lists, stylesheets in use, and so on is mainly determined by browsers, not by the link itself. For example, traveral of <code>A</code> links normally replaces the current view, perhaps with a user option to open a new window.</p></item>\n"
+ " <item><p>The link goes to only one destination (although a server may have great freedom in finding or dynamically creating that destination).</p></item>\n"
+ " </ulist>\n"
+ " </p>\n"
+ " <p>While this set of characteristics is already very powerful and obviously has proven itself highly useful and effective, each of these assumptions also limits the range of hypertext functionality. The linking model defined here provides ways to create links that go beyond each of these specific characteristics, thus providing features previously available mostly in dedicated hypermedia systems.\n"
+ " </p>\n"
     "\n"
     "<div2>\n"
- " <head>Origin and Goals</head>\n"
- " <p>Following is a summary of the design principles governing XLink:\n"
- " <olist>\n"
- " <item><p>XLink must be straightforwardly usable over the Internet. </p></item>\n"
- " <item><p>XLink must be usable by a wide variety of link usage domains and classes of linking application software.</p></item>\n"
- " <item><p>XLink must support HTML 4.0 linking constructs.</p></item>\n"
- " <item><p>The XLink expression language must be XML.</p></item>\n"
- " <item><p>The XLink design must be formal, concise, and illustrative.</p></item>\n"
- " <item><p>XLinks must be human-readable and human-writable.</p></item>\n"
- " <item><p>XLinks may reside within or outside the documents in which the\n"
- " participating resources reside. </p></item>\n"
- " <item><p>XLink must represent the abstract structure and significance of links.</p></item>\n"
- " <item><p>XLink must be feasible to implement.</p></item>\n"
- " <item><p>XLink must be informed by knowledge of established hypermedia systems and standards.</p></item>\n"
- " </olist>\n"
- " </p>\n"
+ " <head>Origin and Goals</head>\n"
+ " <p>Following is a summary of the design principles governing XLink:\n"
+ " <olist>\n"
+ " <item><p>XLink must be straightforwardly usable over the Internet. </p></item>\n"
+ " <item><p>XLink must be usable by a wide variety of link usage domains and classes of linking application software.</p></item>\n"
+ " <item><p>XLink must support HTML 4.0 linking constructs.</p></item>\n"
+ " <item><p>The XLink expression language must be XML.</p></item>\n"
+ " <item><p>The XLink design must be formal, concise, and illustrative.</p></item>\n"
+ " <item><p>XLinks must be human-readable and human-writable.</p></item>\n"
+ " <item><p>XLinks may reside within or outside the documents in which the\n"
+ " participating resources reside. </p></item>\n"
+ " <item><p>XLink must represent the abstract structure and significance of links.</p></item>\n"
+ " <item><p>XLink must be feasible to implement.</p></item>\n"
+ " <item><p>XLink must be informed by knowledge of established hypermedia systems and standards.</p></item>\n"
+ " </olist>\n"
+ " </p>\n"
     "</div2>\n"
     "<!--Changed the list of requirements to reflect current XLink requirements\n"
     "document. bent-->\n"
     "\n"
     "<div2>\n"
- " <head>Relationship to Existing Standards</head>\n"
- " <p>Three standards have been especially influential:\n"
- " <ulist>\n"
- " <item><p><emph>HTML:</emph> Defines several SGML element types that represent links.</p></item>\n"
- " <item><p><emph>HyTime:</emph> Defines inline and out-of-line link structures and some semantic features, including traversal control and presentation of objects. <!--Changed from \"placement of objects into a display or other space\" -elm-->\n"
- " </p></item>\n"
- " <item><p><emph>Text Encoding Initiative Guidelines (TEI P3):</emph> Provides structures for creating links, aggregate objects, and link collections out of them.</p></item>\n"
- " </ulist>\n"
- " </p>\n"
- " <p>Many other linking systems have also informed this design, especially Dexter, FRESS, MicroCosm, and InterMedia.</p>\n"
+ " <head>Relationship to Existing Standards</head>\n"
+ " <p>Three standards have been especially influential:\n"
+ " <ulist>\n"
+ " <item><p><emph>HTML:</emph> Defines several SGML element types that represent links.</p></item>\n"
+ " <item><p><emph>HyTime:</emph> Defines inline and out-of-line link structures and some semantic features, including traversal control and presentation of objects. <!--Changed from \"placement of objects into a display or other space\" -elm-->\n"
+ " </p></item>\n"
+ " <item><p><emph>Text Encoding Initiative Guidelines (TEI P3):</emph> Provides structures for creating links, aggregate objects, and link collections out of them.</p></item>\n"
+ " </ulist>\n"
+ " </p>\n"
+ " <p>Many other linking systems have also informed this design, especially Dexter, FRESS, MicroCosm, and InterMedia.</p>\n"
     "</div2>\n"
     "\n"
     "<div2>\n"
- " <head>Terminology</head>\n"
- " <p>The following basic terms apply in this document. <!--<IMG\n"
- " SRC=\"local://./linkdiag.gif\">(figure to be inserted)-->\n"
- " <glist>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-arc\" term=\"Arc\">arc</termdef></label>\n"
- " <def><p>A symbolic representation of traversal behavior in links, especially the direction, context and timing of traversal.</p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-eltree\" term=\"Element Tree\">element tree</termdef></label>\n"
- " <def><p>A representation of the relevant structure specified by the tags and attributes in an XML document, based on \"groves\" as defined in the ISO DSSSL standard. </p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-inline\" term=\"In-Line Link\">inline link</termdef></label>\n"
- " <def><p>Abstractly, a <termref def=\"dt-link\">link</termref> which serves as one of its own <termref def=\"dt-resource\">resources</termref>. Concretely, a link where the content of the <termref def=\"dt-linkel\">linking element</termref> serves as a <termref def=\"dt-particip-resource\">participating resource</termref>.\n"
- " HTML <code>A</code>, HyTime <code>clink</code>, and TEI <code>XREF</code>\n"
- " are all inline links.</p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-link\" term=\"Link\">link</termdef></label>\n"
- " <def><p>An explicit relationship between two or more data objects or portions of data objects.</p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-linkel\" term=\"Linking Element\">linking element </termdef></label>\n"
- " <def><p>An <xtermref href=\"WD-xml-lang.html#dt-element\">element</xtermref> that asserts the existence and describes the characteristics of a <termref def=\"dt-link\"> link</termref>.</p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-local-resource\" term=\"Local Resource\">local resource</termdef></label>\n"
- " <def><p>The content of an <termref def=\"dt-inline\">inline</termref>linking element. Note that the content of the linking element could be explicitly pointed to by means of a regular <termref def=\"dt-locator\">locator</termref> in the same linking element, in which case the resource is considered <termref def=\"dt-remote-resource\"> remote</termref>, not local.</p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-locator\" term=\"Locator\">locator</termdef> </label>\n"
- " <def><p>Data, provided as part of a link, which identifies a\n"
- " <termref def=\"dt-resource\">resource</termref>.</p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-multidir\" term=\"Multi-Directional Link\">multidirectional link</termdef></label>\n"
- " <def><p>A <termref def=\"dt-link\">link</termref> whose <termref def=\"dt-traversal\"> traversal</termref> can be initiated from more than one of its <termref def=\"dt-particip-resource\"> participating resources</termref>. Note that being able to \"go back\" after following a one-directional link does not make the link multidirectional.</p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-outofline\" term=\"Out-of-line Link\">out-of-line link</termdef></label>\n"
- " <def><p>A <termref def=\"dt-link\">link</termref> whose content does not serve as one of the link's <termref def=\"dt-particip-resource\">participating resources </termref>. Such links presuppose a notion like <termref def=\"dt-xlg\">extended link groups</termref>, which instruct application software where to look for links. Out-of-line links are generally required for supporting multidirectional <termref def=\"dt-traversal\">traversal</termref> and for allowing read-only resources to have outgoing links.</p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-parsedq\" term=\"Parsed\">parsed</termdef></label> <def><p>In the context of link behavior, a parsed link is any link whose content is transcluded into the document where the link originated. The use of the term \"parsed\" directly refers to the concept in XML of a\n"
- " parsed entity.</p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-particip-resource\" term=\"Participating Resource\"> participating resource</termdef></label>\n"
- " <def><p>A <termref def=\"dt-resource\">resource</termref> that belongs to a link. All resources are potential contributors to a link; participating resources are the actual contributors to a particular link.</p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-remote-resource\" term=\"Remote Resource\">remote resource</termdef></label>\n"
- " <def><p>Any participating resource of a link that is pointed to with a locator. </p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-resource\" term=\"Resource\">resource</termdef></label>\n"
- " <def><p>In the abstract sense, an addressable unit of information or service that is participating in a <termref def=\"dt-link\">link</termref>. Examples include files, images, documents, programs, and query results. Concretely, anything reachable by the use of a <termref def=\"dt-locator\">locator</termref> in some <termref def=\"dt-linkel\">linking element</termref>. Note that this term and its definition are taken from the basic specifications governing the World Wide Web. <!--Joel notes: need link here. bent asks: A link?-->\n"
- " </p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-subresource\" term=\"sub-Resource\">sub-resource</termdef></label>\n"
- " <def><p>A portion of a resource, pointed to as the precise destination of a link. As one example, a link might specify that an entire document be retrieved and displayed, but that some specific part(s) of it is the specific linked data, to be treated in an application-appropriate manner such as indication by highlighting, scrolling, etc.</p></def>\n"
- " </gitem>\n"
- " <gitem>\n"
- " <label><termdef id=\"dt-traversal\" term=\"Traversal\">traversal</termdef></label>\n"
- " <def><p>The action of using a <termref def=\"dt-link\">link</termref>; that is, of accessing a <termref def=\"dt-resource\">resource</termref>. Traversal may be initiated by a user action (for example, clicking on the displayed content of a <termref def=\"dt-linkel\">linking element</termref>) or occur under program control.</p></def>\n"
- " </gitem>\n"
- " </glist>\n"
- " </p>\n"
+ " <head>Terminology</head>\n"
+ " <p>The following basic terms apply in this document. <!--<IMG\n"
+ " SRC=\"local://./linkdiag.gif\">(figure to be inserted)-->\n"
+ " <glist>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-arc\" term=\"Arc\">arc</termdef></label>\n"
+ " <def><p>A symbolic representation of traversal behavior in links, especially the direction, context and timing of traversal.</p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-eltree\" term=\"Element Tree\">element tree</termdef></label>\n"
+ " <def><p>A representation of the relevant structure specified by the tags and attributes in an XML document, based on \"groves\" as defined in the ISO DSSSL standard. </p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-inline\" term=\"In-Line Link\">inline link</termdef></label>\n"
+ " <def><p>Abstractly, a <termref def=\"dt-link\">link</termref> which serves as one of its own <termref def=\"dt-resource\">resources</termref>. Concretely, a link where the content of the <termref def=\"dt-linkel\">linking element</termref> serves as a <termref def=\"dt-particip-resource\">participating resource</termref>.\n"
+ " HTML <code>A</code>, HyTime <code>clink</code>, and TEI <code>XREF</code>\n"
+ " are all inline links.</p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-link\" term=\"Link\">link</termdef></label>\n"
+ " <def><p>An explicit relationship between two or more data objects or portions of data objects.</p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-linkel\" term=\"Linking Element\">linking element </termdef></label>\n"
+ " <def><p>An <xtermref href=\"WD-xml-lang.html#dt-element\">element</xtermref> that asserts the existence and describes the characteristics of a <termref def=\"dt-link\"> link</termref>.</p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-local-resource\" term=\"Local Resource\">local resource</termdef></label>\n"
+ " <def><p>The content of an <termref def=\"dt-inline\">inline</termref>linking element. Note that the content of the linking element could be explicitly pointed to by means of a regular <termref def=\"dt-locator\">locator</termref> in the same linking element, in which case the resource is considered <termref def=\"dt-remote-resource\"> remote</termref>, not local.</p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-locator\" term=\"Locator\">locator</termdef> </label>\n"
+ " <def><p>Data, provided as part of a link, which identifies a\n"
+ " <termref def=\"dt-resource\">resource</termref>.</p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-multidir\" term=\"Multi-Directional Link\">multidirectional link</termdef></label>\n"
+ " <def><p>A <termref def=\"dt-link\">link</termref> whose <termref def=\"dt-traversal\"> traversal</termref> can be initiated from more than one of its <termref def=\"dt-particip-resource\"> participating resources</termref>. Note that being able to \"go back\" after following a one-directional link does not make the link multidirectional.</p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-outofline\" term=\"Out-of-line Link\">out-of-line link</termdef></label>\n"
+ " <def><p>A <termref def=\"dt-link\">link</termref> whose content does not serve as one of the link's <termref def=\"dt-particip-resource\">participating resources </termref>. Such links presuppose a notion like <termref def=\"dt-xlg\">extended link groups</termref>, which instruct application software where to look for links. Out-of-line links are generally required for supporting multidirectional <termref def=\"dt-traversal\">traversal</termref> and for allowing read-only resources to have outgoing links.</p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-parsedq\" term=\"Parsed\">parsed</termdef></label> <def><p>In the context of link behavior, a parsed link is any link whose content is transcluded into the document where the link originated. The use of the term \"parsed\" directly refers to the concept in XML of a\n"
+ " parsed entity.</p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-particip-resource\" term=\"Participating Resource\"> participating resource</termdef></label>\n"
+ " <def><p>A <termref def=\"dt-resource\">resource</termref> that belongs to a link. All resources are potential contributors to a link; participating resources are the actual contributors to a particular link.</p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-remote-resource\" term=\"Remote Resource\">remote resource</termdef></label>\n"
+ " <def><p>Any participating resource of a link that is pointed to with a locator. </p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-resource\" term=\"Resource\">resource</termdef></label>\n"
+ " <def><p>In the abstract sense, an addressable unit of information or service that is participating in a <termref def=\"dt-link\">link</termref>. Examples include files, images, documents, programs, and query results. Concretely, anything reachable by the use of a <termref def=\"dt-locator\">locator</termref> in some <termref def=\"dt-linkel\">linking element</termref>. Note that this term and its definition are taken from the basic specifications governing the World Wide Web. <!--Joel notes: need link here. bent asks: A link?-->\n"
+ " </p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-subresource\" term=\"sub-Resource\">sub-resource</termdef></label>\n"
+ " <def><p>A portion of a resource, pointed to as the precise destination of a link. As one example, a link might specify that an entire document be retrieved and displayed, but that some specific part(s) of it is the specific linked data, to be treated in an application-appropriate manner such as indication by highlighting, scrolling, etc.</p></def>\n"
+ " </gitem>\n"
+ " <gitem>\n"
+ " <label><termdef id=\"dt-traversal\" term=\"Traversal\">traversal</termdef></label>\n"
+ " <def><p>The action of using a <termref def=\"dt-link\">link</termref>; that is, of accessing a <termref def=\"dt-resource\">resource</termref>. Traversal may be initiated by a user action (for example, clicking on the displayed content of a <termref def=\"dt-linkel\">linking element</termref>) or occur under program control.</p></def>\n"
+ " </gitem>\n"
+ " </glist>\n"
+ " </p>\n"
     "</div2>\n"
     "\n"
     "<div2>\n"
- " <head>Notation</head>\n"
- " <p>The formal grammar for <termref def=\"dt-locator\">locators</termref> is given using a simple Extended Backus-Naur Form (EBNF) location, as described in <xspecref href=\"
http://www.w3.org/TR/REC-xml#sec-notation\">the XML specification</xspecref>.</p>\n"
- " <!-- fixed link to XML spec - bent -->\n"
+ " <head>Notation</head>\n"
+ " <p>The formal grammar for <termref def=\"dt-locator\">locators</termref> is given using a simple Extended Backus-Naur Form (EBNF) location, as described in <xspecref href=\"http://www.w3.org/TR/REC-xml#sec-notation\">the XML specification</xspecref>.</p>\n"
+ " <!-- fixed link to XML spec - bent -->\n"
     "</div2>\n"
     "</div1>\n"
     "\n"
     "<div1 id=\"addressing\"><?Pub Dtl?>\n"
- " <head>Locator Syntax</head>\n"
- " <p>The locator for a <termref def=\"dt-resource\">resource</termref> is typically provided by means of a Uniform Resource Identifier, or URI. XPointers can be used in conjunction with the URI structure, as fragment identifiers, to specify a more precise sub-resource. </p>\n"
- " <!-- Removed the discussion of queries from the previous paragraph, due to contention within the WG. bent -->\n"
- " <p>A locator generally contains a URI, as described in IETF RFCs <bibref ref=\"rfc1738\"/> and <bibref ref=\"rfc1808\"/>. As these RFCs state, the URI may include a trailing <emph>query</emph> (marked by a leading \"<code>?</code>\"), and be followed by a \"<code>#</code>\" and a <emph>fragment identifier</emph>, with the query interpreted by the host providing the indicated resource, and the interpretation of the fragment identifier dependent on the data type of the indicated resource.</p>\n"
- " <!--Is there some restriction on URNs having queries and/or fragment identifiers? Since these RFCs don't mention URIs explicitly, should the wording here lead from URLs to URIs more explicitly? -elm-->\n"
- " <p>In order to locate XML documents and portions of documents, a locator value may contain either a <xtermref href=\"http://www.w3.org/Addressing/rfc1738.txt\"> URI</xtermref> or a fragment identifier, or both. Any fragment identifier for pointing into XML must be an <xtermref href=\"http://www.w3.org/TR/WD-xptr#dt-xpointer\"> XPointer</xtermref>.</p>\n"
- " <p>Special syntax may be used to request the use of particular processing models in accessing the locator's resource. This is designed to reflect the realities of network operation, where it may or may not be desirable to exercise fine control over the distribution of work between local and remote processors. \n"
- " <scrap id=\"locator\" lang=\"ebnf\">\n"
- " <head>Locator</head>\n"
- " <prod id=\"nt-locator\">\n"
- " <lhs>Locator</lhs>\n"
- " <rhs><nt def=\"nt-uri\">URI</nt></rhs>\n"
- " <rhs>| <nt def=\"nt-connector\">Connector</nt> (<xnt href=\"http://www.w3.org/TR/WD-xptr\">XPointer</xnt> | <xnt href=\"WD-xml-lang.html#NT-Name\">Name</xnt>)</rhs>\n"
- " <rhs>| <nt def=\"nt-uri\">URI</nt> <nt def=\"nt-connector\">Connector</nt> (<xnt href=\"http://www.w3.org/TR/WD-xptr\">XPointer</xnt> | <xnt href=\"WD-xml-lang.html#NT-Name\">Name</xnt>)</rhs>\n"
- " </prod>\n"
- " <prod id=\"nt-connector\">\n"
- " <lhs>Connector</lhs><rhs>'#' | '|'</rhs>\n"
- " </prod>\n"
- " <prod id=\"nt-uri\">\n"
- " <lhs>URI</lhs><rhs><xnt href=\"WD-xml-lang.html#NT-URLchar\">URIchar*</xnt></rhs>\n"
- " </prod>\n"
- " </scrap>\n"
- " </p>\n"
- " <p><termdef id=\"dt-designated\" term=\"Designated Resource\">In this discussion, the term <term>designated resource</term> refers to the resource which an entire locator serves to locate.</termdef> The following rules apply:\n"
- " <ulist>\n"
- " <item>\n"
- " <p><termdef id=\"dt-containing-resource\" term=\"Containing Resource\"> The URI, if provided, locates a resource called the <term>containing resource</term>.</termdef></p>\n"
- " </item>\n"
- " <item>\n"
- " <p>If the URI is not provided, the containing resource is considered to be the document in which the linking element is contained. \n"
- " </p></item>\n"
- " <item>\n"
- " <p><termdef id=\"dt-sub-resource\" term=\"Sub-Resource\">If an XPointer is provided, the designated resource is a <term>sub-resource</term>\n"
- " of the containing resource; otherwise the designated resource is the\n"
- " containing resource.</termdef></p>\n"
- " </item>\n"
- " <!--Is this now incorrect, given the nature of the switch from here() to origin()? -elm \n"
- " Oy, yes, i think so. it will require some fun wording, though, so i haven't fixed it yet here -sjd-->\n"
- " <item>\n"
- " <p>If the <nt def=\"nt-connector\">Connector</nt> is followed directly by a <xnt href=\"http://www.w3.org/TR/REC-xml#NT-Name\">Name</xnt>, the <xnt href=\"http://www.w3.org/TR/REC-xml#NT-Name\">Name</xnt> is shorthand for the XPointer\"<code>id(Name)</code>\"; that is, the sub-resource is the element in the containing resource that has an XML <xtermref href=\"http://www.w3.org/TR/REC-xml#sec-attrtypes\">ID attribute</xtermref> whose value <xtermref href=\"http://www.w3.org/TR/REC-xml#dt-match\">matches</xtermref> the <xnt href=\"http://www.w3.org/TR/REC-xml#NT-Name\">Name</xnt>. This shorthand is to encourage use of the robust <code>id</code> addressing mode.</p>\n"
- " </item>\n"
- " <!-- fixed links to the XML recommendation - bent -->\n"
- " <item>\n"
- " <p>If the connector is \"<code>#</code>\", this signals an intent that the containing resource is to be fetched as a whole from the host that provides it, and that the XPointer processing to extract the sub-resource\n"
- " is to be performed on the client, that is to say on the same system where the linking element is recognized and processed.</p>\n"
- " </item>\n"
- " <item>\n"
- " <p>If the connector is \"<code>|</code>\", no intent is signaled as to what processing model is to be used to go about accessing the designated resource.</p>\n"
- " </item>\n"
- " </ulist>\n"
- " </p>\n"
- " <p>Note that the definition of a URI includes an optional query component. </p>\n"
- " <p>In the case where the URI contains a query (to be interpreted by the server), information providers and authors of server software are urged to use queries as follows: \n"
- " <scrap id=\"querysyntax\" lang=\"ebnf\">\n"
- " <head>Query</head>\n"
- " <prod id=\"nt-query\">\n"
- " <lhs>Query</lhs><rhs>'XML-XPTR=' (<xnt href=\"http://www.w3.org/TR/WD-xptr\"> XPointer</xnt> | <xnt href=\"http://www.w3.org/TR/REC-xml#NT-Name\">Name</xnt>)</rhs>\n"
- " </prod>\n"
- " </scrap>\n"
- " </p>\n"
- " <!-- fixed link to XML recommendation - bent -->\n"
+ " <head>Locator Syntax</head>\n"
+ " <p>The locator for a <termref def=\"dt-resource\">resource</termref> is typically provided by means of a Uniform Resource Identifier, or URI. XPointers can be used in conjunction with the URI structure, as fragment identifiers, to specify a more precise sub-resource. </p>\n"
+ " <!-- Removed the discussion of queries from the previous paragraph, due to contention within the WG. bent -->\n"
+ " <p>A locator generally contains a URI, as described in IETF RFCs <bibref ref=\"rfc1738\"/> and <bibref ref=\"rfc1808\"/>. As these RFCs state, the URI may include a trailing <emph>query</emph> (marked by a leading \"<code>?</code>\"), and be followed by a \"<code>#</code>\" and a <emph>fragment identifier</emph>, with the query interpreted by the host providing the indicated resource, and the interpretation of the fragment identifier dependent on the data type of the indicated resource.</p>\n"
+ " <!--Is there some restriction on URNs having queries and/or fragment identifiers? Since these RFCs don't mention URIs explicitly, should the wording here lead from URLs to URIs more explicitly? -elm-->\n"
+ " <p>In order to locate XML documents and portions of documents, a locator value may contain either a <xtermref href=\"http://www.w3.org/Addressing/rfc1738.txt\"> URI</xtermref> or a fragment identifier, or both. Any fragment identifier for pointing into XML must be an <xtermref href=\"http://www.w3.org/TR/WD-xptr#dt-xpointer\"> XPointer</xtermref>.</p>\n"
+ " <p>Special syntax may be used to request the use of particular processing models in accessing the locator's resource. This is designed to reflect the realities of network operation, where it may or may not be desirable to exercise fine control over the distribution of work between local and remote processors. \n"
+ " <scrap id=\"locator\" lang=\"ebnf\">\n"
+ " <head>Locator</head>\n"
+ " <prod id=\"nt-locator\">\n"
+ " <lhs>Locator</lhs>\n"
+ " <rhs><nt def=\"nt-uri\">URI</nt></rhs>\n"
+ " <rhs>| <nt def=\"nt-connector\">Connector</nt> (<xnt href=\"http://www.w3.org/TR/WD-xptr\">XPointer</xnt> | <xnt href=\"WD-xml-lang.html#NT-Name\">Name</xnt>)</rhs>\n"
+ " <rhs>| <nt def=\"nt-uri\">URI</nt> <nt def=\"nt-connector\">Connector</nt> (<xnt href=\"http://www.w3.org/TR/WD-xptr\">XPointer</xnt> | <xnt href=\"WD-xml-lang.html#NT-Name\">Name</xnt>)</rhs>\n"
+ " </prod>\n"
+ " <prod id=\"nt-connector\">\n"
+ " <lhs>Connector</lhs><rhs>'#' | '|'</rhs>\n"
+ " </prod>\n"
+ " <prod id=\"nt-uri\">\n"
+ " <lhs>URI</lhs><rhs><xnt href=\"WD-xml-lang.html#NT-URLchar\">URIchar*</xnt></rhs>\n"
+ " </prod>\n"
+ " </scrap>\n"
+ " </p>\n"
+ " <p><termdef id=\"dt-designated\" term=\"Designated Resource\">In this discussion, the term <term>designated resource</term> refers to the resource which an entire locator serves to locate.</termdef> The following rules apply:\n"
+ " <ulist>\n"
+ " <item>\n"
+ " <p><termdef id=\"dt-containing-resource\" term=\"Containing Resource\"> The URI, if provided, locates a resource called the <term>containing resource</term>.</termdef></p>\n"
+ " </item>\n"
+ " <item>\n"
+ " <p>If the URI is not provided, the containing resource is considered to be the document in which the linking element is contained. \n"
+ " </p></item>\n"
+ " <item>\n"
+ " <p><termdef id=\"dt-sub-resource\" term=\"Sub-Resource\">If an XPointer is provided, the designated resource is a <term>sub-resource</term>\n"
+ " of the containing resource; otherwise the designated resource is the\n"
+ " containing resource.</termdef></p>\n"
+ " </item>\n"
+ " <!--Is this now incorrect, given the nature of the switch from here() to origin()? -elm \n"
+ " Oy, yes, i think so. it will require some fun wording, though, so i haven't fixed it yet here -sjd-->\n"
+ " <item>\n"
+ " <p>If the <nt def=\"nt-connector\">Connector</nt> is followed directly by a <xnt href=\"http://www.w3.org/TR/REC-xml#NT-Name\">Name</xnt>, the <xnt href=\"http://www.w3.org/TR/REC-xml#NT-Name\">Name</xnt> is shorthand for the XPointer\"<code>id(Name)</code>\"; that is, the sub-resource is the element in the containing resource that has an XML <xtermref href=\"http://www.w3.org/TR/REC-xml#sec-attrtypes\">ID attribute</xtermref> whose value <xtermref href=\"http://www.w3.org/TR/REC-xml#dt-match\">matches</xtermref> the <xnt href=\"http://www.w3.org/TR/REC-xml#NT-Name\">Name</xnt>. This shorthand is to encourage use of the robust <code>id</code> addressing mode.</p>\n"
+ " </item>\n"
+ " <!-- fixed links to the XML recommendation - bent -->\n"
+ " <item>\n"
+ " <p>If the connector is \"<code>#</code>\", this signals an intent that the containing resource is to be fetched as a whole from the host that provides it, and that the XPointer processing to extract the sub-resource\n"
+ " is to be performed on the client, that is to say on the same system where the linking element is recognized and processed.</p>\n"
+ " </item>\n"
+ " <item>\n"
+ " <p>If the connector is \"<code>|</code>\", no intent is signaled as to what processing model is to be used to go about accessing the designated resource.</p>\n"
+ " </item>\n"
+ " </ulist>\n"
+ " </p>\n"
+ " <p>Note that the definition of a URI includes an optional query component. </p>\n"
+ " <p>In the case where the URI contains a query (to be interpreted by the server), information providers and authors of server software are urged to use queries as follows: \n"
+ " <scrap id=\"querysyntax\" lang=\"ebnf\">\n"
+ " <head>Query</head>\n"
+ " <prod id=\"nt-query\">\n"
+ " <lhs>Query</lhs><rhs>'XML-XPTR=' (<xnt href=\"http://www.w3.org/TR/WD-xptr\"> XPointer</xnt> | <xnt href=\"http://www.w3.org/TR/REC-xml#NT-Name\">Name</xnt>)</rhs>\n"
+ " </prod>\n"
+ " </scrap>\n"
+ " </p>\n"
+ " <!-- fixed link to XML recommendation - bent -->\n"
     "</div1>\n"
     "\n"
     "<div1><?Pub Dtl?>\n"
- " <head>Link Recognition</head>\n"
- " <p>The existence of a <termref def=\"dt-link\">link</termref> is asserted by a <termref def=\"dt-linkel\">linking element</termref>. Linking elements must be recognized reliably by application software in order to provide appropriate display and behavior. There are several ways link recognition could be accomplished: for example, reserving element type names, reserving attributes names, leaving the matter of recognition entirely up to stylesheets and application software, or using the XLink <xtermref href=\"http://www.w3.org/TR/REC-xml-names/\">namespace</xtermref> to specify element names and attribute names that would be recognized by namespace and XLink-aware processors. Using element and attribute names within the XLink namespace provides a balance between giving users control of their own markup language design and keeping the identification of linking elements simple and unambiguous.</p>\n"
- " <p>The two approaches to identifying linking elements are relatively simple to implement. For example, here's how the HTML <code>A</code> element would be declared using attributes within the XLink namespace, and then how an element within the XLink namespace might do the same:\n"
- " <eg>&lt;A xlink:type=\"simple\" xlink:href=\"http://www.w3.org/TR/wd-xlink/\"\n"
+ " <head>Link Recognition</head>\n"
+ " <p>The existence of a <termref def=\"dt-link\">link</termref> is asserted by a <termref def=\"dt-linkel\">linking element</termref>. Linking elements must be recognized reliably by application software in order to provide appropriate display and behavior. There are several ways link recognition could be accomplished: for example, reserving element type names, reserving attributes names, leaving the matter of recognition entirely up to stylesheets and application software, or using the XLink <xtermref href=\"http://www.w3.org/TR/REC-xml-names/\">namespace</xtermref> to specify element names and attribute names that would be recognized by namespace and XLink-aware processors. Using element and attribute names within the XLink namespace provides a balance between giving users control of their own markup language design and keeping the identification of linking elements simple and unambiguous.</p>\n"
+ " <p>The two approaches to identifying linking elements are relatively simple to implement. For example, here's how the HTML <code>A</code> element would be declared using attributes within the XLink namespace, and then how an element within the XLink namespace might do the same:\n"
+ " <eg>&lt;A xlink:type=\"simple\" xlink:href=\"http://www.w3.org/TR/wd-xlink/\"\n"
     "xlink:title=\"The Xlink Working Draft\"&gt;The XLink Working Draft.&lt;/A&gt;</eg>\n"
- " <eg>&lt;xlink:simple href=\"http://www.w3.org/TR/wd-xlink/\"\n"
+ " <eg>&lt;xlink:simple href=\"http://www.w3.org/TR/wd-xlink/\"\n"
     "title=\"The XLink Working Draft\"&gt;The XLink Working Draft&lt;/xlink:simple&gt;</eg>\n"
- " Any arbitrary element can be made into an XLink by using the <code>xlink:type</code> attribute. And, of course, the explicit XLink elements may be used, as well. This document will go on to describe the linking attributes that are associated with linking elements. It may be assumed by the reader that these attributes would require the <code>xlink</code> namespace prefix if they existed within an arbitrary element, or that they may be used directly if they exist within an explicit Xlink element.</p>\n"
- " <!-- heavily modified this section to accomodate namespace-aware link recognition - bent -->\n"
+ " Any arbitrary element can be made into an XLink by using the <code>xlink:type</code> attribute. And, of course, the explicit XLink elements may be used, as well. This document will go on to describe the linking attributes that are associated with linking elements. It may be assumed by the reader that these attributes would require the <code>xlink</code> namespace prefix if they existed within an arbitrary element, or that they may be used directly if they exist within an explicit Xlink element.</p>\n"
+ " <!-- heavily modified this section to accomodate namespace-aware link recognition - bent -->\n"
     "</div1>\n"
     "\n"
     "<!-- Rewrote this entire section. - bent -->\n"
     "<div1>\n"
- " <head>Linking Attributes</head>\n"
- " <p>XLink has several attributes associated with the variety of links it may represent. These attributes define four main concepts: locators, arcs, behaviors, and semantics. <emph>Locators</emph> define where the actual resource is located. <emph>Arcs</emph> define the traversal of links. Where does the link come from? Where does it go to? All this information can be stored in the arc attributes. <emph>Behaviors</emph> define how the link is activated, and what the application should do with the resource being linked to. <emph>Semantics</emph> define useful information that the application may use, and enables the link for such specalized targets as constricted devices and accessibility software.</p>\n"
- " \n"
- " <div2 id=\"link-locators\">\n"
- " <head>Locator Attributes</head>\n"
- " <p>The only locator attribute at this time is <code>href</code>. This attribute must contain either a string in the form of a URI that defines the remote resource being linked to, a string containing a fragment identifier that links to a local resource, or a string containing a URI with a fragment identifier concacenated onto it.</p>\n"
- " </div2>\n"
- "\n"
- " <div2 id=\"link-arcs\">\n"
- " <head>Arc Attributes</head>\n"
- " <p>Arcs contain two attributes, <code>from</code> and <code>to</code>. The <code>from</code> attribute may contain a string containing the content of a <code>role</code> attribute from the resource being linked from. The purpose of the <code>from</code> attribute is to define where this link is being actuated from.</p>\n"
- " <p>The <code>to</code> attribute may contain a string containing the content of a <code>role</code> attribute from the resource being linked to. The purpose of the <code>to</code> attribute is to define where this link traverses to.</p>\n"
- " <p>The application may use this information in a number of ways, especially in a complex hypertext system, but it is mainly useful in providing context for application behavior.</p>\n"
- " <!-- I'm at a loss as to how to describe arcs more clearly than this. I don't want to devolve into discussions of directed graphs and n-ary links. -bent -->\n"
- " </div2>\n"
- "\n"
- " <div2 id=\"link-behaviors\">\n"
- " <head>Behavior Attributes</head>\n"
- " <p>There are two attributes associated with behavior: <code>show</code> and <code>actuate</code>. The <code>show</code> attribute defines how the remote resource is to be revealed to the user. It has three options: <code>new</code>, <code>parsed</code>, and <code>replace</code>. The <code>new</code> option indicates that the remote resource should be shown in a new window (or other device context) without replacing the previous content. The <code>parsed</code> option, relating directly to the XML concept of a parsed entity, indicates that the content should be integrated into the document from which the link was actuated. The <code>replace</code> option is the one most commonly seen on the World Wide Web, where the document being linked from is entirely replaced by the object being linked to.</p>\n"
- " <p>The <code>actuate</code> attribute defines how the link is initiated. It has two options: <code>user</code> and <code>auto</code>. The <code>user</code> option indicates that the link must be initiated by some sort of human-initiated selection, such as clicking on an HTML anchor. The <code>auto</code> option indicates that the link is automatically initiated when the application deems that the user has reached the link. It then follows the behavior set out in the <code>show</code> option.</p>\n"
- " <!-- Something should be put here in terms of an example. Idea: \"A\" link versus automatically updating encyclopedia. -bent -->\n"
- " </div2>\n"
- "\n"
- " <div2 id=\"link-semantics\">\n"
- " <head>Semantic Attributes</head>\n"
- " <p>There are two attributes associated with semantics, <code>role</code> and <code>title</code>. The <code>role</code> attribute is a generic string used to describe the function of the link's content. For example, a poem might have a link with a <code>role=\"stanza\"</code>. The <code>role</code> is also used as an identifier for the <code>from</code> and <code>to</code> attributes of arcs.</p>\n"
- " <p>The <code>title</code> attribute is designed to provide human-readable text describing the link. It is very useful for those who have text-based applications, whether that be due to a constricted device that cannot display the link's content, or if it's being read by an application to a visually-impaired user, or if it's being used to create a table of links. The <code>title</code> attribute contains a simple, descriptive string.</p>\n"
- " </div2>\n"
+ " <head>Linking Attributes</head>\n"
+ " <p>XLink has several attributes associated with the variety of links it may represent. These attributes define four main concepts: locators, arcs, behaviors, and semantics. <emph>Locators</emph> define where the actual resource is located. <emph>Arcs</emph> define the traversal of links. Where does the link come from? Where does it go to? All this information can be stored in the arc attributes. <emph>Behaviors</emph> define how the link is activated, and what the application should do with the resource being linked to. <emph>Semantics</emph> define useful information that the application may use, and enables the link for such specalized targets as constricted devices and accessibility software.</p>\n"
+ " \n"
+ " <div2 id=\"link-locators\">\n"
+ " <head>Locator Attributes</head>\n"
+ " <p>The only locator attribute at this time is <code>href</code>. This attribute must contain either a string in the form of a URI that defines the remote resource being linked to, a string containing a fragment identifier that links to a local resource, or a string containing a URI with a fragment identifier concacenated onto it.</p>\n"
+ " </div2>\n"
+ "\n"
+ " <div2 id=\"link-arcs\">\n"
+ " <head>Arc Attributes</head>\n"
+ " <p>Arcs contain two attributes, <code>from</code> and <code>to</code>. The <code>from</code> attribute may contain a string containing the content of a <code>role</code> attribute from the resource being linked from. The purpose of the <code>from</code> attribute is to define where this link is being actuated from.</p>\n"
+ " <p>The <code>to</code> attribute may contain a string containing the content of a <code>role</code> attribute from the resource being linked to. The purpose of the <code>to</code> attribute is to define where this link traverses to.</p>\n"
+ " <p>The application may use this information in a number of ways, especially in a complex hypertext system, but it is mainly useful in providing context for application behavior.</p>\n"
+ " <!-- I'm at a loss as to how to describe arcs more clearly than this. I don't want to devolve into discussions of directed graphs and n-ary links. -bent -->\n"
+ " </div2>\n"
+ "\n"
+ " <div2 id=\"link-behaviors\">\n"
+ " <head>Behavior Attributes</head>\n"
+ " <p>There are two attributes associated with behavior: <code>show</code> and <code>actuate</code>. The <code>show</code> attribute defines how the remote resource is to be revealed to the user. It has three options: <code>new</code>, <code>parsed</code>, and <code>replace</code>. The <code>new</code> option indicates that the remote resource should be shown in a new window (or other device context) without replacing the previous content. The <code>parsed</code> option, relating directly to the XML concept of a parsed entity, indicates that the content should be integrated into the document from which the link was actuated. The <code>replace</code> option is the one most commonly seen on the World Wide Web, where the document being linked from is entirely replaced by the object being linked to.</p>\n"
+ " <p>The <code>actuate</code> attribute defines how the link is initiated. It has two options: <code>user</code> and <code>auto</code>. The <code>user</code> option indicates that the link must be initiated by some sort of human-initiated selection, such as clicking on an HTML anchor. The <code>auto</code> option indicates that the link is automatically initiated when the application deems that the user has reached the link. It then follows the behavior set out in the <code>show</code> option.</p>\n"
+ " <!-- Something should be put here in terms of an example. Idea: \"A\" link versus automatically updating encyclopedia. -bent -->\n"
+ " </div2>\n"
+ "\n"
+ " <div2 id=\"link-semantics\">\n"
+ " <head>Semantic Attributes</head>\n"
+ " <p>There are two attributes associated with semantics, <code>role</code> and <code>title</code>. The <code>role</code> attribute is a generic string used to describe the function of the link's content. For example, a poem might have a link with a <code>role=\"stanza\"</code>. The <code>role</code> is also used as an identifier for the <code>from</code> and <code>to</code> attributes of arcs.</p>\n"
+ " <p>The <code>title</code> attribute is designed to provide human-readable text describing the link. It is very useful for those who have text-based applications, whether that be due to a constricted device that cannot display the link's content, or if it's being read by an application to a visually-impaired user, or if it's being used to create a table of links. The <code>title</code> attribute contains a simple, descriptive string.</p>\n"
+ " </div2>\n"
     "</div1>\n"
     "\n"
     "<div1 id=\"linking-elements\">\n"
- " <head>Linking Elements</head>\n"
- " <p>There are several kinds of linking elements in XLink: <code>simple</code> links, <code>locators</code>, <code>arcs</code>, and <code>extended</code> links. These elements may be instantiated via element declarations from the XLink namespace, or they may be instantiated via attribute declarations from the XLink namespace. Both kinds of instantiation are described in the definition of each linking element.</p>\n"
- " <p>The <code>simple</code> link is used to declare a link that approximates the functionality of the HTML <code>A</code> element. It has, however, a few added features to increase its value, including the potential declaration of semantics and behavior. The <code>locator</code> elements are used to define the resource being linked to. Some links may contain multiple locators, representing a choice of potential links to be traversed. The <code>arcs</code> are used to define the traversal semantics of the link. Finally, an <code>extended</code> linking element differs from a simple link in that it can connect any number of resources, not just one local resource (optionally) and one remote resource, and in that extended links are more often out-of-line than simple links.</p>\n"
+ " <head>Linking Elements</head>\n"
+ " <p>There are several kinds of linking elements in XLink: <code>simple</code> links, <code>locators</code>, <code>arcs</code>, and <code>extended</code> links. These elements may be instantiated via element declarations from the XLink namespace, or they may be instantiated via attribute declarations from the XLink namespace. Both kinds of instantiation are described in the definition of each linking element.</p>\n"
+ " <p>The <code>simple</code> link is used to declare a link that approximates the functionality of the HTML <code>A</code> element. It has, however, a few added features to increase its value, including the potential declaration of semantics and behavior. The <code>locator</code> elements are used to define the resource being linked to. Some links may contain multiple locators, representing a choice of potential links to be traversed. The <code>arcs</code> are used to define the traversal semantics of the link. Finally, an <code>extended</code> linking element differs from a simple link in that it can connect any number of resources, not just one local resource (optionally) and one remote resource, and in that extended links are more often out-of-line than simple links.</p>\n"
     "\n"
     "<div2 id=\"simple-links\">\n"
- " <head>Simple Links</head>\n"
- " <p id=\"dt-simplelink\"><termdef id=\"dt-simpleline\" term=\"Simple Link\"><term>Simple links</term> can be used for purposes that approximate the functionality of a basic HTML <code>A</code> link, but they can also support a limited amount of additional functionality. Simple links have only one locator and thus, for convenience, combine the functions of a linking element and a locator into a single element.</termdef> As a result of this combination, the simple linking element offers both a locator attribute and all the behavior and semantic attributes.</p>\n"
- " <p>The following are two examples of linking elements, each showing all the possible attributes that can be associated with a simple link. Here is the explicit XLink simple linking element.\n"
- " <eg>&lt;!ELEMENT xlink:simple ANY&gt;\n"
+ " <head>Simple Links</head>\n"
+ " <p id=\"dt-simplelink\"><termdef id=\"dt-simpleline\" term=\"Simple Link\"><term>Simple links</term> can be used for purposes that approximate the functionality of a basic HTML <code>A</code> link, but they can also support a limited amount of additional functionality. Simple links have only one locator and thus, for convenience, combine the functions of a linking element and a locator into a single element.</termdef> As a result of this combination, the simple linking element offers both a locator attribute and all the behavior and semantic attributes.</p>\n"
+ " <p>The following are two examples of linking elements, each showing all the possible attributes that can be associated with a simple link. Here is the explicit XLink simple linking element.\n"
+ " <eg>&lt;!ELEMENT xlink:simple ANY&gt;\n"
     "&lt;!ATTLIST xlink:slink\n"
- " href CDATA #REQUIRED\n"
- " role CDATA #IMPLIED\n"
- " title CDATA #IMPLIED\n"
- " show (new|parsed|replace) \"replace\"\n"
- " actuate (user|auto) \"user\"\n"
+ " href CDATA #REQUIRED\n"
+ " role CDATA #IMPLIED\n"
+ " title CDATA #IMPLIED\n"
+ " show (new|parsed|replace) \"replace\"\n"
+ " actuate (user|auto) \"user\"\n"
     "&gt;</eg>\n"
- " And here is how to make an arbitrary element into a simple link.\n"
- " <eg>&lt;!ELEMENT xlink:simple ANY&gt;\n"
+ " And here is how to make an arbitrary element into a simple link.\n"
+ " <eg>&lt;!ELEMENT xlink:simple ANY&gt;\n"
     "&lt;!ATTLIST foo\n"
- " xlink:type (simple|extended|locator|arc) #FIXED \"simple\" \n"
- " xlink:href CDATA #REQUIRED\n"
- " xlink:role CDATA #IMPLIED\n"
- " xlink:title CDATA #IMPLIED\n"
- " xlink:show (new|parsed|replace) \"replace\"\n"
- " xlink:actuate (user|auto) \"user\"\n"
+ " xlink:type (simple|extended|locator|arc) #FIXED \"simple\" \n"
+ " xlink:href CDATA #REQUIRED\n"
+ " xlink:role CDATA #IMPLIED\n"
+ " xlink:title CDATA #IMPLIED\n"
+ " xlink:show (new|parsed|replace) \"replace\"\n"
+ " xlink:actuate (user|auto) \"user\"\n"
     "&gt;</eg>\n"
- " Here is how the first example might look in a document:\n"
+ " Here is how the first example might look in a document:\n"
     "<eg>&lt;xlink:simple href=\"http://www.w3.org/TR/wd-xlink\" role=\"working draft\" \n"
- " title=\"The XLink Working Draft\" show=\"replace\" actuate=\"user\"&gt;\n"
+ " title=\"The XLink Working Draft\" show=\"replace\" actuate=\"user\"&gt;\n"
     "The XLink Working Draft.&lt;/xlink:simple&gt;</eg>\n"
     "<eg>&lt;foo xlink:href=\"http://www.w3.org/TR/wd-xlink\" xlink:role=\"working draft\"\n"
- " xlink:title=\"The XLink Working Draft\" xlink:show=\"new\" xlink:actuate=\"user\"&gt;\n"
+ " xlink:title=\"The XLink Working Draft\" xlink:show=\"new\" xlink:actuate=\"user\"&gt;\n"
     "The XLink Working Draft.&lt;/foo&gt;</eg>\n"
- " Alternately, a simple link could be as terse as this:\n"
+ " Alternately, a simple link could be as terse as this:\n"
     "<eg>&lt;foo xlink:href=\"#stanza1\"&gt;The First Stanza.&lt;/foo&gt;</eg>\n"
- " </p>\n"
- " <p>\n"
- " There are no constraints on the contents of a simple linking element. In\n"
- " the sample declaration above, it is given a content model of <code>ANY</code>\n"
- " to illustrate that any content model or declared content is acceptable. In\n"
- " a valid document, every element that is significant to XLink must still conform\n"
- " to the constraints expressed in its governing DTD.</p>\n"
- " <p>Note that it is meaningful to have an out-of-line simple link, although\n"
- " such links are uncommon. They are called \"one-ended\" and are typically used\n"
- " to associate discrete semantic properties with locations. The properties might\n"
- " be expressed by attributes on the link, the link's element type name, or in\n"
- " some other way, and are not considered full-fledged resources of the link.\n"
- " Most out-of-line links are extended links, as these have a far wider range\n"
- " of uses.</p>\n"
+ " </p>\n"
+ " <p>\n"
+ " There are no constraints on the contents of a simple linking element. In\n"
+ " the sample declaration above, it is given a content model of <code>ANY</code>\n"
+ " to illustrate that any content model or declared content is acceptable. In\n"
+ " a valid document, every element that is significant to XLink must still conform\n"
+ " to the constraints expressed in its governing DTD.</p>\n"
+ " <p>Note that it is meaningful to have an out-of-line simple link, although\n"
+ " such links are uncommon. They are called \"one-ended\" and are typically used\n"
+ " to associate discrete semantic properties with locations. The properties might\n"
+ " be expressed by attributes on the link, the link's element type name, or in\n"
+ " some other way, and are not considered full-fledged resources of the link.\n"
+ " Most out-of-line links are extended links, as these have a far wider range\n"
+ " of uses.</p>\n"
     "</div2>\n"
     "\n"
     "<div2 id=\"extended-link\">\n"
     "<head>Extended Links</head>\n"
- " <p><termdef id=\"dt-extendedlink\" term=\"Extended Link\">An <term>extended link</term> differs from a simple link in that it can connect any number of resources, not just one local resource (optionally) and one remote resource, and in that extended links are more often out-of-line than simple links.</termdef></p>\n"
- " <p>These additional capabilities of extended links are required for: \n"
- " <ulist>\n"
- " <item>\n"
- " <p>Enabling outgoing links in documents that cannot be modified to add an inline link</p>\n"
- " </item>\n"
- " <item>\n"
- " <p>Creating links to and from resources in formats with no native support for embedded links (such as most multimedia formats)</p>\n"
- " </item>\n"
- " <item>\n"
- " <p>Applying and filtering sets of relevant links on demand</p>\n"
- " </item>\n"
- " <item><p>Enabling other advanced hypermedia capabilities</p></item>\n"
- " </ulist>\n"
- " </p>\n"
- " <p>Application software might be expected to provide traversal among all of a link's participating resources (subject to semantic constraints outside the scope of this specification) and to signal the fact that a given resource or sub-resource participates in one or more links when it is displayed (even though there is no markup at exactly that point to signal it).</p>\n"
- " <p>A linking element for an extended link contains a series of <xtermref href=\"http://www.w3.org/TR/REC-xml/#dt-parentchild\">child elements</xtermref> that serve as locators and arcs. Because an extended link can have more than one remote resource, it separates out linking itself from the mechanisms used to locate each resource (whereas a simple link combines the two).</p>\n"
- " <p>The <code>xlink:type</code> attribute value for an extended link must be <code> extended</code>, if the link is being instantiated on an arbitrary element. Note that extended links introduce variants of the <code>show</code> and <code>actuate</code> behavior attributes. These attributes, the <code>showdefault</code> and <code>actuatedefault</code> define the same behavior as their counterparts. However, in this case, they are considered to define the default behavior for all the linking elements that they contain.</p>\n"
- " <p>However, when a linking element within an extended link has a <code>show</code> or <code>actuate</code> attribute of its own, that attribute overrides the defaults set on the extended linking element.</p>\n"
- " <p>The extended linking element itself retains those attributes relevant to the link as a whole, and to its local resource if any. Following are two sample declaration for an extended link. The first is an example of the explicit XLink extended link:\n"
- " \n"
+ " <p><termdef id=\"dt-extendedlink\" term=\"Extended Link\">An <term>extended link</term> differs from a simple link in that it can connect any number of resources, not just one local resource (optionally) and one remote resource, and in that extended links are more often out-of-line than simple links.</termdef></p>\n"
+ " <p>These additional capabilities of extended links are required for: \n"
+ " <ulist>\n"
+ " <item>\n"
+ " <p>Enabling outgoing links in documents that cannot be modified to add an inline link</p>\n"
+ " </item>\n"
+ " <item>\n"
+ " <p>Creating links to and from resources in formats with no native support for embedded links (such as most multimedia formats)</p>\n"
+ " </item>\n"
+ " <item>\n"
+ " <p>Applying and filtering sets of relevant links on demand</p>\n"
+ " </item>\n"
+ " <item><p>Enabling other advanced hypermedia capabilities</p></item>\n"
+ " </ulist>\n"
+ " </p>\n"
+ " <p>Application software might be expected to provide traversal among all of a link's participating resources (subject to semantic constraints outside the scope of this specification) and to signal the fact that a given resource or sub-resource participates in one or more links when it is displayed (even though there is no markup at exactly that point to signal it).</p>\n"
+ " <p>A linking element for an extended link contains a series of <xtermref href=\"http://www.w3.org/TR/REC-xml/#dt-parentchild\">child elements</xtermref> that serve as locators and arcs. Because an extended link can have more than one remote resource, it separates out linking itself from the mechanisms used to locate each resource (whereas a simple link combines the two).</p>\n"
+ " <p>The <code>xlink:type</code> attribute value for an extended link must be <code> extended</code>, if the link is being instantiated on an arbitrary element. Note that extended links introduce variants of the <code>show</code> and <code>actuate</code> behavior attributes. These attributes, the <code>showdefault</code> and <code>actuatedefault</code> define the same behavior as their counterparts. However, in this case, they are considered to define the default behavior for all the linking elements that they contain.</p>\n"
+ " <p>However, when a linking element within an extended link has a <code>show</code> or <code>actuate</code> attribute of its own, that attribute overrides the defaults set on the extended linking element.</p>\n"
+ " <p>The extended linking element itself retains those attributes relevant to the link as a whole, and to its local resource if any. Following are two sample declaration for an extended link. The first is an example of the explicit XLink extended link:\n"
+ " \n"
     "<eg>&lt;!ELEMENT xlink:extended ((xlink:arc | xlink:locator)*)>\n"
     "&lt;!ATTLIST xlink:extended\n"
- " role CDATA #IMPLIED\n"
- " title CDATA #IMPLIED\n"
- " showdefault (new|parsed|replace) #IMPLIED \n"
- " actuatedefault (user|auto) #IMPLIED &gt;</eg>\n"
+ " role CDATA #IMPLIED\n"
+ " title CDATA #IMPLIED\n"
+ " showdefault (new|parsed|replace) #IMPLIED \n"
+ " actuatedefault (user|auto) #IMPLIED &gt;</eg>\n"
     "\n"
- " The second is an example of an arbitrary element being used an extended link:\n"
+ " The second is an example of an arbitrary element being used an extended link:\n"
     "\n"
     "<eg>&lt;!ELEMENT foo ((xlink:arc | xlink:locator)*)>\n"
     "&lt;!ATTLIST foo\n"
- " xlink:type (simple|extended|locator|arc) #FIXED \"extended\"\n"
- " xlink:role CDATA #IMPLIED\n"
- " xlink:title CDATA #IMPLIED\n"
- " xlink:showdefault (new|parsed|replace) #IMPLIED \n"
- " xlink:actuatedefault (user|auto) #IMPLIED &gt;</eg>\n"
+ " xlink:type (simple|extended|locator|arc) #FIXED \"extended\"\n"
+ " xlink:role CDATA #IMPLIED\n"
+ " xlink:title CDATA #IMPLIED\n"
+ " xlink:showdefault (new|parsed|replace) #IMPLIED \n"
+ " xlink:actuatedefault (user|auto) #IMPLIED &gt;</eg>\n"
     "\n"
- " The following two examples demonstrate how each of the above might appear within a document instance. Note that the content of these examples would be other elements. For brevity's sake, they've been left blank. The first example shows how the link might appear, using an explicit XLink extended link:\n"
+ " The following two examples demonstrate how each of the above might appear within a document instance. Note that the content of these examples would be other elements. For brevity's sake, they've been left blank. The first example shows how the link might appear, using an explicit XLink extended link:\n"
     "\n"
     "<eg>&lt;xlink:extended role=\"address book\" title=\"Ben's Address Book\" showdefault=\"replace\" actuatedefault=\"user\"&gt; ... &lt;/xlink:extended&gt;</eg>\n"
     "\n"
- " And the second shows how the link might appear, using an arbitrary element:\n"
+ " And the second shows how the link might appear, using an arbitrary element:\n"
     "\n"
     "<eg>&lt;foo xlink:type=\"extended\" xlink:role=\"address book\" xlink:title=\"Ben's Address Book\" xlink:showdefault=\"replace\" xlink:actuatedefault=\"user\"&gt; ... &lt;/foo&gt;</eg>\n"
- " </p>\n"
+ " </p>\n"
     "\n"
     "</div2>\n"
     "\n"
     "<div2 id=\"xlink-arcs\">\n"
- " <head>Arc Elements</head>\n"
- " <p><termdef id=\"dt-arc\" term=\"Arc\">An <term>arc</term> is contained within an extended link for the purpose of defining traversal behavior.</termdef> More than one arc may be associated with a link. Otherwise, arc elements function exactly as the arc attributes might lead on to expect.</p>\n"
- " <!-- More here? -bent -->\n"
+ " <head>Arc Elements</head>\n"
+ " <p><termdef id=\"dt-arc\" term=\"Arc\">An <term>arc</term> is contained within an extended link for the purpose of defining traversal behavior.</termdef> More than one arc may be associated with a link. Otherwise, arc elements function exactly as the arc attributes might lead on to expect.</p>\n"
+ " <!-- More here? -bent -->\n"
     "</div2>\n"
     "\n"
     "</div1>\n"


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk