src/xmlpull/XmlPullParser.cpp

00001 /* Copyright (c) 2005,2007 Vivek Krishna
00002  *  Based on kxml2 by Stefan Haustein, Oberhausen, Rhld., Germany
00003  *  Permission is hereby granted, free of charge, to any person obtaining a copy
00004  * of this software and associated documentation files (the "Software"), to deal
00005  * in the Software without restriction, including without limitation the rights
00006  * to use, copy, modify, merge, publish, distribute, sublicense, and/or
00007  * sell copies of the Software, and to permit persons to whom the Software is
00008  * furnished to do so, subject to the following conditions:
00009  *
00010  * The  above copyright notice and this permission notice shall be included in
00011  * all copies or substantial portions of the Software.
00012  *
00013  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00014  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00015  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00016  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00017  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00018  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
00019  * IN THE SOFTWARE. */
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 //does common initializations
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       // Creating a variable named 'prefix' generates a warning about hiding the member, so I changed it to 'prefx'. -KEC
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           //nspStack = ensureCapacity(nspStack, j + 2);
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           //vivek,array copy??
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  * common base for next and nextToken. Clears the state, except from
00272  * txtPos and whitespace. Does not set the type variable */
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               // make exception switchable for instances.chg... !!!!
00315               //      else
00316               //    exception ("text '"+getText ()+"' not allowed outside root element");
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       /*            int c0 = read ();
00393                     int c1 = read ();
00394                     int */
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 /** precondition: &lt! consumed */
00467 void
00468 XmlPullParser::parseDoctype (bool bpush)
00469 {
00470   int nesting = 1;
00471   bool quoted = false;
00472 
00473   // read();
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 /* precondition: &lt;/ consumed */
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 /** Sets name and attributes */
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       //attributes = ensureCapacity(attributes, i + 4);
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 ();                              // skip endquote
00660     }
00661   unsigned  int sp = depth++ << 2;
00662 
00663   //elementStack = ensureCapacity(elementStack, sp + 4,elementStackSize);
00664   if (elementStack.size () <= sp + 4)
00665     elementStack.resize (sp + 4 + RESIZE_BUFFER);
00666   elementStack[sp + 3] = name;
00667 
00668   /*    vivek ,avoided the increment array logic..fix later*/
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 /** result: isWspace; if the setName parameter is set,
00705 the name of the entity is stored in "name" */
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 /** types:
00759 '<': parse to any token (for nextToken ())
00760 '"': parse to quote
00761 ' ': parse to whitespace or '>'
00762 */
00763 void
00764 XmlPullParser::pushText (int delimiter, bool resolveEntities)
00765 {
00766   int next = peekbuf (0);
00767   while (next != -1 && next != delimiter)       // covers eof, '<', '"'
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 /** Does never read more than needed */
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 //--------------- public part starts here... ---------------
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           //cout<<nspStack[i]<<nspStack[i+1]<<endl;
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   //vivek,replace 11 by the number of event types
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 ();                            //replace buf with an ostream
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 ();                 //return name.toCharArray();
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 //          if (curr <= TEXT) type = curr;
01158     }
01159     while (minType > CDSECT                       // ignorable
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 // utility methods to make XML parsing easier ...
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 void
01239 XmlPullParser::setProperty(std::string property,  std::string value)
01240 {
01241   if(isProp(property, true, "location"))
01242     {
01243       location = value;
01244     }
01245   else
01246   exception ("unsupported property: " + property);
01247 }
01248 */
01249 
01250 /**
01251  * Skip sub tree that is currently parser positioned on.
01252  * <br>NOTE: parser must be on START_TAG and when funtion returns
01253  * parser will be positioned on corresponding END_TAG. 
01254  */
01255 //      Implementation copied from Alek's mail... 
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 

Generated on Sun Nov 26 03:04:44 2006 for wsdlpull by  doxygen 1.4.6