00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "xmlpull/XmlPullParser.h"
00022 #include "xmlpull/XmlPullParserException.h"
00023 #include "xmlpull/XmlUtils.h"
00024
00025
00026 XmlPullParser::XmlPullParser (std::istream & is)
00027 :unexpected_eof ("Unexpected EOF"),
00028 illegal_type ("wrong Event Type"),
00029 nspStack (16),
00030 elementStack (16),
00031 attributes (16),
00032 reader (is)
00033 {
00034 initBuf ();
00035 commonInit ();
00036 }
00037
00038
00039 XmlPullParser::XmlPullParser (void)
00040 :unexpected_eof ("Unexpected EOF"),
00041 illegal_type ("wrong Event Type"),
00042 nspStack (16),
00043 elementStack (16),
00044 attributes (16),
00045 reader (std::cin)
00046 {
00047 initBuf ();
00048 commonInit ();
00049 }
00050
00051
00052 void
00053 XmlPullParser::initBuf ()
00054 {
00055 srcBuf = new char[8192];
00056 srcBuflength = 8192;
00057 txtBuf = new char[256];
00058 txtBufSize = 256;
00059 nspCounts = new int[8];
00060 nspSize = 8;
00061 }
00062
00063
00064
00065 void
00066 XmlPullParser::commonInit ()
00067 {
00068 line = 1;
00069 column = 0;
00070 type = START_DOCUMENT;
00071 name = "";
00072 Ns = "";
00073 degenerated = false;
00074 attributeCount = -1;
00075 encoding = "";
00076 version = "";
00077 standalone = false;
00078 unresolved = false;
00079 LEGACY = 999;
00080 XML_DECL = 998;
00081 srcPos = 0;
00082 srcCount = 0;
00083 peekCount = 0;
00084 depth = 0;
00085 relaxed = false;
00086 entityMap["apos"] = "'";
00087 entityMap["gt"] = ">";
00088 entityMap["lt"] = "<";
00089 entityMap["quot"] = "\"";
00090 entityMap["amp"] = "&";
00091 for (int i = 0; i < nspSize; i++)
00092 nspCounts[i] = 0;
00093 }
00094
00095
00096 XmlPullParser::~XmlPullParser (void)
00097 {
00098 delete [] srcBuf;
00099 delete [] txtBuf;
00100 delete [] nspCounts;
00101 }
00102
00103
00104 std::string
00105 XmlPullParser::state (int eventType)
00106 {
00107 switch (eventType)
00108 {
00109 case 0:
00110 return "START_DOCUMENT";
00111 case 1:
00112 return "END_DOCUMENT";
00113 case 2:
00114 return "START_TAG";
00115 case 3:
00116 return "END_TAG";
00117 case 4:
00118 return "TEXT";
00119 case 5:
00120 return "CDSECT";
00121 case 6:
00122 return "ENTITY_REF";
00123 case 7:
00124 return "IGNORABLE_WHITESPACE";
00125 case 8:
00126 return "PROCESSING_INSTRUCTION";
00127 case 9:
00128 return "COMMENT";
00129 case 10:
00130 return "DOCDECL";
00131 default:
00132 return "Illegal state";
00133 break;
00134 }
00135 return "";
00136 }
00137
00138
00139 bool XmlPullParser::isProp (std::string n1, bool prop, std::string n2)
00140 {
00141 if (n1.find ("http://xmlpull.org/v1/doc/") != 0)
00142 return false;
00143 if (prop)
00144 return (n1.substr (42) == n2);
00145 else
00146 return (n1.substr (40) == n2);
00147 }
00148
00149
00150 bool XmlPullParser::adjustNsp ()
00151 {
00152 bool
00153 any = false;
00154 for (int i = 0; i < attributeCount << 2; i += 4)
00155
00156 {
00157 std::string
00158 attrName = attributes[i + 2];
00159 int
00160 cut = attrName.find (":");
00161 std::string
00162 prefx;
00163
00164 if (cut != -1)
00165
00166 {
00167 prefx = attrName.substr (0, cut);
00168 attrName = attrName.substr (cut + 1);
00169 }
00170
00171 else if (attrName == "xmlns")
00172
00173 {
00174 prefx = attrName;
00175 attrName = "";
00176 }
00177
00178 else
00179 continue;
00180 if (prefx != "xmlns")
00181 {
00182 any = true;
00183 }
00184 else
00185 {
00186 unsigned int j = (nspCounts[depth]++) << 1;
00187
00188
00189 if (nspStack.size () <= j + 2)
00190 nspStack.resize (j + 2 + RESIZE_BUFFER);
00191 nspStack[j] = attrName;
00192 nspStack[j + 1] = attributes[i + 3];
00193 if (!attrName.empty () && attributes[i + 3] == "")
00194 exception ("illegal empty namespace");
00195
00196
00197 int to = ((--attributeCount) << 2) - i;
00198 for (int p = 1; p <= to; p++)
00199 attributes[i + p - 1] = attributes[i + 4 + p - 1];
00200 i -= 4;
00201 }
00202 }
00203 if (any)
00204
00205 {
00206 for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4)
00207
00208 {
00209 std::string
00210 attrName = attributes[i + 2];
00211 int
00212 cut = attrName.find (":");
00213 if (cut == 0 && !relaxed)
00214 exception ("illegal attribute name: " + attrName);
00215
00216 else if (cut != -1)
00217
00218 {
00219 std::string
00220 attrPrefix = attrName.substr (0, cut);
00221 attrName = attrName.substr (cut + 1);
00222 std::string
00223 attrNs = getNamespace (attrPrefix);
00224 if (attrNs.empty () && !relaxed)
00225 exception ("Undefined Prefix: " + attrPrefix + " in ");
00226 attributes[i] = attrNs;
00227 attributes[i + 1] = attrPrefix;
00228 attributes[i + 2] = attrName;
00229 if (!relaxed)
00230
00231 {
00232 for (int j = (attributeCount << 2) - 4; j > i; j -= 4)
00233 if (attrName == attributes[j + 2]
00234 && attrNs == attributes[j])
00235 exception ("Duplicate Attribute: {"
00236 + attrNs + "}" + attrName);
00237 }
00238 }
00239 }
00240 }
00241 int cut = name.find (":");
00242 if (cut == 0 && !relaxed)
00243 exception ("illegal tag name: " + name);
00244
00245 else if (cut != -1)
00246 {
00247 prefix = name.substr (0, cut);
00248 name = name.substr (cut + 1);
00249 }
00250 Ns = getNamespace (prefix);
00251 if (Ns.empty ())
00252
00253 {
00254 if (!prefix.empty () && !relaxed)
00255 exception ("undefined prefix: " + prefix);
00256 Ns = NO_NAMESPACE;
00257 }
00258 return any;
00259 }
00260
00261
00262 void
00263 XmlPullParser::exception (std::string desc)
00264 {
00265 XmlPullParserException e (desc, state (type), line, column);
00266 throw e;
00267 }
00268
00269
00270
00271
00272
00273 void
00274 XmlPullParser::nextImpl ()
00275 {
00276 if (type == END_TAG)
00277 depth--;
00278 while (true)
00279 {
00280 attributeCount = -1;
00281 if (degenerated)
00282
00283 {
00284 degenerated = false;
00285 type = END_TAG;
00286 return;
00287 }
00288 prefix = "";
00289 name = "";
00290 Ns = "";
00291 text = "";
00292 type = peekType ();
00293 switch (type)
00294 {
00295 case ENTITY_REF:
00296 pushEntity ();
00297 return;
00298 case START_TAG:
00299 parseStartTag (false);
00300 return;
00301 case END_TAG:
00302 parseEndTag ();
00303 return;
00304 case END_DOCUMENT:
00305 return;
00306 case TEXT:
00307 pushText ('<', !token);
00308 if (depth == 0)
00309
00310 {
00311 if (isWspace)
00312 type = IGNORABLE_WHITESPACE;
00313
00314
00315
00316
00317 }
00318 return;
00319 default:
00320 type = parseLegacy (token);
00321 if (type != XML_DECL)
00322 return;
00323 }
00324 }
00325 }
00326
00327
00328 int
00329 XmlPullParser::parseLegacy (bool bpush)
00330 {
00331 std::string req = "";
00332 int term;
00333 int result;
00334 int prev = 0;
00335 read ();
00336 int c = read ();
00337 if (c == '?')
00338
00339 {
00340 if ((peekbuf (0) == 'x' || peekbuf (0) == 'X')
00341 && (peekbuf (1) == 'm' || peekbuf (1) == 'M'))
00342
00343 {
00344 if (bpush)
00345
00346 {
00347 push (peekbuf (0));
00348 push (peekbuf (1));
00349 }
00350 read ();
00351 read ();
00352 if ((peekbuf (0) == 'l' || peekbuf (0) == 'L')
00353 && peekbuf (1) <= ' ')
00354
00355 {
00356 if (line != 1 || column > 4)
00357 exception ("PI must not start with xml");
00358 parseStartTag (true);
00359 if (attributeCount < 1 || "version" != attributes[2])
00360 exception ("version expected");
00361 version = attributes[3];
00362 int pos = 1;
00363 if (pos < attributeCount && "encoding" == attributes[2 + 4])
00364
00365 {
00366 encoding = attributes[3 + 4];
00367 pos++;
00368 }
00369 if (pos < attributeCount
00370 && "standalone" == attributes[4 * pos + 2])
00371
00372 {
00373 std::string st = attributes[3 + 4 * pos];
00374 if ("yes" == st)
00375 standalone = true;
00376
00377 else if ("no" == st)
00378 standalone = false;
00379
00380 else
00381 exception ("illegal standalone value: " + st);
00382 pos++;
00383 }
00384 if (pos != attributeCount)
00385 exception ("illegal xmldecl");
00386 isWspace = true;
00387 txtPos = 0;
00388 return XML_DECL;
00389 }
00390 }
00391
00392
00393
00394
00395 term = '?';
00396 result = PROCESSING_INSTRUCTION;
00397 }
00398
00399 else if (c == '!')
00400
00401 {
00402 if (peekbuf (0) == '-')
00403
00404 {
00405 result = COMMENT;
00406 req = "--";
00407 term = '-';
00408 }
00409
00410 else if (peekbuf (0) == '[')
00411
00412 {
00413 result = CDSECT;
00414 req = "[CDATA[";
00415 term = ']';
00416 bpush = true;
00417 }
00418
00419 else
00420
00421 {
00422 result = DOCDECL;
00423 req = "DOCTYPE";
00424 term = -1;
00425 }
00426 }
00427
00428 else
00429
00430 {
00431 exception ("illegal: <" + c);
00432 return -1;
00433 }
00434 for (unsigned int i = 0; i < req.length (); i++)
00435 read (req.at (i));
00436 if (result == DOCDECL)
00437 parseDoctype (bpush);
00438
00439 else
00440
00441 {
00442 while (true)
00443
00444 {
00445 c = read ();
00446 if (c == -1)
00447 exception (unexpected_eof);
00448 if (bpush)
00449 push (c);
00450 if ((term == '?' || c == term)
00451 && peekbuf (0) == term && peekbuf (1) == '>')
00452 break;
00453 prev = c;
00454 }
00455 if (term == '-' && prev == '-' && !relaxed)
00456 exception ("illegal comment delimiter: --->");
00457 read ();
00458 read ();
00459 if (bpush && term != '?')
00460 txtPos--;
00461 }
00462 return result;
00463 }
00464
00465
00466
00467 void
00468 XmlPullParser::parseDoctype (bool bpush)
00469 {
00470 int nesting = 1;
00471 bool quoted = false;
00472
00473
00474 while (true)
00475
00476 {
00477 int i = read ();
00478 switch (i)
00479
00480 {
00481 case -1:
00482 exception (unexpected_eof);
00483 case '\'':
00484 quoted = !quoted;
00485 break;
00486 case '<':
00487 if (!quoted)
00488 nesting++;
00489 break;
00490 case '>':
00491 if (!quoted)
00492
00493 {
00494 if ((--nesting) == 0)
00495 return;
00496 }
00497 break;
00498 }
00499 if (bpush)
00500 push (i);
00501 }
00502 }
00503
00504
00505
00506 void
00507 XmlPullParser::parseEndTag ()
00508 {
00509 read ();
00510 read ();
00511 name = readName ();
00512 skip ();
00513 read ('>');
00514 int sp = (depth - 1) << 2;
00515 if (!relaxed)
00516
00517 {
00518 if (depth == 0)
00519 exception ("element stack empty");
00520 if (name != elementStack[sp + 3])
00521 exception ("expected: " + elementStack[sp + 3]);
00522 }
00523
00524 else if (depth == 0 || name != elementStack[sp + 3])
00525 return;
00526 Ns = elementStack[sp];
00527 prefix = elementStack[sp + 1];
00528 name = elementStack[sp + 2];
00529 }
00530
00531
00532 int
00533 XmlPullParser::peekType ()
00534 {
00535 switch (peekbuf (0))
00536
00537 {
00538 case -1:
00539 return END_DOCUMENT;
00540 case '&':
00541 return ENTITY_REF;
00542 case '<':
00543 switch (peekbuf (1))
00544
00545 {
00546 case '/':
00547 return END_TAG;
00548 case '?':
00549 case '!':
00550 return LEGACY;
00551 default:
00552 return START_TAG;
00553 }
00554 default:
00555 return TEXT;
00556 }
00557 }
00558
00559
00560 std::string XmlPullParser::get (int pos)
00561 {
00562 std::string
00563 tmp (txtBuf);
00564 return tmp.substr (pos, txtPos - pos);
00565 }
00566
00567
00568 void
00569 XmlPullParser::push (int c)
00570 {
00571 isWspace &= c <= ' ';
00572 if (txtPos >= txtBufSize - 1)
00573
00574 {
00575 char *bigger = new char[txtBufSize = txtPos * 4 / 3 + 4];
00576 memcpy (bigger, txtBuf, txtPos);
00577 delete[] txtBuf;
00578 txtBuf = bigger;
00579 }
00580 txtBuf[txtPos++] = (char) c;
00581 txtBuf[txtPos] = 0;
00582 }
00583
00584
00585
00586 void
00587 XmlPullParser::parseStartTag (bool xmldecl)
00588 {
00589 if (!xmldecl)
00590 read ();
00591 name = readName ();
00592 attributeCount = 0;
00593 while (true)
00594
00595 {
00596 skip ();
00597 int c = peekbuf (0);
00598 if (xmldecl)
00599
00600 {
00601 if (c == '?')
00602
00603 {
00604 read ();
00605 read ('>');
00606 return;
00607 }
00608 }
00609
00610 else
00611
00612 {
00613 if (c == '/')
00614
00615 {
00616 degenerated = true;
00617 read ();
00618 skip ();
00619 read ('>');
00620 break;
00621 }
00622 if (c == '>' && !xmldecl)
00623
00624 {
00625 read ();
00626 break;
00627 }
00628 }
00629 if (c == -1)
00630 exception (unexpected_eof);
00631 std::string attrName = readName ();
00632 if (attrName.empty ())
00633 exception ("attr name expected");
00634 skip ();
00635 read ('=');
00636 skip ();
00637 int delimiter = read ();
00638 if (delimiter != '\'' && delimiter != '"')
00639
00640 {
00641 if (!relaxed)
00642 exception ("<"
00643 + name + ">: invalid delimiter: " + (char) delimiter);
00644 delimiter = ' ';
00645 }
00646 unsigned int i = (attributeCount++) << 2;
00647
00648
00649 if (attributes.size () <= i + 4)
00650 attributes.resize (i + 4 + RESIZE_BUFFER);
00651 attributes[i++] = "";
00652 attributes[i++] = "";
00653 attributes[i++] = attrName;
00654 int p = txtPos;
00655 pushText (delimiter, true);
00656 attributes[i] = get (p);
00657 txtPos = p;
00658 if (delimiter != ' ')
00659 read ();
00660 }
00661 unsigned int sp = depth++ << 2;
00662
00663
00664 if (elementStack.size () <= sp + 4)
00665 elementStack.resize (sp + 4 + RESIZE_BUFFER);
00666 elementStack[sp + 3] = name;
00667
00668
00669 if (depth >= nspSize)
00670
00671 {
00672 int *bigger = new int[nspSize + 4];
00673 int i = 0;
00674 for (i = 0; i < nspSize; i++)
00675 bigger[i] = nspCounts[i];
00676 for (i = nspSize; i < nspSize + 4; i++)
00677 bigger[i] = 0;
00678 delete [] nspCounts;
00679 nspCounts = bigger;
00680 nspSize += 4;
00681 }
00682 nspCounts[depth] = nspCounts[depth - 1];
00683 for (int i = attributeCount - 1; i > 0; i--)
00684
00685 {
00686 for (int j = 0; j < i; j++)
00687
00688 {
00689 if (getAttributeName (i) == getAttributeName (j))
00690 exception ("Duplicate Attribute: " + getAttributeName (i));
00691 }
00692 }
00693 if (processNsp)
00694 adjustNsp ();
00695
00696 else
00697 Ns = "";
00698 elementStack[sp] = Ns;
00699 elementStack[sp + 1] = prefix;
00700 elementStack[sp + 2] = name;
00701 }
00702
00703
00704
00705
00706 void
00707 XmlPullParser::pushEntity ()
00708 {
00709 read ();
00710 int pos = txtPos;
00711 while (true)
00712
00713 {
00714 int c = read ();
00715 if (c == ';')
00716 break;
00717 if (relaxed && (c == '<' || c == '&' || c <= ' '))
00718
00719 {
00720 if (c != -1)
00721 push (c);
00722 return;
00723 }
00724 if (c == -1)
00725 exception (unexpected_eof);
00726 push (c);
00727 }
00728 std::string code = get (pos);
00729 txtPos = pos;
00730 if (token && type == ENTITY_REF)
00731 name = code;
00732 if (code[0] == '#')
00733
00734 {
00735 int c = (code[1] == 'x' ? XmlUtils::parseInt (code.substr (2),16)
00736 : XmlUtils::parseInt (code.substr (1)));
00737 push (c);
00738 return;
00739 }
00740 std::string result = (std::string) entityMap[code];
00741 unresolved = result == "";
00742 if (unresolved)
00743
00744 {
00745 if (!token)
00746 exception ("unresolved: &" + code + ";");
00747 }
00748
00749 else
00750
00751 {
00752 for (unsigned int i = 0; i < result.length (); i++)
00753 push (result.at (i));
00754 }
00755 }
00756
00757
00758
00759
00760
00761
00762
00763 void
00764 XmlPullParser::pushText (int delimiter, bool resolveEntities)
00765 {
00766 int next = peekbuf (0);
00767 while (next != -1 && next != delimiter)
00768 {
00769 if (delimiter == ' ')
00770 if (next <= ' ' || next == '>')
00771 break;
00772 if (next == '&')
00773
00774 {
00775 if (!resolveEntities)
00776 break;
00777 pushEntity ();
00778 }
00779
00780 else if (next == '\n' && type == START_TAG)
00781
00782 {
00783 read ();
00784 push (' ');
00785 }
00786
00787 else
00788 push (read ());
00789 next = peekbuf (0);
00790 }
00791 }
00792
00793
00794 void
00795 XmlPullParser::read (char c)
00796 {
00797 int a = read ();
00798 std::string sa (1, (char) a), sc (1, c);
00799 if (a != c)
00800 exception ("expected: '" + sc + "' actual: '" + sa + "'");
00801 }
00802
00803
00804 int
00805 XmlPullParser::read ()
00806 {
00807 int result;
00808 if (peekCount == 0)
00809 result = peekbuf (0);
00810
00811 else
00812
00813 {
00814 result = peek[0];
00815 peek[0] = peek[1];
00816 }
00817 peekCount--;
00818 column++;
00819 if (result == '\n')
00820
00821 {
00822 line++;
00823 column = 1;
00824 }
00825 return result;
00826 }
00827
00828
00829
00830 int
00831 XmlPullParser::peekbuf (int pos)
00832 {
00833 while (pos >= peekCount)
00834
00835 {
00836 int nw;
00837 if (srcBuflength <= 1)
00838 nw = reader.get ();
00839
00840 else if (srcPos < srcCount)
00841 nw = srcBuf[srcPos++];
00842
00843 else
00844
00845 {
00846 srcCount = reader.read (srcBuf, srcBuflength).gcount ();
00847 if (srcCount <= 0)
00848 nw = -1;
00849
00850 else
00851 nw = srcBuf[0];
00852 srcPos = 1;
00853 }
00854 if (nw == '\r')
00855
00856 {
00857 wasCR = true;
00858 peek[peekCount++] = '\n';
00859 }
00860
00861 else
00862
00863 {
00864 if (nw == '\n')
00865
00866 {
00867 if (!wasCR)
00868 peek[peekCount++] = '\n';
00869 }
00870
00871 else
00872 peek[peekCount++] = nw;
00873 wasCR = false;
00874 }
00875 }
00876 return peek[pos];
00877 }
00878
00879
00880 std::string XmlPullParser::readName ()
00881 {
00882 int pos = txtPos;
00883 int c = peekbuf (0);
00884 if ((c < 'a' || c > 'z')
00885 && (c < 'A' || c > 'Z') && c != '_' && c != ':' && c < 0x0c0)
00886 exception ("name expected");
00887
00888 do
00889
00890 {
00891 push (read ());
00892 c = peekbuf (0);
00893 }
00894 while ((c >= 'a' && c <= 'z')
00895 || (c >= 'A' && c <= 'Z')
00896 || (c >= '0' && c <= '9')
00897 || c == '_' || c == '-' || c == ':' || c == '.' || c >= 0x0b7);
00898 std::string
00899 result = get (pos);
00900 txtPos = pos;
00901 return result;
00902 }
00903
00904
00905 void
00906 XmlPullParser::skip ()
00907 {
00908 while (true)
00909
00910 {
00911 int c = peekbuf (0);
00912 if (c > ' ' || c == -1)
00913 break;
00914 read ();
00915 }
00916 }
00917
00918
00919
00920 bool XmlPullParser::getFeature (std::string feature)
00921 {
00922 if (FEATURE_PROCESS_NAMESPACES == feature)
00923 return processNsp;
00924
00925 else if (isProp (feature, false, "relaxed"))
00926 return relaxed;
00927
00928 else
00929 return false;
00930 }
00931
00932
00933 std::string XmlPullParser::getInputEncoding ()
00934 {
00935 return encoding;
00936 }
00937
00938
00939 void
00940 XmlPullParser::defineEntityReplacementText (std::string entity, std::string value)
00941 {
00942 if (entityMap.empty ())
00943 exception ("entity replacement text must be defined after setInput!");
00944 entityMap[entity] = value;
00945 }
00946
00947
00948 int
00949 XmlPullParser::getNamespaceCount (int d)
00950 {
00951 if (d > depth)
00952 exception ("IndexOutOfBoundsException");;
00953 return nspCounts[d];
00954 }
00955
00956
00957 std::string XmlPullParser::getNamespacePrefix (int pos)
00958 {
00959 return nspStack[pos << 1];
00960 }
00961
00962
00963 std::string XmlPullParser::getNamespaceUri (int pos)
00964 {
00965 return nspStack[(pos << 1) + 1];
00966 }
00967
00968
00969 std::string XmlPullParser::getNamespace (std::string prefx)
00970 {
00971 if ("xml" == prefx)
00972 return "http://www.w3.org/XML/1998/namespace";
00973 if ("xmlns" == prefx)
00974 return "http://www.w3.org/2000/xmlns/";
00975 for (int i = (getNamespaceCount (depth) << 1) - 2; i >= 0; i -= 2)
00976
00977 {
00978 if (prefx.empty ())
00979
00980 {
00981
00982
00983 if (nspStack[i].empty ())
00984 return nspStack[i + 1];
00985 }
00986
00987 else if (prefx == nspStack[i])
00988 return nspStack[i + 1];
00989 }
00990 return "";
00991 }
00992
00993
00994 int
00995 XmlPullParser::getDepth ()
00996 {
00997 return depth;
00998 }
00999
01000
01001 std::string XmlPullParser::getPositionDescription ()
01002 {
01003 std::ostringstream buf (std::ios::ate);
01004
01005 buf << (type < 11 ? state (type) : "Unknown Event");
01006 buf << " ";
01007 if (type == START_TAG || type == END_TAG)
01008
01009 {
01010 if (degenerated)
01011 buf << "(empty) ";
01012 buf << "<";
01013 if (type == END_TAG)
01014 buf << "/";
01015 if (!prefix.empty ())
01016 buf << "{" << Ns << "}" << prefix << ":";
01017 buf << name;
01018 int
01019 cnt = attributeCount << 2;
01020 for (int i = 0; i < cnt; i += 4)
01021
01022 {
01023 buf << " ";
01024 if (!attributes[i + 1].empty ())
01025 buf << "{" << attributes[i] << "}" << attributes[i + 1] << ":";
01026 buf << attributes[i + 2] << "='" << attributes[i + 3] << "'";
01027 }
01028 buf << ">";
01029 }
01030
01031 else if (type == IGNORABLE_WHITESPACE);
01032
01033 else if (type != TEXT)
01034 buf << getText ();
01035
01036 else if (isWspace)
01037 buf << "(whitespace)";
01038
01039 else
01040
01041 {
01042 std::string
01043 txt = getText ();
01044 if (txt.length () > 16)
01045 txt = txt.substr (0, 16) + "...";
01046 buf << txt;
01047 }
01048 buf << " @" << line << ":" << column;
01049 return buf.str ();
01050 }
01051
01052
01053 bool XmlPullParser::isWhitespace ()
01054 {
01055 if (type != TEXT && type != IGNORABLE_WHITESPACE && type != CDSECT)
01056 exception (illegal_type);
01057 return isWspace;
01058 }
01059
01060
01061 std::string XmlPullParser::getText ()
01062 {
01063 return type < TEXT || (type == ENTITY_REF && unresolved) ? "" : get (0);
01064 }
01065
01066
01067 const char *
01068 XmlPullParser::getTextCharacters (int *poslen)
01069 {
01070 if (type >= TEXT)
01071
01072 {
01073 if (type == ENTITY_REF)
01074
01075 {
01076 poslen[0] = 0;
01077 poslen[1] = name.length ();
01078 return name.c_str ();
01079 }
01080 poslen[0] = 0;
01081 poslen[1] = txtPos;
01082 return txtBuf;
01083 }
01084 poslen[0] = -1;
01085 poslen[1] = -1;
01086 return 0;
01087 }
01088
01089
01090 bool XmlPullParser::isEmptyElementTag ()
01091 {
01092 if (type != START_TAG)
01093 exception (illegal_type);
01094 return degenerated;
01095 }
01096
01097
01098 std::string XmlPullParser::getAttributeNamespace (int index)
01099 {
01100 if (index >= attributeCount)
01101 exception ("IndexOutOfBoundsException()");
01102 return attributes[index << 2];
01103 }
01104
01105
01106 std::string XmlPullParser::getAttributeName (int index)
01107 {
01108 if (index >= attributeCount)
01109 exception ("IndexOutOfBoundsException()");
01110 return attributes[(index << 2) + 2];
01111 }
01112
01113
01114 std::string XmlPullParser::getAttributePrefix (int index)
01115 {
01116 if (index >= attributeCount)
01117 exception ("IndexOutOfBoundsException()");
01118 return attributes[(index << 2) + 1];
01119 }
01120
01121
01122 std::string XmlPullParser::getAttributeValue (int index)
01123 {
01124 if (index >= attributeCount)
01125 exception ("IndexOutOfBoundsException()");
01126 return attributes[(index << 2) + 3];
01127 }
01128
01129
01130 std::string XmlPullParser::getAttributeValue (std::string ns, std::string nam)
01131 {
01132 for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4)
01133
01134 {
01135 if (attributes[i + 2] == nam && (ns.empty () || attributes[i] == ns))
01136 return attributes[i + 3];
01137 }
01138 return "";
01139 }
01140
01141
01142 int
01143 XmlPullParser::next ()
01144 {
01145 txtPos = 0;
01146 isWspace = true;
01147 int minType = 9999;
01148 token = false;
01149
01150 do
01151
01152 {
01153 nextImpl ();
01154 if (type < minType)
01155 minType = type;
01156
01157
01158 }
01159 while (minType > CDSECT
01160 || (minType >= TEXT && peekType () >= TEXT));
01161 type = minType;
01162 if (type > TEXT)
01163 type = TEXT;
01164 return type;
01165 }
01166
01167
01168 int
01169 XmlPullParser::nextToken ()
01170 {
01171 isWspace = true;
01172 txtPos = 0;
01173 token = true;
01174 nextImpl ();
01175 return type;
01176 }
01177
01178
01179
01180
01181 int
01182 XmlPullParser::nextTag ()
01183 {
01184 next ();
01185 if (type == TEXT && isWspace)
01186 next ();
01187 if (type != END_TAG && type != START_TAG && type != END_DOCUMENT)
01188 exception ("unexpected type");
01189 return type;
01190 }
01191
01192
01193 void
01194 XmlPullParser::require (int Type, std::string ns, std::string nam)
01195 {
01196 if (Type != type || (!ns.empty () && ns != getNamespace ())
01197 || (!nam.empty () && nam != getName ()))
01198 exception ("expected: " + state (Type) + " {" + ns + "}" + nam);
01199 }
01200
01201
01202 std::string XmlPullParser::nextText ()
01203 {
01204 if (type != START_TAG)
01205 exception ("precondition: START_TAG");
01206 next ();
01207 std::string
01208 result;
01209 if (type == TEXT)
01210
01211 {
01212 result = getText ();
01213 next ();
01214 }
01215
01216 else
01217 result = "";
01218 if (type != END_TAG)
01219 exception ("END_TAG expected");
01220 return result;
01221 }
01222
01223
01224 void
01225 XmlPullParser::setFeature (std::string feature, bool value)
01226 {
01227 if (FEATURE_PROCESS_NAMESPACES == feature)
01228 processNsp = value;
01229
01230 else if (isProp (feature, false, "relaxed"))
01231 relaxed = value;
01232
01233 else
01234 exception ("unsupported feature: " + feature);
01235 }
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257 void
01258 XmlPullParser::skipSubTree() {
01259 require(START_TAG, "", "");
01260 int level = 1;
01261 while (level > 0) {
01262 int eventType = next();
01263 if (eventType == END_TAG) {
01264 --level;
01265 }
01266 else if (eventType == START_TAG) {
01267 ++level;
01268 }
01269 }
01270 }
01271