Alexander Steiger / tinyxml
Committer:
steiger
Date:
Sun Nov 21 00:49:17 2010 +0000
Revision:
0:7c97dcef700c

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
steiger 0:7c97dcef700c 1 /*
steiger 0:7c97dcef700c 2 www.sourceforge.net/projects/tinyxml
steiger 0:7c97dcef700c 3 Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
steiger 0:7c97dcef700c 4
steiger 0:7c97dcef700c 5 This software is provided 'as-is', without any express or implied
steiger 0:7c97dcef700c 6 warranty. In no event will the authors be held liable for any
steiger 0:7c97dcef700c 7 damages arising from the use of this software.
steiger 0:7c97dcef700c 8
steiger 0:7c97dcef700c 9 Permission is granted to anyone to use this software for any
steiger 0:7c97dcef700c 10 purpose, including commercial applications, and to alter it and
steiger 0:7c97dcef700c 11 redistribute it freely, subject to the following restrictions:
steiger 0:7c97dcef700c 12
steiger 0:7c97dcef700c 13 1. The origin of this software must not be misrepresented; you must
steiger 0:7c97dcef700c 14 not claim that you wrote the original software. If you use this
steiger 0:7c97dcef700c 15 software in a product, an acknowledgment in the product documentation
steiger 0:7c97dcef700c 16 would be appreciated but is not required.
steiger 0:7c97dcef700c 17
steiger 0:7c97dcef700c 18 2. Altered source versions must be plainly marked as such, and
steiger 0:7c97dcef700c 19 must not be misrepresented as being the original software.
steiger 0:7c97dcef700c 20
steiger 0:7c97dcef700c 21 3. This notice may not be removed or altered from any source
steiger 0:7c97dcef700c 22 distribution.
steiger 0:7c97dcef700c 23 */
steiger 0:7c97dcef700c 24
steiger 0:7c97dcef700c 25 #include <ctype.h>
steiger 0:7c97dcef700c 26 #include <stddef.h>
steiger 0:7c97dcef700c 27
steiger 0:7c97dcef700c 28 #include "tinyxml.h"
steiger 0:7c97dcef700c 29
steiger 0:7c97dcef700c 30 //#define DEBUG_PARSER
steiger 0:7c97dcef700c 31 #if defined( DEBUG_PARSER )
steiger 0:7c97dcef700c 32 # if defined( DEBUG ) && defined( _MSC_VER )
steiger 0:7c97dcef700c 33 # include <windows.h>
steiger 0:7c97dcef700c 34 # define TIXML_LOG OutputDebugString
steiger 0:7c97dcef700c 35 # else
steiger 0:7c97dcef700c 36 # define TIXML_LOG printf
steiger 0:7c97dcef700c 37 # endif
steiger 0:7c97dcef700c 38 #endif
steiger 0:7c97dcef700c 39
steiger 0:7c97dcef700c 40 // Note tha "PutString" hardcodes the same list. This
steiger 0:7c97dcef700c 41 // is less flexible than it appears. Changing the entries
steiger 0:7c97dcef700c 42 // or order will break putstring.
steiger 0:7c97dcef700c 43 TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] =
steiger 0:7c97dcef700c 44 {
steiger 0:7c97dcef700c 45 { "&amp;", 5, '&' },
steiger 0:7c97dcef700c 46 { "&lt;", 4, '<' },
steiger 0:7c97dcef700c 47 { "&gt;", 4, '>' },
steiger 0:7c97dcef700c 48 { "&quot;", 6, '\"' },
steiger 0:7c97dcef700c 49 { "&apos;", 6, '\'' }
steiger 0:7c97dcef700c 50 };
steiger 0:7c97dcef700c 51
steiger 0:7c97dcef700c 52 // Bunch of unicode info at:
steiger 0:7c97dcef700c 53 // http://www.unicode.org/faq/utf_bom.html
steiger 0:7c97dcef700c 54 // Including the basic of this table, which determines the #bytes in the
steiger 0:7c97dcef700c 55 // sequence from the lead byte. 1 placed for invalid sequences --
steiger 0:7c97dcef700c 56 // although the result will be junk, pass it through as much as possible.
steiger 0:7c97dcef700c 57 // Beware of the non-characters in UTF-8:
steiger 0:7c97dcef700c 58 // ef bb bf (Microsoft "lead bytes")
steiger 0:7c97dcef700c 59 // ef bf be
steiger 0:7c97dcef700c 60 // ef bf bf
steiger 0:7c97dcef700c 61
steiger 0:7c97dcef700c 62 const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
steiger 0:7c97dcef700c 63 const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
steiger 0:7c97dcef700c 64 const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
steiger 0:7c97dcef700c 65
steiger 0:7c97dcef700c 66 const int TiXmlBase::utf8ByteTable[256] =
steiger 0:7c97dcef700c 67 {
steiger 0:7c97dcef700c 68 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
steiger 0:7c97dcef700c 69 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
steiger 0:7c97dcef700c 70 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
steiger 0:7c97dcef700c 71 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20
steiger 0:7c97dcef700c 72 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30
steiger 0:7c97dcef700c 73 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
steiger 0:7c97dcef700c 74 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50
steiger 0:7c97dcef700c 75 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
steiger 0:7c97dcef700c 76 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range
steiger 0:7c97dcef700c 77 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid
steiger 0:7c97dcef700c 78 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
steiger 0:7c97dcef700c 79 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
steiger 0:7c97dcef700c 80 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
steiger 0:7c97dcef700c 81 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte
steiger 0:7c97dcef700c 82 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
steiger 0:7c97dcef700c 83 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte
steiger 0:7c97dcef700c 84 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
steiger 0:7c97dcef700c 85 };
steiger 0:7c97dcef700c 86
steiger 0:7c97dcef700c 87
steiger 0:7c97dcef700c 88 void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
steiger 0:7c97dcef700c 89 {
steiger 0:7c97dcef700c 90 const unsigned long BYTE_MASK = 0xBF;
steiger 0:7c97dcef700c 91 const unsigned long BYTE_MARK = 0x80;
steiger 0:7c97dcef700c 92 const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
steiger 0:7c97dcef700c 93
steiger 0:7c97dcef700c 94 if (input < 0x80)
steiger 0:7c97dcef700c 95 *length = 1;
steiger 0:7c97dcef700c 96 else if ( input < 0x800 )
steiger 0:7c97dcef700c 97 *length = 2;
steiger 0:7c97dcef700c 98 else if ( input < 0x10000 )
steiger 0:7c97dcef700c 99 *length = 3;
steiger 0:7c97dcef700c 100 else if ( input < 0x200000 )
steiger 0:7c97dcef700c 101 *length = 4;
steiger 0:7c97dcef700c 102 else
steiger 0:7c97dcef700c 103 { *length = 0; return; } // This code won't covert this correctly anyway.
steiger 0:7c97dcef700c 104
steiger 0:7c97dcef700c 105 output += *length;
steiger 0:7c97dcef700c 106
steiger 0:7c97dcef700c 107 // Scary scary fall throughs.
steiger 0:7c97dcef700c 108 switch (*length)
steiger 0:7c97dcef700c 109 {
steiger 0:7c97dcef700c 110 case 4:
steiger 0:7c97dcef700c 111 --output;
steiger 0:7c97dcef700c 112 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
steiger 0:7c97dcef700c 113 input >>= 6;
steiger 0:7c97dcef700c 114 case 3:
steiger 0:7c97dcef700c 115 --output;
steiger 0:7c97dcef700c 116 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
steiger 0:7c97dcef700c 117 input >>= 6;
steiger 0:7c97dcef700c 118 case 2:
steiger 0:7c97dcef700c 119 --output;
steiger 0:7c97dcef700c 120 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
steiger 0:7c97dcef700c 121 input >>= 6;
steiger 0:7c97dcef700c 122 case 1:
steiger 0:7c97dcef700c 123 --output;
steiger 0:7c97dcef700c 124 *output = (char)(input | FIRST_BYTE_MARK[*length]);
steiger 0:7c97dcef700c 125 }
steiger 0:7c97dcef700c 126 }
steiger 0:7c97dcef700c 127
steiger 0:7c97dcef700c 128
steiger 0:7c97dcef700c 129 /*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
steiger 0:7c97dcef700c 130 {
steiger 0:7c97dcef700c 131 // This will only work for low-ascii, everything else is assumed to be a valid
steiger 0:7c97dcef700c 132 // letter. I'm not sure this is the best approach, but it is quite tricky trying
steiger 0:7c97dcef700c 133 // to figure out alhabetical vs. not across encoding. So take a very
steiger 0:7c97dcef700c 134 // conservative approach.
steiger 0:7c97dcef700c 135
steiger 0:7c97dcef700c 136 // if ( encoding == TIXML_ENCODING_UTF8 )
steiger 0:7c97dcef700c 137 // {
steiger 0:7c97dcef700c 138 if ( anyByte < 127 )
steiger 0:7c97dcef700c 139 return isalpha( anyByte );
steiger 0:7c97dcef700c 140 else
steiger 0:7c97dcef700c 141 return 1; // What else to do? The unicode set is huge...get the english ones right.
steiger 0:7c97dcef700c 142 // }
steiger 0:7c97dcef700c 143 // else
steiger 0:7c97dcef700c 144 // {
steiger 0:7c97dcef700c 145 // return isalpha( anyByte );
steiger 0:7c97dcef700c 146 // }
steiger 0:7c97dcef700c 147 }
steiger 0:7c97dcef700c 148
steiger 0:7c97dcef700c 149
steiger 0:7c97dcef700c 150 /*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
steiger 0:7c97dcef700c 151 {
steiger 0:7c97dcef700c 152 // This will only work for low-ascii, everything else is assumed to be a valid
steiger 0:7c97dcef700c 153 // letter. I'm not sure this is the best approach, but it is quite tricky trying
steiger 0:7c97dcef700c 154 // to figure out alhabetical vs. not across encoding. So take a very
steiger 0:7c97dcef700c 155 // conservative approach.
steiger 0:7c97dcef700c 156
steiger 0:7c97dcef700c 157 // if ( encoding == TIXML_ENCODING_UTF8 )
steiger 0:7c97dcef700c 158 // {
steiger 0:7c97dcef700c 159 if ( anyByte < 127 )
steiger 0:7c97dcef700c 160 return isalnum( anyByte );
steiger 0:7c97dcef700c 161 else
steiger 0:7c97dcef700c 162 return 1; // What else to do? The unicode set is huge...get the english ones right.
steiger 0:7c97dcef700c 163 // }
steiger 0:7c97dcef700c 164 // else
steiger 0:7c97dcef700c 165 // {
steiger 0:7c97dcef700c 166 // return isalnum( anyByte );
steiger 0:7c97dcef700c 167 // }
steiger 0:7c97dcef700c 168 }
steiger 0:7c97dcef700c 169
steiger 0:7c97dcef700c 170
steiger 0:7c97dcef700c 171 class TiXmlParsingData
steiger 0:7c97dcef700c 172 {
steiger 0:7c97dcef700c 173 friend class TiXmlDocument;
steiger 0:7c97dcef700c 174 public:
steiger 0:7c97dcef700c 175 void Stamp( const char* now, TiXmlEncoding encoding );
steiger 0:7c97dcef700c 176
steiger 0:7c97dcef700c 177 const TiXmlCursor& Cursor() { return cursor; }
steiger 0:7c97dcef700c 178
steiger 0:7c97dcef700c 179 private:
steiger 0:7c97dcef700c 180 // Only used by the document!
steiger 0:7c97dcef700c 181 TiXmlParsingData( const char* start, int _tabsize, int row, int col )
steiger 0:7c97dcef700c 182 {
steiger 0:7c97dcef700c 183 assert( start );
steiger 0:7c97dcef700c 184 stamp = start;
steiger 0:7c97dcef700c 185 tabsize = _tabsize;
steiger 0:7c97dcef700c 186 cursor.row = row;
steiger 0:7c97dcef700c 187 cursor.col = col;
steiger 0:7c97dcef700c 188 }
steiger 0:7c97dcef700c 189
steiger 0:7c97dcef700c 190 TiXmlCursor cursor;
steiger 0:7c97dcef700c 191 const char* stamp;
steiger 0:7c97dcef700c 192 int tabsize;
steiger 0:7c97dcef700c 193 };
steiger 0:7c97dcef700c 194
steiger 0:7c97dcef700c 195
steiger 0:7c97dcef700c 196 void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 197 {
steiger 0:7c97dcef700c 198 assert( now );
steiger 0:7c97dcef700c 199
steiger 0:7c97dcef700c 200 // Do nothing if the tabsize is 0.
steiger 0:7c97dcef700c 201 if ( tabsize < 1 )
steiger 0:7c97dcef700c 202 {
steiger 0:7c97dcef700c 203 return;
steiger 0:7c97dcef700c 204 }
steiger 0:7c97dcef700c 205
steiger 0:7c97dcef700c 206 // Get the current row, column.
steiger 0:7c97dcef700c 207 int row = cursor.row;
steiger 0:7c97dcef700c 208 int col = cursor.col;
steiger 0:7c97dcef700c 209 const char* p = stamp;
steiger 0:7c97dcef700c 210 assert( p );
steiger 0:7c97dcef700c 211
steiger 0:7c97dcef700c 212 while ( p < now )
steiger 0:7c97dcef700c 213 {
steiger 0:7c97dcef700c 214 // Treat p as unsigned, so we have a happy compiler.
steiger 0:7c97dcef700c 215 const unsigned char* pU = (const unsigned char*)p;
steiger 0:7c97dcef700c 216
steiger 0:7c97dcef700c 217 // Code contributed by Fletcher Dunn: (modified by lee)
steiger 0:7c97dcef700c 218 switch (*pU) {
steiger 0:7c97dcef700c 219 case 0:
steiger 0:7c97dcef700c 220 // We *should* never get here, but in case we do, don't
steiger 0:7c97dcef700c 221 // advance past the terminating null character, ever
steiger 0:7c97dcef700c 222 return;
steiger 0:7c97dcef700c 223
steiger 0:7c97dcef700c 224 case '\r':
steiger 0:7c97dcef700c 225 // bump down to the next line
steiger 0:7c97dcef700c 226 ++row;
steiger 0:7c97dcef700c 227 col = 0;
steiger 0:7c97dcef700c 228 // Eat the character
steiger 0:7c97dcef700c 229 ++p;
steiger 0:7c97dcef700c 230
steiger 0:7c97dcef700c 231 // Check for \r\n sequence, and treat this as a single character
steiger 0:7c97dcef700c 232 if (*p == '\n') {
steiger 0:7c97dcef700c 233 ++p;
steiger 0:7c97dcef700c 234 }
steiger 0:7c97dcef700c 235 break;
steiger 0:7c97dcef700c 236
steiger 0:7c97dcef700c 237 case '\n':
steiger 0:7c97dcef700c 238 // bump down to the next line
steiger 0:7c97dcef700c 239 ++row;
steiger 0:7c97dcef700c 240 col = 0;
steiger 0:7c97dcef700c 241
steiger 0:7c97dcef700c 242 // Eat the character
steiger 0:7c97dcef700c 243 ++p;
steiger 0:7c97dcef700c 244
steiger 0:7c97dcef700c 245 // Check for \n\r sequence, and treat this as a single
steiger 0:7c97dcef700c 246 // character. (Yes, this bizarre thing does occur still
steiger 0:7c97dcef700c 247 // on some arcane platforms...)
steiger 0:7c97dcef700c 248 if (*p == '\r') {
steiger 0:7c97dcef700c 249 ++p;
steiger 0:7c97dcef700c 250 }
steiger 0:7c97dcef700c 251 break;
steiger 0:7c97dcef700c 252
steiger 0:7c97dcef700c 253 case '\t':
steiger 0:7c97dcef700c 254 // Eat the character
steiger 0:7c97dcef700c 255 ++p;
steiger 0:7c97dcef700c 256
steiger 0:7c97dcef700c 257 // Skip to next tab stop
steiger 0:7c97dcef700c 258 col = (col / tabsize + 1) * tabsize;
steiger 0:7c97dcef700c 259 break;
steiger 0:7c97dcef700c 260
steiger 0:7c97dcef700c 261 case TIXML_UTF_LEAD_0:
steiger 0:7c97dcef700c 262 if ( encoding == TIXML_ENCODING_UTF8 )
steiger 0:7c97dcef700c 263 {
steiger 0:7c97dcef700c 264 if ( *(p+1) && *(p+2) )
steiger 0:7c97dcef700c 265 {
steiger 0:7c97dcef700c 266 // In these cases, don't advance the column. These are
steiger 0:7c97dcef700c 267 // 0-width spaces.
steiger 0:7c97dcef700c 268 if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 )
steiger 0:7c97dcef700c 269 p += 3;
steiger 0:7c97dcef700c 270 else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU )
steiger 0:7c97dcef700c 271 p += 3;
steiger 0:7c97dcef700c 272 else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU )
steiger 0:7c97dcef700c 273 p += 3;
steiger 0:7c97dcef700c 274 else
steiger 0:7c97dcef700c 275 { p +=3; ++col; } // A normal character.
steiger 0:7c97dcef700c 276 }
steiger 0:7c97dcef700c 277 }
steiger 0:7c97dcef700c 278 else
steiger 0:7c97dcef700c 279 {
steiger 0:7c97dcef700c 280 ++p;
steiger 0:7c97dcef700c 281 ++col;
steiger 0:7c97dcef700c 282 }
steiger 0:7c97dcef700c 283 break;
steiger 0:7c97dcef700c 284
steiger 0:7c97dcef700c 285 default:
steiger 0:7c97dcef700c 286 if ( encoding == TIXML_ENCODING_UTF8 )
steiger 0:7c97dcef700c 287 {
steiger 0:7c97dcef700c 288 // Eat the 1 to 4 byte utf8 character.
steiger 0:7c97dcef700c 289 int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)];
steiger 0:7c97dcef700c 290 if ( step == 0 )
steiger 0:7c97dcef700c 291 step = 1; // Error case from bad encoding, but handle gracefully.
steiger 0:7c97dcef700c 292 p += step;
steiger 0:7c97dcef700c 293
steiger 0:7c97dcef700c 294 // Just advance one column, of course.
steiger 0:7c97dcef700c 295 ++col;
steiger 0:7c97dcef700c 296 }
steiger 0:7c97dcef700c 297 else
steiger 0:7c97dcef700c 298 {
steiger 0:7c97dcef700c 299 ++p;
steiger 0:7c97dcef700c 300 ++col;
steiger 0:7c97dcef700c 301 }
steiger 0:7c97dcef700c 302 break;
steiger 0:7c97dcef700c 303 }
steiger 0:7c97dcef700c 304 }
steiger 0:7c97dcef700c 305 cursor.row = row;
steiger 0:7c97dcef700c 306 cursor.col = col;
steiger 0:7c97dcef700c 307 assert( cursor.row >= -1 );
steiger 0:7c97dcef700c 308 assert( cursor.col >= -1 );
steiger 0:7c97dcef700c 309 stamp = p;
steiger 0:7c97dcef700c 310 assert( stamp );
steiger 0:7c97dcef700c 311 }
steiger 0:7c97dcef700c 312
steiger 0:7c97dcef700c 313
steiger 0:7c97dcef700c 314 const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 315 {
steiger 0:7c97dcef700c 316 if ( !p || !*p )
steiger 0:7c97dcef700c 317 {
steiger 0:7c97dcef700c 318 return 0;
steiger 0:7c97dcef700c 319 }
steiger 0:7c97dcef700c 320 if ( encoding == TIXML_ENCODING_UTF8 )
steiger 0:7c97dcef700c 321 {
steiger 0:7c97dcef700c 322 while ( *p )
steiger 0:7c97dcef700c 323 {
steiger 0:7c97dcef700c 324 const unsigned char* pU = (const unsigned char*)p;
steiger 0:7c97dcef700c 325
steiger 0:7c97dcef700c 326 // Skip the stupid Microsoft UTF-8 Byte order marks
steiger 0:7c97dcef700c 327 if ( *(pU+0)==TIXML_UTF_LEAD_0
steiger 0:7c97dcef700c 328 && *(pU+1)==TIXML_UTF_LEAD_1
steiger 0:7c97dcef700c 329 && *(pU+2)==TIXML_UTF_LEAD_2 )
steiger 0:7c97dcef700c 330 {
steiger 0:7c97dcef700c 331 p += 3;
steiger 0:7c97dcef700c 332 continue;
steiger 0:7c97dcef700c 333 }
steiger 0:7c97dcef700c 334 else if(*(pU+0)==TIXML_UTF_LEAD_0
steiger 0:7c97dcef700c 335 && *(pU+1)==0xbfU
steiger 0:7c97dcef700c 336 && *(pU+2)==0xbeU )
steiger 0:7c97dcef700c 337 {
steiger 0:7c97dcef700c 338 p += 3;
steiger 0:7c97dcef700c 339 continue;
steiger 0:7c97dcef700c 340 }
steiger 0:7c97dcef700c 341 else if(*(pU+0)==TIXML_UTF_LEAD_0
steiger 0:7c97dcef700c 342 && *(pU+1)==0xbfU
steiger 0:7c97dcef700c 343 && *(pU+2)==0xbfU )
steiger 0:7c97dcef700c 344 {
steiger 0:7c97dcef700c 345 p += 3;
steiger 0:7c97dcef700c 346 continue;
steiger 0:7c97dcef700c 347 }
steiger 0:7c97dcef700c 348
steiger 0:7c97dcef700c 349 if ( IsWhiteSpace( *p ) ) // Still using old rules for white space.
steiger 0:7c97dcef700c 350 ++p;
steiger 0:7c97dcef700c 351 else
steiger 0:7c97dcef700c 352 break;
steiger 0:7c97dcef700c 353 }
steiger 0:7c97dcef700c 354 }
steiger 0:7c97dcef700c 355 else
steiger 0:7c97dcef700c 356 {
steiger 0:7c97dcef700c 357 while ( *p && IsWhiteSpace( *p ) )
steiger 0:7c97dcef700c 358 ++p;
steiger 0:7c97dcef700c 359 }
steiger 0:7c97dcef700c 360
steiger 0:7c97dcef700c 361 return p;
steiger 0:7c97dcef700c 362 }
steiger 0:7c97dcef700c 363
steiger 0:7c97dcef700c 364 #ifdef TIXML_USE_STL
steiger 0:7c97dcef700c 365 /*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag )
steiger 0:7c97dcef700c 366 {
steiger 0:7c97dcef700c 367 for( ;; )
steiger 0:7c97dcef700c 368 {
steiger 0:7c97dcef700c 369 if ( !in->good() ) return false;
steiger 0:7c97dcef700c 370
steiger 0:7c97dcef700c 371 int c = in->peek();
steiger 0:7c97dcef700c 372 // At this scope, we can't get to a document. So fail silently.
steiger 0:7c97dcef700c 373 if ( !IsWhiteSpace( c ) || c <= 0 )
steiger 0:7c97dcef700c 374 return true;
steiger 0:7c97dcef700c 375
steiger 0:7c97dcef700c 376 *tag += (char) in->get();
steiger 0:7c97dcef700c 377 }
steiger 0:7c97dcef700c 378 }
steiger 0:7c97dcef700c 379
steiger 0:7c97dcef700c 380 /*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag )
steiger 0:7c97dcef700c 381 {
steiger 0:7c97dcef700c 382 //assert( character > 0 && character < 128 ); // else it won't work in utf-8
steiger 0:7c97dcef700c 383 while ( in->good() )
steiger 0:7c97dcef700c 384 {
steiger 0:7c97dcef700c 385 int c = in->peek();
steiger 0:7c97dcef700c 386 if ( c == character )
steiger 0:7c97dcef700c 387 return true;
steiger 0:7c97dcef700c 388 if ( c <= 0 ) // Silent failure: can't get document at this scope
steiger 0:7c97dcef700c 389 return false;
steiger 0:7c97dcef700c 390
steiger 0:7c97dcef700c 391 in->get();
steiger 0:7c97dcef700c 392 *tag += (char) c;
steiger 0:7c97dcef700c 393 }
steiger 0:7c97dcef700c 394 return false;
steiger 0:7c97dcef700c 395 }
steiger 0:7c97dcef700c 396 #endif
steiger 0:7c97dcef700c 397
steiger 0:7c97dcef700c 398 // One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The
steiger 0:7c97dcef700c 399 // "assign" optimization removes over 10% of the execution time.
steiger 0:7c97dcef700c 400 //
steiger 0:7c97dcef700c 401 const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 402 {
steiger 0:7c97dcef700c 403 // Oddly, not supported on some comilers,
steiger 0:7c97dcef700c 404 //name->clear();
steiger 0:7c97dcef700c 405 // So use this:
steiger 0:7c97dcef700c 406 *name = "";
steiger 0:7c97dcef700c 407 assert( p );
steiger 0:7c97dcef700c 408
steiger 0:7c97dcef700c 409 // Names start with letters or underscores.
steiger 0:7c97dcef700c 410 // Of course, in unicode, tinyxml has no idea what a letter *is*. The
steiger 0:7c97dcef700c 411 // algorithm is generous.
steiger 0:7c97dcef700c 412 //
steiger 0:7c97dcef700c 413 // After that, they can be letters, underscores, numbers,
steiger 0:7c97dcef700c 414 // hyphens, or colons. (Colons are valid ony for namespaces,
steiger 0:7c97dcef700c 415 // but tinyxml can't tell namespaces from names.)
steiger 0:7c97dcef700c 416 if ( p && *p
steiger 0:7c97dcef700c 417 && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) )
steiger 0:7c97dcef700c 418 {
steiger 0:7c97dcef700c 419 const char* start = p;
steiger 0:7c97dcef700c 420 while( p && *p
steiger 0:7c97dcef700c 421 && ( IsAlphaNum( (unsigned char ) *p, encoding )
steiger 0:7c97dcef700c 422 || *p == '_'
steiger 0:7c97dcef700c 423 || *p == '-'
steiger 0:7c97dcef700c 424 || *p == '.'
steiger 0:7c97dcef700c 425 || *p == ':' ) )
steiger 0:7c97dcef700c 426 {
steiger 0:7c97dcef700c 427 //(*name) += *p; // expensive
steiger 0:7c97dcef700c 428 ++p;
steiger 0:7c97dcef700c 429 }
steiger 0:7c97dcef700c 430 if ( p-start > 0 ) {
steiger 0:7c97dcef700c 431 name->assign( start, p-start );
steiger 0:7c97dcef700c 432 }
steiger 0:7c97dcef700c 433 return p;
steiger 0:7c97dcef700c 434 }
steiger 0:7c97dcef700c 435 return 0;
steiger 0:7c97dcef700c 436 }
steiger 0:7c97dcef700c 437
steiger 0:7c97dcef700c 438 const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 439 {
steiger 0:7c97dcef700c 440 // Presume an entity, and pull it out.
steiger 0:7c97dcef700c 441 TIXML_STRING ent;
steiger 0:7c97dcef700c 442 int i;
steiger 0:7c97dcef700c 443 *length = 0;
steiger 0:7c97dcef700c 444
steiger 0:7c97dcef700c 445 if ( *(p+1) && *(p+1) == '#' && *(p+2) )
steiger 0:7c97dcef700c 446 {
steiger 0:7c97dcef700c 447 unsigned long ucs = 0;
steiger 0:7c97dcef700c 448 ptrdiff_t delta = 0;
steiger 0:7c97dcef700c 449 unsigned mult = 1;
steiger 0:7c97dcef700c 450
steiger 0:7c97dcef700c 451 if ( *(p+2) == 'x' )
steiger 0:7c97dcef700c 452 {
steiger 0:7c97dcef700c 453 // Hexadecimal.
steiger 0:7c97dcef700c 454 if ( !*(p+3) ) return 0;
steiger 0:7c97dcef700c 455
steiger 0:7c97dcef700c 456 const char* q = p+3;
steiger 0:7c97dcef700c 457 q = strchr( q, ';' );
steiger 0:7c97dcef700c 458
steiger 0:7c97dcef700c 459 if ( !q || !*q ) return 0;
steiger 0:7c97dcef700c 460
steiger 0:7c97dcef700c 461 delta = q-p;
steiger 0:7c97dcef700c 462 --q;
steiger 0:7c97dcef700c 463
steiger 0:7c97dcef700c 464 while ( *q != 'x' )
steiger 0:7c97dcef700c 465 {
steiger 0:7c97dcef700c 466 if ( *q >= '0' && *q <= '9' )
steiger 0:7c97dcef700c 467 ucs += mult * (*q - '0');
steiger 0:7c97dcef700c 468 else if ( *q >= 'a' && *q <= 'f' )
steiger 0:7c97dcef700c 469 ucs += mult * (*q - 'a' + 10);
steiger 0:7c97dcef700c 470 else if ( *q >= 'A' && *q <= 'F' )
steiger 0:7c97dcef700c 471 ucs += mult * (*q - 'A' + 10 );
steiger 0:7c97dcef700c 472 else
steiger 0:7c97dcef700c 473 return 0;
steiger 0:7c97dcef700c 474 mult *= 16;
steiger 0:7c97dcef700c 475 --q;
steiger 0:7c97dcef700c 476 }
steiger 0:7c97dcef700c 477 }
steiger 0:7c97dcef700c 478 else
steiger 0:7c97dcef700c 479 {
steiger 0:7c97dcef700c 480 // Decimal.
steiger 0:7c97dcef700c 481 if ( !*(p+2) ) return 0;
steiger 0:7c97dcef700c 482
steiger 0:7c97dcef700c 483 const char* q = p+2;
steiger 0:7c97dcef700c 484 q = strchr( q, ';' );
steiger 0:7c97dcef700c 485
steiger 0:7c97dcef700c 486 if ( !q || !*q ) return 0;
steiger 0:7c97dcef700c 487
steiger 0:7c97dcef700c 488 delta = q-p;
steiger 0:7c97dcef700c 489 --q;
steiger 0:7c97dcef700c 490
steiger 0:7c97dcef700c 491 while ( *q != '#' )
steiger 0:7c97dcef700c 492 {
steiger 0:7c97dcef700c 493 if ( *q >= '0' && *q <= '9' )
steiger 0:7c97dcef700c 494 ucs += mult * (*q - '0');
steiger 0:7c97dcef700c 495 else
steiger 0:7c97dcef700c 496 return 0;
steiger 0:7c97dcef700c 497 mult *= 10;
steiger 0:7c97dcef700c 498 --q;
steiger 0:7c97dcef700c 499 }
steiger 0:7c97dcef700c 500 }
steiger 0:7c97dcef700c 501 if ( encoding == TIXML_ENCODING_UTF8 )
steiger 0:7c97dcef700c 502 {
steiger 0:7c97dcef700c 503 // convert the UCS to UTF-8
steiger 0:7c97dcef700c 504 ConvertUTF32ToUTF8( ucs, value, length );
steiger 0:7c97dcef700c 505 }
steiger 0:7c97dcef700c 506 else
steiger 0:7c97dcef700c 507 {
steiger 0:7c97dcef700c 508 *value = (char)ucs;
steiger 0:7c97dcef700c 509 *length = 1;
steiger 0:7c97dcef700c 510 }
steiger 0:7c97dcef700c 511 return p + delta + 1;
steiger 0:7c97dcef700c 512 }
steiger 0:7c97dcef700c 513
steiger 0:7c97dcef700c 514 // Now try to match it.
steiger 0:7c97dcef700c 515 for( i=0; i<NUM_ENTITY; ++i )
steiger 0:7c97dcef700c 516 {
steiger 0:7c97dcef700c 517 if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
steiger 0:7c97dcef700c 518 {
steiger 0:7c97dcef700c 519 assert( strlen( entity[i].str ) == entity[i].strLength );
steiger 0:7c97dcef700c 520 *value = entity[i].chr;
steiger 0:7c97dcef700c 521 *length = 1;
steiger 0:7c97dcef700c 522 return ( p + entity[i].strLength );
steiger 0:7c97dcef700c 523 }
steiger 0:7c97dcef700c 524 }
steiger 0:7c97dcef700c 525
steiger 0:7c97dcef700c 526 // So it wasn't an entity, its unrecognized, or something like that.
steiger 0:7c97dcef700c 527 *value = *p; // Don't put back the last one, since we return it!
steiger 0:7c97dcef700c 528 //*length = 1; // Leave unrecognized entities - this doesn't really work.
steiger 0:7c97dcef700c 529 // Just writes strange XML.
steiger 0:7c97dcef700c 530 return p+1;
steiger 0:7c97dcef700c 531 }
steiger 0:7c97dcef700c 532
steiger 0:7c97dcef700c 533
steiger 0:7c97dcef700c 534 bool TiXmlBase::StringEqual( const char* p,
steiger 0:7c97dcef700c 535 const char* tag,
steiger 0:7c97dcef700c 536 bool ignoreCase,
steiger 0:7c97dcef700c 537 TiXmlEncoding encoding )
steiger 0:7c97dcef700c 538 {
steiger 0:7c97dcef700c 539 assert( p );
steiger 0:7c97dcef700c 540 assert( tag );
steiger 0:7c97dcef700c 541 if ( !p || !*p )
steiger 0:7c97dcef700c 542 {
steiger 0:7c97dcef700c 543 assert( 0 );
steiger 0:7c97dcef700c 544 return false;
steiger 0:7c97dcef700c 545 }
steiger 0:7c97dcef700c 546
steiger 0:7c97dcef700c 547 const char* q = p;
steiger 0:7c97dcef700c 548
steiger 0:7c97dcef700c 549 if ( ignoreCase )
steiger 0:7c97dcef700c 550 {
steiger 0:7c97dcef700c 551 while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) )
steiger 0:7c97dcef700c 552 {
steiger 0:7c97dcef700c 553 ++q;
steiger 0:7c97dcef700c 554 ++tag;
steiger 0:7c97dcef700c 555 }
steiger 0:7c97dcef700c 556
steiger 0:7c97dcef700c 557 if ( *tag == 0 )
steiger 0:7c97dcef700c 558 return true;
steiger 0:7c97dcef700c 559 }
steiger 0:7c97dcef700c 560 else
steiger 0:7c97dcef700c 561 {
steiger 0:7c97dcef700c 562 while ( *q && *tag && *q == *tag )
steiger 0:7c97dcef700c 563 {
steiger 0:7c97dcef700c 564 ++q;
steiger 0:7c97dcef700c 565 ++tag;
steiger 0:7c97dcef700c 566 }
steiger 0:7c97dcef700c 567
steiger 0:7c97dcef700c 568 if ( *tag == 0 ) // Have we found the end of the tag, and everything equal?
steiger 0:7c97dcef700c 569 return true;
steiger 0:7c97dcef700c 570 }
steiger 0:7c97dcef700c 571 return false;
steiger 0:7c97dcef700c 572 }
steiger 0:7c97dcef700c 573
steiger 0:7c97dcef700c 574 const char* TiXmlBase::ReadText( const char* p,
steiger 0:7c97dcef700c 575 TIXML_STRING * text,
steiger 0:7c97dcef700c 576 bool trimWhiteSpace,
steiger 0:7c97dcef700c 577 const char* endTag,
steiger 0:7c97dcef700c 578 bool caseInsensitive,
steiger 0:7c97dcef700c 579 TiXmlEncoding encoding )
steiger 0:7c97dcef700c 580 {
steiger 0:7c97dcef700c 581 *text = "";
steiger 0:7c97dcef700c 582 if ( !trimWhiteSpace // certain tags always keep whitespace
steiger 0:7c97dcef700c 583 || !condenseWhiteSpace ) // if true, whitespace is always kept
steiger 0:7c97dcef700c 584 {
steiger 0:7c97dcef700c 585 // Keep all the white space.
steiger 0:7c97dcef700c 586 while ( p && *p
steiger 0:7c97dcef700c 587 && !StringEqual( p, endTag, caseInsensitive, encoding )
steiger 0:7c97dcef700c 588 )
steiger 0:7c97dcef700c 589 {
steiger 0:7c97dcef700c 590 int len;
steiger 0:7c97dcef700c 591 char cArr[4] = { 0, 0, 0, 0 };
steiger 0:7c97dcef700c 592 p = GetChar( p, cArr, &len, encoding );
steiger 0:7c97dcef700c 593 text->append( cArr, len );
steiger 0:7c97dcef700c 594 }
steiger 0:7c97dcef700c 595 }
steiger 0:7c97dcef700c 596 else
steiger 0:7c97dcef700c 597 {
steiger 0:7c97dcef700c 598 bool whitespace = false;
steiger 0:7c97dcef700c 599
steiger 0:7c97dcef700c 600 // Remove leading white space:
steiger 0:7c97dcef700c 601 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 602 while ( p && *p
steiger 0:7c97dcef700c 603 && !StringEqual( p, endTag, caseInsensitive, encoding ) )
steiger 0:7c97dcef700c 604 {
steiger 0:7c97dcef700c 605 if ( *p == '\r' || *p == '\n' )
steiger 0:7c97dcef700c 606 {
steiger 0:7c97dcef700c 607 whitespace = true;
steiger 0:7c97dcef700c 608 ++p;
steiger 0:7c97dcef700c 609 }
steiger 0:7c97dcef700c 610 else if ( IsWhiteSpace( *p ) )
steiger 0:7c97dcef700c 611 {
steiger 0:7c97dcef700c 612 whitespace = true;
steiger 0:7c97dcef700c 613 ++p;
steiger 0:7c97dcef700c 614 }
steiger 0:7c97dcef700c 615 else
steiger 0:7c97dcef700c 616 {
steiger 0:7c97dcef700c 617 // If we've found whitespace, add it before the
steiger 0:7c97dcef700c 618 // new character. Any whitespace just becomes a space.
steiger 0:7c97dcef700c 619 if ( whitespace )
steiger 0:7c97dcef700c 620 {
steiger 0:7c97dcef700c 621 (*text) += ' ';
steiger 0:7c97dcef700c 622 whitespace = false;
steiger 0:7c97dcef700c 623 }
steiger 0:7c97dcef700c 624 int len;
steiger 0:7c97dcef700c 625 char cArr[4] = { 0, 0, 0, 0 };
steiger 0:7c97dcef700c 626 p = GetChar( p, cArr, &len, encoding );
steiger 0:7c97dcef700c 627 if ( len == 1 )
steiger 0:7c97dcef700c 628 (*text) += cArr[0]; // more efficient
steiger 0:7c97dcef700c 629 else
steiger 0:7c97dcef700c 630 text->append( cArr, len );
steiger 0:7c97dcef700c 631 }
steiger 0:7c97dcef700c 632 }
steiger 0:7c97dcef700c 633 }
steiger 0:7c97dcef700c 634 if ( p && *p )
steiger 0:7c97dcef700c 635 p += strlen( endTag );
steiger 0:7c97dcef700c 636 return p;
steiger 0:7c97dcef700c 637 }
steiger 0:7c97dcef700c 638
steiger 0:7c97dcef700c 639 #ifdef TIXML_USE_STL
steiger 0:7c97dcef700c 640
steiger 0:7c97dcef700c 641 void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag )
steiger 0:7c97dcef700c 642 {
steiger 0:7c97dcef700c 643 // The basic issue with a document is that we don't know what we're
steiger 0:7c97dcef700c 644 // streaming. Read something presumed to be a tag (and hope), then
steiger 0:7c97dcef700c 645 // identify it, and call the appropriate stream method on the tag.
steiger 0:7c97dcef700c 646 //
steiger 0:7c97dcef700c 647 // This "pre-streaming" will never read the closing ">" so the
steiger 0:7c97dcef700c 648 // sub-tag can orient itself.
steiger 0:7c97dcef700c 649
steiger 0:7c97dcef700c 650 if ( !StreamTo( in, '<', tag ) )
steiger 0:7c97dcef700c 651 {
steiger 0:7c97dcef700c 652 SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 653 return;
steiger 0:7c97dcef700c 654 }
steiger 0:7c97dcef700c 655
steiger 0:7c97dcef700c 656 while ( in->good() )
steiger 0:7c97dcef700c 657 {
steiger 0:7c97dcef700c 658 int tagIndex = (int) tag->length();
steiger 0:7c97dcef700c 659 while ( in->good() && in->peek() != '>' )
steiger 0:7c97dcef700c 660 {
steiger 0:7c97dcef700c 661 int c = in->get();
steiger 0:7c97dcef700c 662 if ( c <= 0 )
steiger 0:7c97dcef700c 663 {
steiger 0:7c97dcef700c 664 SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 665 break;
steiger 0:7c97dcef700c 666 }
steiger 0:7c97dcef700c 667 (*tag) += (char) c;
steiger 0:7c97dcef700c 668 }
steiger 0:7c97dcef700c 669
steiger 0:7c97dcef700c 670 if ( in->good() )
steiger 0:7c97dcef700c 671 {
steiger 0:7c97dcef700c 672 // We now have something we presume to be a node of
steiger 0:7c97dcef700c 673 // some sort. Identify it, and call the node to
steiger 0:7c97dcef700c 674 // continue streaming.
steiger 0:7c97dcef700c 675 TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING );
steiger 0:7c97dcef700c 676
steiger 0:7c97dcef700c 677 if ( node )
steiger 0:7c97dcef700c 678 {
steiger 0:7c97dcef700c 679 node->StreamIn( in, tag );
steiger 0:7c97dcef700c 680 bool isElement = node->ToElement() != 0;
steiger 0:7c97dcef700c 681 delete node;
steiger 0:7c97dcef700c 682 node = 0;
steiger 0:7c97dcef700c 683
steiger 0:7c97dcef700c 684 // If this is the root element, we're done. Parsing will be
steiger 0:7c97dcef700c 685 // done by the >> operator.
steiger 0:7c97dcef700c 686 if ( isElement )
steiger 0:7c97dcef700c 687 {
steiger 0:7c97dcef700c 688 return;
steiger 0:7c97dcef700c 689 }
steiger 0:7c97dcef700c 690 }
steiger 0:7c97dcef700c 691 else
steiger 0:7c97dcef700c 692 {
steiger 0:7c97dcef700c 693 SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 694 return;
steiger 0:7c97dcef700c 695 }
steiger 0:7c97dcef700c 696 }
steiger 0:7c97dcef700c 697 }
steiger 0:7c97dcef700c 698 // We should have returned sooner.
steiger 0:7c97dcef700c 699 SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 700 }
steiger 0:7c97dcef700c 701
steiger 0:7c97dcef700c 702 #endif
steiger 0:7c97dcef700c 703
steiger 0:7c97dcef700c 704 const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 705 {
steiger 0:7c97dcef700c 706 ClearError();
steiger 0:7c97dcef700c 707
steiger 0:7c97dcef700c 708 // Parse away, at the document level. Since a document
steiger 0:7c97dcef700c 709 // contains nothing but other tags, most of what happens
steiger 0:7c97dcef700c 710 // here is skipping white space.
steiger 0:7c97dcef700c 711 if ( !p || !*p )
steiger 0:7c97dcef700c 712 {
steiger 0:7c97dcef700c 713 SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 714 return 0;
steiger 0:7c97dcef700c 715 }
steiger 0:7c97dcef700c 716
steiger 0:7c97dcef700c 717 // Note that, for a document, this needs to come
steiger 0:7c97dcef700c 718 // before the while space skip, so that parsing
steiger 0:7c97dcef700c 719 // starts from the pointer we are given.
steiger 0:7c97dcef700c 720 location.Clear();
steiger 0:7c97dcef700c 721 if ( prevData )
steiger 0:7c97dcef700c 722 {
steiger 0:7c97dcef700c 723 location.row = prevData->cursor.row;
steiger 0:7c97dcef700c 724 location.col = prevData->cursor.col;
steiger 0:7c97dcef700c 725 }
steiger 0:7c97dcef700c 726 else
steiger 0:7c97dcef700c 727 {
steiger 0:7c97dcef700c 728 location.row = 0;
steiger 0:7c97dcef700c 729 location.col = 0;
steiger 0:7c97dcef700c 730 }
steiger 0:7c97dcef700c 731 TiXmlParsingData data( p, TabSize(), location.row, location.col );
steiger 0:7c97dcef700c 732 location = data.Cursor();
steiger 0:7c97dcef700c 733
steiger 0:7c97dcef700c 734 if ( encoding == TIXML_ENCODING_UNKNOWN )
steiger 0:7c97dcef700c 735 {
steiger 0:7c97dcef700c 736 // Check for the Microsoft UTF-8 lead bytes.
steiger 0:7c97dcef700c 737 const unsigned char* pU = (const unsigned char*)p;
steiger 0:7c97dcef700c 738 if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0
steiger 0:7c97dcef700c 739 && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1
steiger 0:7c97dcef700c 740 && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 )
steiger 0:7c97dcef700c 741 {
steiger 0:7c97dcef700c 742 encoding = TIXML_ENCODING_UTF8;
steiger 0:7c97dcef700c 743 useMicrosoftBOM = true;
steiger 0:7c97dcef700c 744 }
steiger 0:7c97dcef700c 745 }
steiger 0:7c97dcef700c 746
steiger 0:7c97dcef700c 747 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 748 if ( !p )
steiger 0:7c97dcef700c 749 {
steiger 0:7c97dcef700c 750 SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 751 return 0;
steiger 0:7c97dcef700c 752 }
steiger 0:7c97dcef700c 753
steiger 0:7c97dcef700c 754 while ( p && *p )
steiger 0:7c97dcef700c 755 {
steiger 0:7c97dcef700c 756 TiXmlNode* node = Identify( p, encoding );
steiger 0:7c97dcef700c 757 if ( node )
steiger 0:7c97dcef700c 758 {
steiger 0:7c97dcef700c 759 p = node->Parse( p, &data, encoding );
steiger 0:7c97dcef700c 760 LinkEndChild( node );
steiger 0:7c97dcef700c 761 }
steiger 0:7c97dcef700c 762 else
steiger 0:7c97dcef700c 763 {
steiger 0:7c97dcef700c 764 break;
steiger 0:7c97dcef700c 765 }
steiger 0:7c97dcef700c 766
steiger 0:7c97dcef700c 767 // Did we get encoding info?
steiger 0:7c97dcef700c 768 if ( encoding == TIXML_ENCODING_UNKNOWN
steiger 0:7c97dcef700c 769 && node->ToDeclaration() )
steiger 0:7c97dcef700c 770 {
steiger 0:7c97dcef700c 771 TiXmlDeclaration* dec = node->ToDeclaration();
steiger 0:7c97dcef700c 772 const char* enc = dec->Encoding();
steiger 0:7c97dcef700c 773 assert( enc );
steiger 0:7c97dcef700c 774
steiger 0:7c97dcef700c 775 if ( *enc == 0 )
steiger 0:7c97dcef700c 776 encoding = TIXML_ENCODING_UTF8;
steiger 0:7c97dcef700c 777 else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) )
steiger 0:7c97dcef700c 778 encoding = TIXML_ENCODING_UTF8;
steiger 0:7c97dcef700c 779 else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) )
steiger 0:7c97dcef700c 780 encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice
steiger 0:7c97dcef700c 781 else
steiger 0:7c97dcef700c 782 encoding = TIXML_ENCODING_LEGACY;
steiger 0:7c97dcef700c 783 }
steiger 0:7c97dcef700c 784
steiger 0:7c97dcef700c 785 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 786 }
steiger 0:7c97dcef700c 787
steiger 0:7c97dcef700c 788 // Was this empty?
steiger 0:7c97dcef700c 789 if ( !firstChild ) {
steiger 0:7c97dcef700c 790 SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding );
steiger 0:7c97dcef700c 791 return 0;
steiger 0:7c97dcef700c 792 }
steiger 0:7c97dcef700c 793
steiger 0:7c97dcef700c 794 // All is well.
steiger 0:7c97dcef700c 795 return p;
steiger 0:7c97dcef700c 796 }
steiger 0:7c97dcef700c 797
steiger 0:7c97dcef700c 798 void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 799 {
steiger 0:7c97dcef700c 800 // The first error in a chain is more accurate - don't set again!
steiger 0:7c97dcef700c 801 if ( error )
steiger 0:7c97dcef700c 802 return;
steiger 0:7c97dcef700c 803
steiger 0:7c97dcef700c 804 assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
steiger 0:7c97dcef700c 805 error = true;
steiger 0:7c97dcef700c 806 errorId = err;
steiger 0:7c97dcef700c 807 errorDesc = errorString[ errorId ];
steiger 0:7c97dcef700c 808
steiger 0:7c97dcef700c 809 errorLocation.Clear();
steiger 0:7c97dcef700c 810 if ( pError && data )
steiger 0:7c97dcef700c 811 {
steiger 0:7c97dcef700c 812 data->Stamp( pError, encoding );
steiger 0:7c97dcef700c 813 errorLocation = data->Cursor();
steiger 0:7c97dcef700c 814 }
steiger 0:7c97dcef700c 815 }
steiger 0:7c97dcef700c 816
steiger 0:7c97dcef700c 817
steiger 0:7c97dcef700c 818 TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 819 {
steiger 0:7c97dcef700c 820 TiXmlNode* returnNode = 0;
steiger 0:7c97dcef700c 821
steiger 0:7c97dcef700c 822 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 823 if( !p || !*p || *p != '<' )
steiger 0:7c97dcef700c 824 {
steiger 0:7c97dcef700c 825 return 0;
steiger 0:7c97dcef700c 826 }
steiger 0:7c97dcef700c 827
steiger 0:7c97dcef700c 828 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 829
steiger 0:7c97dcef700c 830 if ( !p || !*p )
steiger 0:7c97dcef700c 831 {
steiger 0:7c97dcef700c 832 return 0;
steiger 0:7c97dcef700c 833 }
steiger 0:7c97dcef700c 834
steiger 0:7c97dcef700c 835 // What is this thing?
steiger 0:7c97dcef700c 836 // - Elements start with a letter or underscore, but xml is reserved.
steiger 0:7c97dcef700c 837 // - Comments: <!--
steiger 0:7c97dcef700c 838 // - Decleration: <?xml
steiger 0:7c97dcef700c 839 // - Everthing else is unknown to tinyxml.
steiger 0:7c97dcef700c 840 //
steiger 0:7c97dcef700c 841
steiger 0:7c97dcef700c 842 const char* xmlHeader = { "<?xml" };
steiger 0:7c97dcef700c 843 const char* commentHeader = { "<!--" };
steiger 0:7c97dcef700c 844 const char* dtdHeader = { "<!" };
steiger 0:7c97dcef700c 845 const char* cdataHeader = { "<![CDATA[" };
steiger 0:7c97dcef700c 846
steiger 0:7c97dcef700c 847 if ( StringEqual( p, xmlHeader, true, encoding ) )
steiger 0:7c97dcef700c 848 {
steiger 0:7c97dcef700c 849 #ifdef DEBUG_PARSER
steiger 0:7c97dcef700c 850 TIXML_LOG( "XML parsing Declaration\n" );
steiger 0:7c97dcef700c 851 #endif
steiger 0:7c97dcef700c 852 returnNode = new TiXmlDeclaration();
steiger 0:7c97dcef700c 853 }
steiger 0:7c97dcef700c 854 else if ( StringEqual( p, commentHeader, false, encoding ) )
steiger 0:7c97dcef700c 855 {
steiger 0:7c97dcef700c 856 #ifdef DEBUG_PARSER
steiger 0:7c97dcef700c 857 TIXML_LOG( "XML parsing Comment\n" );
steiger 0:7c97dcef700c 858 #endif
steiger 0:7c97dcef700c 859 returnNode = new TiXmlComment();
steiger 0:7c97dcef700c 860 }
steiger 0:7c97dcef700c 861 else if ( StringEqual( p, cdataHeader, false, encoding ) )
steiger 0:7c97dcef700c 862 {
steiger 0:7c97dcef700c 863 #ifdef DEBUG_PARSER
steiger 0:7c97dcef700c 864 TIXML_LOG( "XML parsing CDATA\n" );
steiger 0:7c97dcef700c 865 #endif
steiger 0:7c97dcef700c 866 TiXmlText* text = new TiXmlText( "" );
steiger 0:7c97dcef700c 867 text->SetCDATA( true );
steiger 0:7c97dcef700c 868 returnNode = text;
steiger 0:7c97dcef700c 869 }
steiger 0:7c97dcef700c 870 else if ( StringEqual( p, dtdHeader, false, encoding ) )
steiger 0:7c97dcef700c 871 {
steiger 0:7c97dcef700c 872 #ifdef DEBUG_PARSER
steiger 0:7c97dcef700c 873 TIXML_LOG( "XML parsing Unknown(1)\n" );
steiger 0:7c97dcef700c 874 #endif
steiger 0:7c97dcef700c 875 returnNode = new TiXmlUnknown();
steiger 0:7c97dcef700c 876 }
steiger 0:7c97dcef700c 877 else if ( IsAlpha( *(p+1), encoding )
steiger 0:7c97dcef700c 878 || *(p+1) == '_' )
steiger 0:7c97dcef700c 879 {
steiger 0:7c97dcef700c 880 #ifdef DEBUG_PARSER
steiger 0:7c97dcef700c 881 TIXML_LOG( "XML parsing Element\n" );
steiger 0:7c97dcef700c 882 #endif
steiger 0:7c97dcef700c 883 returnNode = new TiXmlElement( "" );
steiger 0:7c97dcef700c 884 }
steiger 0:7c97dcef700c 885 else
steiger 0:7c97dcef700c 886 {
steiger 0:7c97dcef700c 887 #ifdef DEBUG_PARSER
steiger 0:7c97dcef700c 888 TIXML_LOG( "XML parsing Unknown(2)\n" );
steiger 0:7c97dcef700c 889 #endif
steiger 0:7c97dcef700c 890 returnNode = new TiXmlUnknown();
steiger 0:7c97dcef700c 891 }
steiger 0:7c97dcef700c 892
steiger 0:7c97dcef700c 893 if ( returnNode )
steiger 0:7c97dcef700c 894 {
steiger 0:7c97dcef700c 895 // Set the parent, so it can report errors
steiger 0:7c97dcef700c 896 returnNode->parent = this;
steiger 0:7c97dcef700c 897 }
steiger 0:7c97dcef700c 898 return returnNode;
steiger 0:7c97dcef700c 899 }
steiger 0:7c97dcef700c 900
steiger 0:7c97dcef700c 901 #ifdef TIXML_USE_STL
steiger 0:7c97dcef700c 902
steiger 0:7c97dcef700c 903 void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag)
steiger 0:7c97dcef700c 904 {
steiger 0:7c97dcef700c 905 // We're called with some amount of pre-parsing. That is, some of "this"
steiger 0:7c97dcef700c 906 // element is in "tag". Go ahead and stream to the closing ">"
steiger 0:7c97dcef700c 907 while( in->good() )
steiger 0:7c97dcef700c 908 {
steiger 0:7c97dcef700c 909 int c = in->get();
steiger 0:7c97dcef700c 910 if ( c <= 0 )
steiger 0:7c97dcef700c 911 {
steiger 0:7c97dcef700c 912 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 913 if ( document )
steiger 0:7c97dcef700c 914 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 915 return;
steiger 0:7c97dcef700c 916 }
steiger 0:7c97dcef700c 917 (*tag) += (char) c ;
steiger 0:7c97dcef700c 918
steiger 0:7c97dcef700c 919 if ( c == '>' )
steiger 0:7c97dcef700c 920 break;
steiger 0:7c97dcef700c 921 }
steiger 0:7c97dcef700c 922
steiger 0:7c97dcef700c 923 if ( tag->length() < 3 ) return;
steiger 0:7c97dcef700c 924
steiger 0:7c97dcef700c 925 // Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
steiger 0:7c97dcef700c 926 // If not, identify and stream.
steiger 0:7c97dcef700c 927
steiger 0:7c97dcef700c 928 if ( tag->at( tag->length() - 1 ) == '>'
steiger 0:7c97dcef700c 929 && tag->at( tag->length() - 2 ) == '/' )
steiger 0:7c97dcef700c 930 {
steiger 0:7c97dcef700c 931 // All good!
steiger 0:7c97dcef700c 932 return;
steiger 0:7c97dcef700c 933 }
steiger 0:7c97dcef700c 934 else if ( tag->at( tag->length() - 1 ) == '>' )
steiger 0:7c97dcef700c 935 {
steiger 0:7c97dcef700c 936 // There is more. Could be:
steiger 0:7c97dcef700c 937 // text
steiger 0:7c97dcef700c 938 // cdata text (which looks like another node)
steiger 0:7c97dcef700c 939 // closing tag
steiger 0:7c97dcef700c 940 // another node.
steiger 0:7c97dcef700c 941 for ( ;; )
steiger 0:7c97dcef700c 942 {
steiger 0:7c97dcef700c 943 StreamWhiteSpace( in, tag );
steiger 0:7c97dcef700c 944
steiger 0:7c97dcef700c 945 // Do we have text?
steiger 0:7c97dcef700c 946 if ( in->good() && in->peek() != '<' )
steiger 0:7c97dcef700c 947 {
steiger 0:7c97dcef700c 948 // Yep, text.
steiger 0:7c97dcef700c 949 TiXmlText text( "" );
steiger 0:7c97dcef700c 950 text.StreamIn( in, tag );
steiger 0:7c97dcef700c 951
steiger 0:7c97dcef700c 952 // What follows text is a closing tag or another node.
steiger 0:7c97dcef700c 953 // Go around again and figure it out.
steiger 0:7c97dcef700c 954 continue;
steiger 0:7c97dcef700c 955 }
steiger 0:7c97dcef700c 956
steiger 0:7c97dcef700c 957 // We now have either a closing tag...or another node.
steiger 0:7c97dcef700c 958 // We should be at a "<", regardless.
steiger 0:7c97dcef700c 959 if ( !in->good() ) return;
steiger 0:7c97dcef700c 960 assert( in->peek() == '<' );
steiger 0:7c97dcef700c 961 int tagIndex = (int) tag->length();
steiger 0:7c97dcef700c 962
steiger 0:7c97dcef700c 963 bool closingTag = false;
steiger 0:7c97dcef700c 964 bool firstCharFound = false;
steiger 0:7c97dcef700c 965
steiger 0:7c97dcef700c 966 for( ;; )
steiger 0:7c97dcef700c 967 {
steiger 0:7c97dcef700c 968 if ( !in->good() )
steiger 0:7c97dcef700c 969 return;
steiger 0:7c97dcef700c 970
steiger 0:7c97dcef700c 971 int c = in->peek();
steiger 0:7c97dcef700c 972 if ( c <= 0 )
steiger 0:7c97dcef700c 973 {
steiger 0:7c97dcef700c 974 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 975 if ( document )
steiger 0:7c97dcef700c 976 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 977 return;
steiger 0:7c97dcef700c 978 }
steiger 0:7c97dcef700c 979
steiger 0:7c97dcef700c 980 if ( c == '>' )
steiger 0:7c97dcef700c 981 break;
steiger 0:7c97dcef700c 982
steiger 0:7c97dcef700c 983 *tag += (char) c;
steiger 0:7c97dcef700c 984 in->get();
steiger 0:7c97dcef700c 985
steiger 0:7c97dcef700c 986 // Early out if we find the CDATA id.
steiger 0:7c97dcef700c 987 if ( c == '[' && tag->size() >= 9 )
steiger 0:7c97dcef700c 988 {
steiger 0:7c97dcef700c 989 size_t len = tag->size();
steiger 0:7c97dcef700c 990 const char* start = tag->c_str() + len - 9;
steiger 0:7c97dcef700c 991 if ( strcmp( start, "<![CDATA[" ) == 0 ) {
steiger 0:7c97dcef700c 992 assert( !closingTag );
steiger 0:7c97dcef700c 993 break;
steiger 0:7c97dcef700c 994 }
steiger 0:7c97dcef700c 995 }
steiger 0:7c97dcef700c 996
steiger 0:7c97dcef700c 997 if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
steiger 0:7c97dcef700c 998 {
steiger 0:7c97dcef700c 999 firstCharFound = true;
steiger 0:7c97dcef700c 1000 if ( c == '/' )
steiger 0:7c97dcef700c 1001 closingTag = true;
steiger 0:7c97dcef700c 1002 }
steiger 0:7c97dcef700c 1003 }
steiger 0:7c97dcef700c 1004 // If it was a closing tag, then read in the closing '>' to clean up the input stream.
steiger 0:7c97dcef700c 1005 // If it was not, the streaming will be done by the tag.
steiger 0:7c97dcef700c 1006 if ( closingTag )
steiger 0:7c97dcef700c 1007 {
steiger 0:7c97dcef700c 1008 if ( !in->good() )
steiger 0:7c97dcef700c 1009 return;
steiger 0:7c97dcef700c 1010
steiger 0:7c97dcef700c 1011 int c = in->get();
steiger 0:7c97dcef700c 1012 if ( c <= 0 )
steiger 0:7c97dcef700c 1013 {
steiger 0:7c97dcef700c 1014 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 1015 if ( document )
steiger 0:7c97dcef700c 1016 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 1017 return;
steiger 0:7c97dcef700c 1018 }
steiger 0:7c97dcef700c 1019 assert( c == '>' );
steiger 0:7c97dcef700c 1020 *tag += (char) c;
steiger 0:7c97dcef700c 1021
steiger 0:7c97dcef700c 1022 // We are done, once we've found our closing tag.
steiger 0:7c97dcef700c 1023 return;
steiger 0:7c97dcef700c 1024 }
steiger 0:7c97dcef700c 1025 else
steiger 0:7c97dcef700c 1026 {
steiger 0:7c97dcef700c 1027 // If not a closing tag, id it, and stream.
steiger 0:7c97dcef700c 1028 const char* tagloc = tag->c_str() + tagIndex;
steiger 0:7c97dcef700c 1029 TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING );
steiger 0:7c97dcef700c 1030 if ( !node )
steiger 0:7c97dcef700c 1031 return;
steiger 0:7c97dcef700c 1032 node->StreamIn( in, tag );
steiger 0:7c97dcef700c 1033 delete node;
steiger 0:7c97dcef700c 1034 node = 0;
steiger 0:7c97dcef700c 1035
steiger 0:7c97dcef700c 1036 // No return: go around from the beginning: text, closing tag, or node.
steiger 0:7c97dcef700c 1037 }
steiger 0:7c97dcef700c 1038 }
steiger 0:7c97dcef700c 1039 }
steiger 0:7c97dcef700c 1040 }
steiger 0:7c97dcef700c 1041 #endif
steiger 0:7c97dcef700c 1042
steiger 0:7c97dcef700c 1043 const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 1044 {
steiger 0:7c97dcef700c 1045 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 1046 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 1047
steiger 0:7c97dcef700c 1048 if ( !p || !*p )
steiger 0:7c97dcef700c 1049 {
steiger 0:7c97dcef700c 1050 if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
steiger 0:7c97dcef700c 1051 return 0;
steiger 0:7c97dcef700c 1052 }
steiger 0:7c97dcef700c 1053
steiger 0:7c97dcef700c 1054 if ( data )
steiger 0:7c97dcef700c 1055 {
steiger 0:7c97dcef700c 1056 data->Stamp( p, encoding );
steiger 0:7c97dcef700c 1057 location = data->Cursor();
steiger 0:7c97dcef700c 1058 }
steiger 0:7c97dcef700c 1059
steiger 0:7c97dcef700c 1060 if ( *p != '<' )
steiger 0:7c97dcef700c 1061 {
steiger 0:7c97dcef700c 1062 if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
steiger 0:7c97dcef700c 1063 return 0;
steiger 0:7c97dcef700c 1064 }
steiger 0:7c97dcef700c 1065
steiger 0:7c97dcef700c 1066 p = SkipWhiteSpace( p+1, encoding );
steiger 0:7c97dcef700c 1067
steiger 0:7c97dcef700c 1068 // Read the name.
steiger 0:7c97dcef700c 1069 const char* pErr = p;
steiger 0:7c97dcef700c 1070
steiger 0:7c97dcef700c 1071 p = ReadName( p, &value, encoding );
steiger 0:7c97dcef700c 1072 if ( !p || !*p )
steiger 0:7c97dcef700c 1073 {
steiger 0:7c97dcef700c 1074 if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
steiger 0:7c97dcef700c 1075 return 0;
steiger 0:7c97dcef700c 1076 }
steiger 0:7c97dcef700c 1077
steiger 0:7c97dcef700c 1078 TIXML_STRING endTag ("</");
steiger 0:7c97dcef700c 1079 endTag += value;
steiger 0:7c97dcef700c 1080
steiger 0:7c97dcef700c 1081 // Check for and read attributes. Also look for an empty
steiger 0:7c97dcef700c 1082 // tag or an end tag.
steiger 0:7c97dcef700c 1083 while ( p && *p )
steiger 0:7c97dcef700c 1084 {
steiger 0:7c97dcef700c 1085 pErr = p;
steiger 0:7c97dcef700c 1086 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 1087 if ( !p || !*p )
steiger 0:7c97dcef700c 1088 {
steiger 0:7c97dcef700c 1089 if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
steiger 0:7c97dcef700c 1090 return 0;
steiger 0:7c97dcef700c 1091 }
steiger 0:7c97dcef700c 1092 if ( *p == '/' )
steiger 0:7c97dcef700c 1093 {
steiger 0:7c97dcef700c 1094 ++p;
steiger 0:7c97dcef700c 1095 // Empty tag.
steiger 0:7c97dcef700c 1096 if ( *p != '>' )
steiger 0:7c97dcef700c 1097 {
steiger 0:7c97dcef700c 1098 if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );
steiger 0:7c97dcef700c 1099 return 0;
steiger 0:7c97dcef700c 1100 }
steiger 0:7c97dcef700c 1101 return (p+1);
steiger 0:7c97dcef700c 1102 }
steiger 0:7c97dcef700c 1103 else if ( *p == '>' )
steiger 0:7c97dcef700c 1104 {
steiger 0:7c97dcef700c 1105 // Done with attributes (if there were any.)
steiger 0:7c97dcef700c 1106 // Read the value -- which can include other
steiger 0:7c97dcef700c 1107 // elements -- read the end tag, and return.
steiger 0:7c97dcef700c 1108 ++p;
steiger 0:7c97dcef700c 1109 p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens.
steiger 0:7c97dcef700c 1110 if ( !p || !*p ) {
steiger 0:7c97dcef700c 1111 // We were looking for the end tag, but found nothing.
steiger 0:7c97dcef700c 1112 // Fix for [ 1663758 ] Failure to report error on bad XML
steiger 0:7c97dcef700c 1113 if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
steiger 0:7c97dcef700c 1114 return 0;
steiger 0:7c97dcef700c 1115 }
steiger 0:7c97dcef700c 1116
steiger 0:7c97dcef700c 1117 // We should find the end tag now
steiger 0:7c97dcef700c 1118 // note that:
steiger 0:7c97dcef700c 1119 // </foo > and
steiger 0:7c97dcef700c 1120 // </foo>
steiger 0:7c97dcef700c 1121 // are both valid end tags.
steiger 0:7c97dcef700c 1122 if ( StringEqual( p, endTag.c_str(), false, encoding ) )
steiger 0:7c97dcef700c 1123 {
steiger 0:7c97dcef700c 1124 p += endTag.length();
steiger 0:7c97dcef700c 1125 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 1126 if ( p && *p && *p == '>' ) {
steiger 0:7c97dcef700c 1127 ++p;
steiger 0:7c97dcef700c 1128 return p;
steiger 0:7c97dcef700c 1129 }
steiger 0:7c97dcef700c 1130 if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
steiger 0:7c97dcef700c 1131 return 0;
steiger 0:7c97dcef700c 1132 }
steiger 0:7c97dcef700c 1133 else
steiger 0:7c97dcef700c 1134 {
steiger 0:7c97dcef700c 1135 if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
steiger 0:7c97dcef700c 1136 return 0;
steiger 0:7c97dcef700c 1137 }
steiger 0:7c97dcef700c 1138 }
steiger 0:7c97dcef700c 1139 else
steiger 0:7c97dcef700c 1140 {
steiger 0:7c97dcef700c 1141 // Try to read an attribute:
steiger 0:7c97dcef700c 1142 TiXmlAttribute* attrib = new TiXmlAttribute();
steiger 0:7c97dcef700c 1143 if ( !attrib )
steiger 0:7c97dcef700c 1144 {
steiger 0:7c97dcef700c 1145 return 0;
steiger 0:7c97dcef700c 1146 }
steiger 0:7c97dcef700c 1147
steiger 0:7c97dcef700c 1148 attrib->SetDocument( document );
steiger 0:7c97dcef700c 1149 pErr = p;
steiger 0:7c97dcef700c 1150 p = attrib->Parse( p, data, encoding );
steiger 0:7c97dcef700c 1151
steiger 0:7c97dcef700c 1152 if ( !p || !*p )
steiger 0:7c97dcef700c 1153 {
steiger 0:7c97dcef700c 1154 if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
steiger 0:7c97dcef700c 1155 delete attrib;
steiger 0:7c97dcef700c 1156 return 0;
steiger 0:7c97dcef700c 1157 }
steiger 0:7c97dcef700c 1158
steiger 0:7c97dcef700c 1159 // Handle the strange case of double attributes:
steiger 0:7c97dcef700c 1160 #ifdef TIXML_USE_STL
steiger 0:7c97dcef700c 1161 TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() );
steiger 0:7c97dcef700c 1162 #else
steiger 0:7c97dcef700c 1163 TiXmlAttribute* node = attributeSet.Find( attrib->Name() );
steiger 0:7c97dcef700c 1164 #endif
steiger 0:7c97dcef700c 1165 if ( node )
steiger 0:7c97dcef700c 1166 {
steiger 0:7c97dcef700c 1167 if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
steiger 0:7c97dcef700c 1168 delete attrib;
steiger 0:7c97dcef700c 1169 return 0;
steiger 0:7c97dcef700c 1170 }
steiger 0:7c97dcef700c 1171
steiger 0:7c97dcef700c 1172 attributeSet.Add( attrib );
steiger 0:7c97dcef700c 1173 }
steiger 0:7c97dcef700c 1174 }
steiger 0:7c97dcef700c 1175 return p;
steiger 0:7c97dcef700c 1176 }
steiger 0:7c97dcef700c 1177
steiger 0:7c97dcef700c 1178
steiger 0:7c97dcef700c 1179 const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 1180 {
steiger 0:7c97dcef700c 1181 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 1182
steiger 0:7c97dcef700c 1183 // Read in text and elements in any order.
steiger 0:7c97dcef700c 1184 const char* pWithWhiteSpace = p;
steiger 0:7c97dcef700c 1185 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 1186
steiger 0:7c97dcef700c 1187 while ( p && *p )
steiger 0:7c97dcef700c 1188 {
steiger 0:7c97dcef700c 1189 if ( *p != '<' )
steiger 0:7c97dcef700c 1190 {
steiger 0:7c97dcef700c 1191 // Take what we have, make a text element.
steiger 0:7c97dcef700c 1192 TiXmlText* textNode = new TiXmlText( "" );
steiger 0:7c97dcef700c 1193
steiger 0:7c97dcef700c 1194 if ( !textNode )
steiger 0:7c97dcef700c 1195 {
steiger 0:7c97dcef700c 1196 return 0;
steiger 0:7c97dcef700c 1197 }
steiger 0:7c97dcef700c 1198
steiger 0:7c97dcef700c 1199 if ( TiXmlBase::IsWhiteSpaceCondensed() )
steiger 0:7c97dcef700c 1200 {
steiger 0:7c97dcef700c 1201 p = textNode->Parse( p, data, encoding );
steiger 0:7c97dcef700c 1202 }
steiger 0:7c97dcef700c 1203 else
steiger 0:7c97dcef700c 1204 {
steiger 0:7c97dcef700c 1205 // Special case: we want to keep the white space
steiger 0:7c97dcef700c 1206 // so that leading spaces aren't removed.
steiger 0:7c97dcef700c 1207 p = textNode->Parse( pWithWhiteSpace, data, encoding );
steiger 0:7c97dcef700c 1208 }
steiger 0:7c97dcef700c 1209
steiger 0:7c97dcef700c 1210 if ( !textNode->Blank() )
steiger 0:7c97dcef700c 1211 LinkEndChild( textNode );
steiger 0:7c97dcef700c 1212 else
steiger 0:7c97dcef700c 1213 delete textNode;
steiger 0:7c97dcef700c 1214 }
steiger 0:7c97dcef700c 1215 else
steiger 0:7c97dcef700c 1216 {
steiger 0:7c97dcef700c 1217 // We hit a '<'
steiger 0:7c97dcef700c 1218 // Have we hit a new element or an end tag? This could also be
steiger 0:7c97dcef700c 1219 // a TiXmlText in the "CDATA" style.
steiger 0:7c97dcef700c 1220 if ( StringEqual( p, "</", false, encoding ) )
steiger 0:7c97dcef700c 1221 {
steiger 0:7c97dcef700c 1222 return p;
steiger 0:7c97dcef700c 1223 }
steiger 0:7c97dcef700c 1224 else
steiger 0:7c97dcef700c 1225 {
steiger 0:7c97dcef700c 1226 TiXmlNode* node = Identify( p, encoding );
steiger 0:7c97dcef700c 1227 if ( node )
steiger 0:7c97dcef700c 1228 {
steiger 0:7c97dcef700c 1229 p = node->Parse( p, data, encoding );
steiger 0:7c97dcef700c 1230 LinkEndChild( node );
steiger 0:7c97dcef700c 1231 }
steiger 0:7c97dcef700c 1232 else
steiger 0:7c97dcef700c 1233 {
steiger 0:7c97dcef700c 1234 return 0;
steiger 0:7c97dcef700c 1235 }
steiger 0:7c97dcef700c 1236 }
steiger 0:7c97dcef700c 1237 }
steiger 0:7c97dcef700c 1238 pWithWhiteSpace = p;
steiger 0:7c97dcef700c 1239 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 1240 }
steiger 0:7c97dcef700c 1241
steiger 0:7c97dcef700c 1242 if ( !p )
steiger 0:7c97dcef700c 1243 {
steiger 0:7c97dcef700c 1244 if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding );
steiger 0:7c97dcef700c 1245 }
steiger 0:7c97dcef700c 1246 return p;
steiger 0:7c97dcef700c 1247 }
steiger 0:7c97dcef700c 1248
steiger 0:7c97dcef700c 1249
steiger 0:7c97dcef700c 1250 #ifdef TIXML_USE_STL
steiger 0:7c97dcef700c 1251 void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag )
steiger 0:7c97dcef700c 1252 {
steiger 0:7c97dcef700c 1253 while ( in->good() )
steiger 0:7c97dcef700c 1254 {
steiger 0:7c97dcef700c 1255 int c = in->get();
steiger 0:7c97dcef700c 1256 if ( c <= 0 )
steiger 0:7c97dcef700c 1257 {
steiger 0:7c97dcef700c 1258 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 1259 if ( document )
steiger 0:7c97dcef700c 1260 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 1261 return;
steiger 0:7c97dcef700c 1262 }
steiger 0:7c97dcef700c 1263 (*tag) += (char) c;
steiger 0:7c97dcef700c 1264
steiger 0:7c97dcef700c 1265 if ( c == '>' )
steiger 0:7c97dcef700c 1266 {
steiger 0:7c97dcef700c 1267 // All is well.
steiger 0:7c97dcef700c 1268 return;
steiger 0:7c97dcef700c 1269 }
steiger 0:7c97dcef700c 1270 }
steiger 0:7c97dcef700c 1271 }
steiger 0:7c97dcef700c 1272 #endif
steiger 0:7c97dcef700c 1273
steiger 0:7c97dcef700c 1274
steiger 0:7c97dcef700c 1275 const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 1276 {
steiger 0:7c97dcef700c 1277 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 1278 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 1279
steiger 0:7c97dcef700c 1280 if ( data )
steiger 0:7c97dcef700c 1281 {
steiger 0:7c97dcef700c 1282 data->Stamp( p, encoding );
steiger 0:7c97dcef700c 1283 location = data->Cursor();
steiger 0:7c97dcef700c 1284 }
steiger 0:7c97dcef700c 1285 if ( !p || !*p || *p != '<' )
steiger 0:7c97dcef700c 1286 {
steiger 0:7c97dcef700c 1287 if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding );
steiger 0:7c97dcef700c 1288 return 0;
steiger 0:7c97dcef700c 1289 }
steiger 0:7c97dcef700c 1290 ++p;
steiger 0:7c97dcef700c 1291 value = "";
steiger 0:7c97dcef700c 1292
steiger 0:7c97dcef700c 1293 while ( p && *p && *p != '>' )
steiger 0:7c97dcef700c 1294 {
steiger 0:7c97dcef700c 1295 value += *p;
steiger 0:7c97dcef700c 1296 ++p;
steiger 0:7c97dcef700c 1297 }
steiger 0:7c97dcef700c 1298
steiger 0:7c97dcef700c 1299 if ( !p )
steiger 0:7c97dcef700c 1300 {
steiger 0:7c97dcef700c 1301 if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
steiger 0:7c97dcef700c 1302 }
steiger 0:7c97dcef700c 1303 if ( *p == '>' )
steiger 0:7c97dcef700c 1304 return p+1;
steiger 0:7c97dcef700c 1305 return p;
steiger 0:7c97dcef700c 1306 }
steiger 0:7c97dcef700c 1307
steiger 0:7c97dcef700c 1308 #ifdef TIXML_USE_STL
steiger 0:7c97dcef700c 1309 void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag )
steiger 0:7c97dcef700c 1310 {
steiger 0:7c97dcef700c 1311 while ( in->good() )
steiger 0:7c97dcef700c 1312 {
steiger 0:7c97dcef700c 1313 int c = in->get();
steiger 0:7c97dcef700c 1314 if ( c <= 0 )
steiger 0:7c97dcef700c 1315 {
steiger 0:7c97dcef700c 1316 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 1317 if ( document )
steiger 0:7c97dcef700c 1318 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 1319 return;
steiger 0:7c97dcef700c 1320 }
steiger 0:7c97dcef700c 1321
steiger 0:7c97dcef700c 1322 (*tag) += (char) c;
steiger 0:7c97dcef700c 1323
steiger 0:7c97dcef700c 1324 if ( c == '>'
steiger 0:7c97dcef700c 1325 && tag->at( tag->length() - 2 ) == '-'
steiger 0:7c97dcef700c 1326 && tag->at( tag->length() - 3 ) == '-' )
steiger 0:7c97dcef700c 1327 {
steiger 0:7c97dcef700c 1328 // All is well.
steiger 0:7c97dcef700c 1329 return;
steiger 0:7c97dcef700c 1330 }
steiger 0:7c97dcef700c 1331 }
steiger 0:7c97dcef700c 1332 }
steiger 0:7c97dcef700c 1333 #endif
steiger 0:7c97dcef700c 1334
steiger 0:7c97dcef700c 1335
steiger 0:7c97dcef700c 1336 const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 1337 {
steiger 0:7c97dcef700c 1338 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 1339 value = "";
steiger 0:7c97dcef700c 1340
steiger 0:7c97dcef700c 1341 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 1342
steiger 0:7c97dcef700c 1343 if ( data )
steiger 0:7c97dcef700c 1344 {
steiger 0:7c97dcef700c 1345 data->Stamp( p, encoding );
steiger 0:7c97dcef700c 1346 location = data->Cursor();
steiger 0:7c97dcef700c 1347 }
steiger 0:7c97dcef700c 1348 const char* startTag = "<!--";
steiger 0:7c97dcef700c 1349 const char* endTag = "-->";
steiger 0:7c97dcef700c 1350
steiger 0:7c97dcef700c 1351 if ( !StringEqual( p, startTag, false, encoding ) )
steiger 0:7c97dcef700c 1352 {
steiger 0:7c97dcef700c 1353 document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
steiger 0:7c97dcef700c 1354 return 0;
steiger 0:7c97dcef700c 1355 }
steiger 0:7c97dcef700c 1356 p += strlen( startTag );
steiger 0:7c97dcef700c 1357
steiger 0:7c97dcef700c 1358 // [ 1475201 ] TinyXML parses entities in comments
steiger 0:7c97dcef700c 1359 // Oops - ReadText doesn't work, because we don't want to parse the entities.
steiger 0:7c97dcef700c 1360 // p = ReadText( p, &value, false, endTag, false, encoding );
steiger 0:7c97dcef700c 1361 //
steiger 0:7c97dcef700c 1362 // from the XML spec:
steiger 0:7c97dcef700c 1363 /*
steiger 0:7c97dcef700c 1364 [Definition: Comments may appear anywhere in a document outside other markup; in addition,
steiger 0:7c97dcef700c 1365 they may appear within the document type declaration at places allowed by the grammar.
steiger 0:7c97dcef700c 1366 They are not part of the document's character data; an XML processor MAY, but need not,
steiger 0:7c97dcef700c 1367 make it possible for an application to retrieve the text of comments. For compatibility,
steiger 0:7c97dcef700c 1368 the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity
steiger 0:7c97dcef700c 1369 references MUST NOT be recognized within comments.
steiger 0:7c97dcef700c 1370
steiger 0:7c97dcef700c 1371 An example of a comment:
steiger 0:7c97dcef700c 1372
steiger 0:7c97dcef700c 1373 <!-- declarations for <head> & <body> -->
steiger 0:7c97dcef700c 1374 */
steiger 0:7c97dcef700c 1375
steiger 0:7c97dcef700c 1376 value = "";
steiger 0:7c97dcef700c 1377 // Keep all the white space.
steiger 0:7c97dcef700c 1378 while ( p && *p && !StringEqual( p, endTag, false, encoding ) )
steiger 0:7c97dcef700c 1379 {
steiger 0:7c97dcef700c 1380 value.append( p, 1 );
steiger 0:7c97dcef700c 1381 ++p;
steiger 0:7c97dcef700c 1382 }
steiger 0:7c97dcef700c 1383 if ( p && *p )
steiger 0:7c97dcef700c 1384 p += strlen( endTag );
steiger 0:7c97dcef700c 1385
steiger 0:7c97dcef700c 1386 return p;
steiger 0:7c97dcef700c 1387 }
steiger 0:7c97dcef700c 1388
steiger 0:7c97dcef700c 1389
steiger 0:7c97dcef700c 1390 const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 1391 {
steiger 0:7c97dcef700c 1392 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 1393 if ( !p || !*p ) return 0;
steiger 0:7c97dcef700c 1394
steiger 0:7c97dcef700c 1395 if ( data )
steiger 0:7c97dcef700c 1396 {
steiger 0:7c97dcef700c 1397 data->Stamp( p, encoding );
steiger 0:7c97dcef700c 1398 location = data->Cursor();
steiger 0:7c97dcef700c 1399 }
steiger 0:7c97dcef700c 1400 // Read the name, the '=' and the value.
steiger 0:7c97dcef700c 1401 const char* pErr = p;
steiger 0:7c97dcef700c 1402 p = ReadName( p, &name, encoding );
steiger 0:7c97dcef700c 1403 if ( !p || !*p )
steiger 0:7c97dcef700c 1404 {
steiger 0:7c97dcef700c 1405 if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
steiger 0:7c97dcef700c 1406 return 0;
steiger 0:7c97dcef700c 1407 }
steiger 0:7c97dcef700c 1408 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 1409 if ( !p || !*p || *p != '=' )
steiger 0:7c97dcef700c 1410 {
steiger 0:7c97dcef700c 1411 if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
steiger 0:7c97dcef700c 1412 return 0;
steiger 0:7c97dcef700c 1413 }
steiger 0:7c97dcef700c 1414
steiger 0:7c97dcef700c 1415 ++p; // skip '='
steiger 0:7c97dcef700c 1416 p = SkipWhiteSpace( p, encoding );
steiger 0:7c97dcef700c 1417 if ( !p || !*p )
steiger 0:7c97dcef700c 1418 {
steiger 0:7c97dcef700c 1419 if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
steiger 0:7c97dcef700c 1420 return 0;
steiger 0:7c97dcef700c 1421 }
steiger 0:7c97dcef700c 1422
steiger 0:7c97dcef700c 1423 const char* end;
steiger 0:7c97dcef700c 1424 const char SINGLE_QUOTE = '\'';
steiger 0:7c97dcef700c 1425 const char DOUBLE_QUOTE = '\"';
steiger 0:7c97dcef700c 1426
steiger 0:7c97dcef700c 1427 if ( *p == SINGLE_QUOTE )
steiger 0:7c97dcef700c 1428 {
steiger 0:7c97dcef700c 1429 ++p;
steiger 0:7c97dcef700c 1430 end = "\'"; // single quote in string
steiger 0:7c97dcef700c 1431 p = ReadText( p, &value, false, end, false, encoding );
steiger 0:7c97dcef700c 1432 }
steiger 0:7c97dcef700c 1433 else if ( *p == DOUBLE_QUOTE )
steiger 0:7c97dcef700c 1434 {
steiger 0:7c97dcef700c 1435 ++p;
steiger 0:7c97dcef700c 1436 end = "\""; // double quote in string
steiger 0:7c97dcef700c 1437 p = ReadText( p, &value, false, end, false, encoding );
steiger 0:7c97dcef700c 1438 }
steiger 0:7c97dcef700c 1439 else
steiger 0:7c97dcef700c 1440 {
steiger 0:7c97dcef700c 1441 // All attribute values should be in single or double quotes.
steiger 0:7c97dcef700c 1442 // But this is such a common error that the parser will try
steiger 0:7c97dcef700c 1443 // its best, even without them.
steiger 0:7c97dcef700c 1444 value = "";
steiger 0:7c97dcef700c 1445 while ( p && *p // existence
steiger 0:7c97dcef700c 1446 && !IsWhiteSpace( *p ) // whitespace
steiger 0:7c97dcef700c 1447 && *p != '/' && *p != '>' ) // tag end
steiger 0:7c97dcef700c 1448 {
steiger 0:7c97dcef700c 1449 if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) {
steiger 0:7c97dcef700c 1450 // [ 1451649 ] Attribute values with trailing quotes not handled correctly
steiger 0:7c97dcef700c 1451 // We did not have an opening quote but seem to have a
steiger 0:7c97dcef700c 1452 // closing one. Give up and throw an error.
steiger 0:7c97dcef700c 1453 if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
steiger 0:7c97dcef700c 1454 return 0;
steiger 0:7c97dcef700c 1455 }
steiger 0:7c97dcef700c 1456 value += *p;
steiger 0:7c97dcef700c 1457 ++p;
steiger 0:7c97dcef700c 1458 }
steiger 0:7c97dcef700c 1459 }
steiger 0:7c97dcef700c 1460 return p;
steiger 0:7c97dcef700c 1461 }
steiger 0:7c97dcef700c 1462
steiger 0:7c97dcef700c 1463 #ifdef TIXML_USE_STL
steiger 0:7c97dcef700c 1464 void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag )
steiger 0:7c97dcef700c 1465 {
steiger 0:7c97dcef700c 1466 while ( in->good() )
steiger 0:7c97dcef700c 1467 {
steiger 0:7c97dcef700c 1468 int c = in->peek();
steiger 0:7c97dcef700c 1469 if ( !cdata && (c == '<' ) )
steiger 0:7c97dcef700c 1470 {
steiger 0:7c97dcef700c 1471 return;
steiger 0:7c97dcef700c 1472 }
steiger 0:7c97dcef700c 1473 if ( c <= 0 )
steiger 0:7c97dcef700c 1474 {
steiger 0:7c97dcef700c 1475 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 1476 if ( document )
steiger 0:7c97dcef700c 1477 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 1478 return;
steiger 0:7c97dcef700c 1479 }
steiger 0:7c97dcef700c 1480
steiger 0:7c97dcef700c 1481 (*tag) += (char) c;
steiger 0:7c97dcef700c 1482 in->get(); // "commits" the peek made above
steiger 0:7c97dcef700c 1483
steiger 0:7c97dcef700c 1484 if ( cdata && c == '>' && tag->size() >= 3 ) {
steiger 0:7c97dcef700c 1485 size_t len = tag->size();
steiger 0:7c97dcef700c 1486 if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) {
steiger 0:7c97dcef700c 1487 // terminator of cdata.
steiger 0:7c97dcef700c 1488 return;
steiger 0:7c97dcef700c 1489 }
steiger 0:7c97dcef700c 1490 }
steiger 0:7c97dcef700c 1491 }
steiger 0:7c97dcef700c 1492 }
steiger 0:7c97dcef700c 1493 #endif
steiger 0:7c97dcef700c 1494
steiger 0:7c97dcef700c 1495 const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
steiger 0:7c97dcef700c 1496 {
steiger 0:7c97dcef700c 1497 value = "";
steiger 0:7c97dcef700c 1498 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 1499
steiger 0:7c97dcef700c 1500 if ( data )
steiger 0:7c97dcef700c 1501 {
steiger 0:7c97dcef700c 1502 data->Stamp( p, encoding );
steiger 0:7c97dcef700c 1503 location = data->Cursor();
steiger 0:7c97dcef700c 1504 }
steiger 0:7c97dcef700c 1505
steiger 0:7c97dcef700c 1506 const char* const startTag = "<![CDATA[";
steiger 0:7c97dcef700c 1507 const char* const endTag = "]]>";
steiger 0:7c97dcef700c 1508
steiger 0:7c97dcef700c 1509 if ( cdata || StringEqual( p, startTag, false, encoding ) )
steiger 0:7c97dcef700c 1510 {
steiger 0:7c97dcef700c 1511 cdata = true;
steiger 0:7c97dcef700c 1512
steiger 0:7c97dcef700c 1513 if ( !StringEqual( p, startTag, false, encoding ) )
steiger 0:7c97dcef700c 1514 {
steiger 0:7c97dcef700c 1515 document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding );
steiger 0:7c97dcef700c 1516 return 0;
steiger 0:7c97dcef700c 1517 }
steiger 0:7c97dcef700c 1518 p += strlen( startTag );
steiger 0:7c97dcef700c 1519
steiger 0:7c97dcef700c 1520 // Keep all the white space, ignore the encoding, etc.
steiger 0:7c97dcef700c 1521 while ( p && *p
steiger 0:7c97dcef700c 1522 && !StringEqual( p, endTag, false, encoding )
steiger 0:7c97dcef700c 1523 )
steiger 0:7c97dcef700c 1524 {
steiger 0:7c97dcef700c 1525 value += *p;
steiger 0:7c97dcef700c 1526 ++p;
steiger 0:7c97dcef700c 1527 }
steiger 0:7c97dcef700c 1528
steiger 0:7c97dcef700c 1529 TIXML_STRING dummy;
steiger 0:7c97dcef700c 1530 p = ReadText( p, &dummy, false, endTag, false, encoding );
steiger 0:7c97dcef700c 1531 return p;
steiger 0:7c97dcef700c 1532 }
steiger 0:7c97dcef700c 1533 else
steiger 0:7c97dcef700c 1534 {
steiger 0:7c97dcef700c 1535 bool ignoreWhite = true;
steiger 0:7c97dcef700c 1536
steiger 0:7c97dcef700c 1537 const char* end = "<";
steiger 0:7c97dcef700c 1538 p = ReadText( p, &value, ignoreWhite, end, false, encoding );
steiger 0:7c97dcef700c 1539 if ( p )
steiger 0:7c97dcef700c 1540 return p-1; // don't truncate the '<'
steiger 0:7c97dcef700c 1541 return 0;
steiger 0:7c97dcef700c 1542 }
steiger 0:7c97dcef700c 1543 }
steiger 0:7c97dcef700c 1544
steiger 0:7c97dcef700c 1545 #ifdef TIXML_USE_STL
steiger 0:7c97dcef700c 1546 void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag )
steiger 0:7c97dcef700c 1547 {
steiger 0:7c97dcef700c 1548 while ( in->good() )
steiger 0:7c97dcef700c 1549 {
steiger 0:7c97dcef700c 1550 int c = in->get();
steiger 0:7c97dcef700c 1551 if ( c <= 0 )
steiger 0:7c97dcef700c 1552 {
steiger 0:7c97dcef700c 1553 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 1554 if ( document )
steiger 0:7c97dcef700c 1555 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
steiger 0:7c97dcef700c 1556 return;
steiger 0:7c97dcef700c 1557 }
steiger 0:7c97dcef700c 1558 (*tag) += (char) c;
steiger 0:7c97dcef700c 1559
steiger 0:7c97dcef700c 1560 if ( c == '>' )
steiger 0:7c97dcef700c 1561 {
steiger 0:7c97dcef700c 1562 // All is well.
steiger 0:7c97dcef700c 1563 return;
steiger 0:7c97dcef700c 1564 }
steiger 0:7c97dcef700c 1565 }
steiger 0:7c97dcef700c 1566 }
steiger 0:7c97dcef700c 1567 #endif
steiger 0:7c97dcef700c 1568
steiger 0:7c97dcef700c 1569 const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
steiger 0:7c97dcef700c 1570 {
steiger 0:7c97dcef700c 1571 p = SkipWhiteSpace( p, _encoding );
steiger 0:7c97dcef700c 1572 // Find the beginning, find the end, and look for
steiger 0:7c97dcef700c 1573 // the stuff in-between.
steiger 0:7c97dcef700c 1574 TiXmlDocument* document = GetDocument();
steiger 0:7c97dcef700c 1575 if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) )
steiger 0:7c97dcef700c 1576 {
steiger 0:7c97dcef700c 1577 if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
steiger 0:7c97dcef700c 1578 return 0;
steiger 0:7c97dcef700c 1579 }
steiger 0:7c97dcef700c 1580 if ( data )
steiger 0:7c97dcef700c 1581 {
steiger 0:7c97dcef700c 1582 data->Stamp( p, _encoding );
steiger 0:7c97dcef700c 1583 location = data->Cursor();
steiger 0:7c97dcef700c 1584 }
steiger 0:7c97dcef700c 1585 p += 5;
steiger 0:7c97dcef700c 1586
steiger 0:7c97dcef700c 1587 version = "";
steiger 0:7c97dcef700c 1588 encoding = "";
steiger 0:7c97dcef700c 1589 standalone = "";
steiger 0:7c97dcef700c 1590
steiger 0:7c97dcef700c 1591 while ( p && *p )
steiger 0:7c97dcef700c 1592 {
steiger 0:7c97dcef700c 1593 if ( *p == '>' )
steiger 0:7c97dcef700c 1594 {
steiger 0:7c97dcef700c 1595 ++p;
steiger 0:7c97dcef700c 1596 return p;
steiger 0:7c97dcef700c 1597 }
steiger 0:7c97dcef700c 1598
steiger 0:7c97dcef700c 1599 p = SkipWhiteSpace( p, _encoding );
steiger 0:7c97dcef700c 1600 if ( StringEqual( p, "version", true, _encoding ) )
steiger 0:7c97dcef700c 1601 {
steiger 0:7c97dcef700c 1602 TiXmlAttribute attrib;
steiger 0:7c97dcef700c 1603 p = attrib.Parse( p, data, _encoding );
steiger 0:7c97dcef700c 1604 version = attrib.Value();
steiger 0:7c97dcef700c 1605 }
steiger 0:7c97dcef700c 1606 else if ( StringEqual( p, "encoding", true, _encoding ) )
steiger 0:7c97dcef700c 1607 {
steiger 0:7c97dcef700c 1608 TiXmlAttribute attrib;
steiger 0:7c97dcef700c 1609 p = attrib.Parse( p, data, _encoding );
steiger 0:7c97dcef700c 1610 encoding = attrib.Value();
steiger 0:7c97dcef700c 1611 }
steiger 0:7c97dcef700c 1612 else if ( StringEqual( p, "standalone", true, _encoding ) )
steiger 0:7c97dcef700c 1613 {
steiger 0:7c97dcef700c 1614 TiXmlAttribute attrib;
steiger 0:7c97dcef700c 1615 p = attrib.Parse( p, data, _encoding );
steiger 0:7c97dcef700c 1616 standalone = attrib.Value();
steiger 0:7c97dcef700c 1617 }
steiger 0:7c97dcef700c 1618 else
steiger 0:7c97dcef700c 1619 {
steiger 0:7c97dcef700c 1620 // Read over whatever it is.
steiger 0:7c97dcef700c 1621 while( p && *p && *p != '>' && !IsWhiteSpace( *p ) )
steiger 0:7c97dcef700c 1622 ++p;
steiger 0:7c97dcef700c 1623 }
steiger 0:7c97dcef700c 1624 }
steiger 0:7c97dcef700c 1625 return 0;
steiger 0:7c97dcef700c 1626 }
steiger 0:7c97dcef700c 1627
steiger 0:7c97dcef700c 1628 bool TiXmlText::Blank() const
steiger 0:7c97dcef700c 1629 {
steiger 0:7c97dcef700c 1630 for ( unsigned i=0; i<value.length(); i++ )
steiger 0:7c97dcef700c 1631 if ( !IsWhiteSpace( value[i] ) )
steiger 0:7c97dcef700c 1632 return false;
steiger 0:7c97dcef700c 1633 return true;
steiger 0:7c97dcef700c 1634 }
steiger 0:7c97dcef700c 1635