wsdlpull  1.23
XmlPullParser.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2005,2007 Vivek Krishna
2  * Based on kxml2 by Stefan Haustein, Oberhausen, Rhld., Germany
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to deal
5  * in the Software without restriction, including without limitation the rights
6  * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE. */
20 
21 #include "xmlpull/XmlPullParser.h"
23 #include "xmlpull/XmlUtils.h"
24 //
25 #include <cstring>
26 
27 
28 XmlPullParser::XmlPullParser (std::istream & is)
29  :unexpected_eof ("Unexpected EOF"),
30  illegal_type ("wrong Event Type"),
31  nspStack (16),
32  elementStack (16),
33  attributes (16),
34  reader (is)
35 {
36  initBuf ();
37  commonInit ();
38 }
39 
40 
42  :unexpected_eof ("Unexpected EOF"),
43  illegal_type ("wrong Event Type"),
44  nspStack (16),
45  elementStack (16),
46  attributes (16),
47  reader (std::cin)
48 {
49  initBuf ();
50  commonInit ();
51 }
52 
53 
54 void
55 XmlPullParser::initBuf ()
56 {
57  srcBuf = new char[8192];
58  srcBuflength = 8192;
59  txtBuf = new char[256];
60  txtBufSize = 256;
61  nspCounts = new int[8];
62  nspSize = 8;
63 }
64 
65 
66 //does common initializations
67 void
68 XmlPullParser::commonInit ()
69 {
70  line = 1;
71  column = 0;
72  type = START_DOCUMENT;
73  name = "";
74  Ns = "";
75  degenerated = false;
76  attributeCount = -1;
77  encoding = "";
78  version = "";
79  standalone = false;
80  unresolved = false;
81  LEGACY = 999;
82  XML_DECL = 998;
83  srcPos = 0;
84  srcCount = 0;
85  peekCount = 0;
86  depth = 0;
87  relaxed = false;
88  skipNextTag=false;
89  entityMap["apos"] = "'";
90  entityMap["gt"] = ">";
91  entityMap["lt"] = "<";
92  entityMap["quot"] = "\"";
93  entityMap["amp"] = "&";
94  for (int i = 0; i < nspSize; i++)
95  nspCounts[i] = 0;
96 }
97 
98 
100 {
101  delete [] srcBuf;
102  delete [] txtBuf;
103  delete [] nspCounts;
104 }
105 
106 
107 std::string
108 XmlPullParser::state (int eventType)
109 {
110  switch (eventType)
111  {
112  case 0:
113  return "START_DOCUMENT";
114  case 1:
115  return "END_DOCUMENT";
116  case 2:
117  return "START_TAG";
118  case 3:
119  return "END_TAG";
120  case 4:
121  return "TEXT";
122  case 5:
123  return "CDSECT";
124  case 6:
125  return "ENTITY_REF";
126  case 7:
127  return "IGNORABLE_WHITESPACE";
128  case 8:
129  return "PROCESSING_INSTRUCTION";
130  case 9:
131  return "COMMENT";
132  case 10:
133  return "DOCDECL";
134  default:
135  return "Illegal state";
136  break;
137  }
138  return "";
139 }
140 
141 
142 bool XmlPullParser::isProp (std::string n1, bool prop, std::string n2)
143 {
144  if (n1.find ("http://xmlpull.org/v1/doc/") != 0)
145  return false;
146  if (prop)
147  return (n1.substr (42) == n2);
148  else
149  return (n1.substr (40) == n2);
150 }
151 
152 
153 bool XmlPullParser::adjustNsp ()
154 {
155  bool
156  any = false;
157  for (int i = 0; i < attributeCount << 2; i += 4)
158 
159  {
160  std::string
161  attrName = attributes[i + 2];
162  int
163  cut = attrName.find (":");
164  std::string
165  prefx;
166  // Creating a variable named 'prefix' generates a warning about hiding the member, so I changed it to 'prefx'. -KEC
167  if (cut != -1)
168 
169  {
170  prefx = attrName.substr (0, cut);
171  attrName = attrName.substr (cut + 1);
172  }
173 
174  else if (attrName == "xmlns")
175 
176  {
177  prefx = attrName;
178  attrName = "";
179  }
180 
181  else
182  continue;
183  if (prefx != "xmlns")
184  {
185  any = true;
186  }
187  else
188  {
189  unsigned int j = (nspCounts[depth]++) << 1;
190 
191  //nspStack = ensureCapacity(nspStack, j + 2);
192  if (nspStack.size () <= j + 2)
193  nspStack.resize (j + 2 + RESIZE_BUFFER);
194  nspStack[j] = attrName;
195  nspStack[j + 1] = attributes[i + 3];
196  if (!attrName.empty () && attributes[i + 3] == "")
197  exception ("illegal empty namespace");
198 
199  //vivek,array copy??
200  int to = ((--attributeCount) << 2) - i;
201  for (int p = 1; p <= to; p++)
202  attributes[i + p - 1] = attributes[i + 4 + p - 1];
203  i -= 4;
204  }
205  }
206  if (any)
207 
208  {
209  for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4)
210 
211  {
212  std::string
213  attrName = attributes[i + 2];
214  int
215  cut = attrName.find (":");
216  if (cut == 0 && !relaxed)
217  exception ("illegal attribute name: " + attrName);
218 
219  else if (cut != -1)
220 
221  {
222  std::string
223  attrPrefix = attrName.substr (0, cut);
224  attrName = attrName.substr (cut + 1);
225  std::string
226  attrNs = getNamespace (attrPrefix);
227  if (attrNs.empty () && !relaxed)
228  exception ("Undefined Prefix: " + attrPrefix + " in ");
229  attributes[i] = attrNs;
230  attributes[i + 1] = attrPrefix;
231  attributes[i + 2] = attrName;
232  if (!relaxed)
233 
234  {
235  for (int j = (attributeCount << 2) - 4; j > i; j -= 4)
236  if (attrName == attributes[j + 2]
237  && attrNs == attributes[j])
238  exception ("Duplicate Attribute: {"
239  + attrNs + "}" + attrName);
240  }
241  }
242  }
243  }
244  int cut = name.find (":");
245  if (cut == 0 && !relaxed)
246  exception ("illegal tag name: " + name);
247 
248  else if (cut != -1)
249  {
250  prefix = name.substr (0, cut);
251  name = name.substr (cut + 1);
252  }
253  Ns = getNamespace (prefix);
254  if (Ns.empty ())
255 
256  {
257  if (!prefix.empty () && !relaxed)
258  exception ("undefined prefix: " + prefix);
259  Ns = NO_NAMESPACE;
260  }
261  return any;
262 }
263 
264 
265 void
266 XmlPullParser::exception (std::string desc)
267 {
268  XmlPullParserException e (desc, state (type), line, column);
269  throw e;
270 }
271 
272 
276 void
277 XmlPullParser::nextImpl ()
278 {
279  if (type == END_TAG)
280  depth--;
281  while (true)
282  {
283  attributeCount = -1;
284  if (degenerated)
285 
286  {
287  degenerated = false;
288  type = END_TAG;
289  return;
290  }
291  prefix = "";
292  name = "";
293  Ns = "";
294  text = "";
295  type = peekType ();
296  switch (type)
297  {
298  case ENTITY_REF:
299  pushEntity ();
300  return;
301  case START_TAG:
302  parseStartTag (false);
303  return;
304  case END_TAG:
305  parseEndTag ();
306  return;
307  case END_DOCUMENT:
308  return;
309  case TEXT:
310  pushText ('<', !token);
311  if (depth == 0)
312 
313  {
314  if (isWspace)
315  type = IGNORABLE_WHITESPACE;
316 
317  // make exception switchable for instances.chg... !!!!
318  // else
319  // exception ("text '"+getText ()+"' not allowed outside root element");
320  }
321  return;
322  default:
323  type = parseLegacy (token);
324  if (type != XML_DECL)
325  return;
326  }
327  }
328 }
329 
330 
331 int
332 XmlPullParser::parseLegacy (bool bpush)
333 {
334  std::string req = "";
335  int term;
336  int result;
337  int prev = 0;
338  read (); // <
339  int c = read ();
340  if (c == '?')
341 
342  {
343  if ((peekbuf (0) == 'x' || peekbuf (0) == 'X')
344  && (peekbuf (1) == 'm' || peekbuf (1) == 'M'))
345 
346  {
347  if (bpush)
348 
349  {
350  push (peekbuf (0));
351  push (peekbuf (1));
352  }
353  read ();
354  read ();
355  if ((peekbuf (0) == 'l' || peekbuf (0) == 'L')
356  && peekbuf (1) <= ' ')
357 
358  {
359  if (line != 1 || column > 4)
360  exception ("PI must not start with xml");
361  parseStartTag (true);
362  if (attributeCount < 1 || "version" != attributes[2])
363  exception ("version expected");
364  version = attributes[3];
365  int pos = 1;
366  if (pos < attributeCount && "encoding" == attributes[2 + 4])
367 
368  {
369  encoding = attributes[3 + 4];
370  pos++;
371  }
372  if (pos < attributeCount
373  && "standalone" == attributes[4 * pos + 2])
374 
375  {
376  std::string st = attributes[3 + 4 * pos];
377  if ("yes" == st)
378  standalone = true;
379 
380  else if ("no" == st)
381  standalone = false;
382 
383  else
384  exception ("illegal standalone value: " + st);
385  pos++;
386  }
387  if (pos != attributeCount)
388  exception ("illegal xmldecl");
389  isWspace = true;
390  txtPos = 0;
391  return XML_DECL;
392  }
393  }
394 
395  /* int c0 = read ();
396  int c1 = read ();
397  int */
398  term = '?';
399  result = PROCESSING_INSTRUCTION;
400  }
401 
402  else if (c == '!')
403 
404  {
405  if (peekbuf (0) == '-')
406 
407  {
408  result = COMMENT;
409  req = "--";
410  term = '-';
411  }
412 
413  else if (peekbuf (0) == '[')
414 
415  {
416  result = CDSECT;
417  req = "[CDATA[";
418  term = ']';
419  bpush = true;
420  }
421 
422  else
423 
424  {
425  result = DOCDECL;
426  req = "DOCTYPE";
427  term = -1;
428  }
429  }
430 
431  else
432 
433  {
434  exception ("illegal: <" + c);
435  return -1;
436  }
437  for (unsigned int i = 0; i < req.length (); i++)
438  read (req.at (i));
439  if (result == DOCDECL)
440  parseDoctype (bpush);
441 
442  else
443 
444  {
445  while (true)
446 
447  {
448  c = read ();
449  if (c == -1)
450  exception (unexpected_eof);
451  if (bpush)
452  push (c);
453  if ((term == '?' || c == term)
454  && peekbuf (0) == term && peekbuf (1) == '>')
455  break;
456  prev = c;
457  }
458  if (term == '-' && prev == '-' && !relaxed)
459  exception ("illegal comment delimiter: --->");
460  read ();
461  read ();
462  if (bpush && term != '?')
463  txtPos--;
464  }
465  return result;
466 }
467 
468 
470 void
471 XmlPullParser::parseDoctype (bool bpush)
472 {
473  int nesting = 1;
474  bool quoted = false;
475 
476  // read();
477  while (true)
478 
479  {
480  int i = read ();
481  switch (i)
482 
483  {
484  case -1:
485  exception (unexpected_eof);
486  case '\'':
487  quoted = !quoted;
488  break;
489  case '<':
490  if (!quoted)
491  nesting++;
492  break;
493  case '>':
494  if (!quoted)
495 
496  {
497  if ((--nesting) == 0)
498  return;
499  }
500  break;
501  }
502  if (bpush)
503  push (i);
504  }
505 }
506 
507 
508 /* precondition: &lt;/ consumed */
509 void
510 XmlPullParser::parseEndTag ()
511 {
512  read (); // '<'
513  read (); // '/'
514  name = readName ();
515  skip ();
516  read ('>');
517  int sp = (depth - 1) << 2;
518  if (!relaxed)
519 
520  {
521  if (depth == 0)
522  exception ("element stack empty");
523  if (name != elementStack[sp + 3])
524  exception ("expected: " + elementStack[sp + 3]);
525  }
526 
527  else if (depth == 0 || name != elementStack[sp + 3])
528  return;
529  Ns = elementStack[sp];
530  prefix = elementStack[sp + 1];
531  name = elementStack[sp + 2];
532 }
533 
534 
535 int
536 XmlPullParser::peekType ()
537 {
538  switch (peekbuf (0))
539 
540  {
541  case -1:
542  return END_DOCUMENT;
543  case '&':
544  return ENTITY_REF;
545  case '<':
546  switch (peekbuf (1))
547 
548  {
549  case '/':
550  return END_TAG;
551  case '?':
552  case '!':
553  return LEGACY;
554  default:
555  return START_TAG;
556  }
557  default:
558  return TEXT;
559  }
560 }
561 
562 
563 std::string XmlPullParser::get (int pos)
564 {
565  std::string
566  tmp (txtBuf);
567  return tmp.substr (pos, txtPos - pos);
568 }
569 
570 
571 void
572 XmlPullParser::push (int c)
573 {
574  isWspace &= c <= ' ';
575  if (txtPos >= txtBufSize - 1)
576 
577  {
578  char *bigger = new char[txtBufSize = txtPos * 4 / 3 + 4];
579  memcpy (bigger, txtBuf, txtPos);
580  delete[] txtBuf;
581  txtBuf = bigger;
582  }
583  txtBuf[txtPos++] = (char) c;
584  txtBuf[txtPos] = 0;
585 }
586 
587 
589 void
590 XmlPullParser::parseStartTag (bool xmldecl)
591 {
592  if (!xmldecl)
593  read ();
594  name = readName ();
595  attributeCount = 0;
596  while (true)
597 
598  {
599  skip ();
600  int c = peekbuf (0);
601  if (xmldecl)
602 
603  {
604  if (c == '?')
605 
606  {
607  read ();
608  read ('>');
609  return;
610  }
611  }
612 
613  else
614 
615  {
616  if (c == '/')
617 
618  {
619  degenerated = true;
620  read ();
621  skip ();
622  read ('>');
623  break;
624  }
625  if (c == '>' && !xmldecl)
626 
627  {
628  read ();
629  break;
630  }
631  }
632  if (c == -1)
633  exception (unexpected_eof);
634  std::string attrName = readName ();
635  if (attrName.empty ())
636  exception ("attr name expected");
637  skip ();
638  read ('=');
639  skip ();
640  int delimiter = read ();
641  if (delimiter != '\'' && delimiter != '"')
642 
643  {
644  if (!relaxed)
645  exception ("<"
646  + name + ">: invalid delimiter: " + (char) delimiter);
647  delimiter = ' ';
648  }
649  unsigned int i = (attributeCount++) << 2;
650 
651  //attributes = ensureCapacity(attributes, i + 4);
652  if (attributes.size () <= i + 4)
653  attributes.resize (i + 4 + RESIZE_BUFFER);
654  attributes[i++] = "";
655  attributes[i++] = "";
656  attributes[i++] = attrName;
657  int p = txtPos;
658  pushText (delimiter, true);
659  attributes[i] = get (p);
660  txtPos = p;
661  if (delimiter != ' ')
662  read (); // skip endquote
663  }
664  unsigned int sp = depth++ << 2;
665 
666  //elementStack = ensureCapacity(elementStack, sp + 4,elementStackSize);
667  if (elementStack.size () <= sp + 4)
668  elementStack.resize (sp + 4 + RESIZE_BUFFER);
669  elementStack[sp + 3] = name;
670 
671  /* vivek ,avoided the increment array logic..fix later*/
672  if (depth >= nspSize)
673 
674  {
675  int *bigger = new int[nspSize + 4];
676  int i = 0;
677  for (i = 0; i < nspSize; i++)
678  bigger[i] = nspCounts[i];
679  for (i = nspSize; i < nspSize + 4; i++)
680  bigger[i] = 0;
681  delete [] nspCounts;
682  nspCounts = bigger;
683  nspSize += 4;
684  }
685  nspCounts[depth] = nspCounts[depth - 1];
686  for (int i = attributeCount - 1; i > 0; i--)
687 
688  {
689  for (int j = 0; j < i; j++)
690 
691  {
692  if (getAttributeName (i) == getAttributeName (j))
693  exception ("Duplicate Attribute: " + getAttributeName (i));
694  }
695  }
696  if (processNsp)
697  adjustNsp ();
698 
699  else
700  Ns = "";
701  elementStack[sp] = Ns;
702  elementStack[sp + 1] = prefix;
703  elementStack[sp + 2] = name;
704 }
705 
706 
709 void
710 XmlPullParser::pushEntity ()
711 {
712  read (); // &
713  int pos = txtPos;
714  while (true)
715 
716  {
717  int c = read ();
718  if (c == ';')
719  break;
720  if (relaxed && (c == '<' || c == '&' || c <= ' '))
721 
722  {
723  if (c != -1)
724  push (c);
725  return;
726  }
727  if (c == -1)
728  exception (unexpected_eof);
729  push (c);
730  }
731  std::string code = get (pos);
732  txtPos = pos;
733  if (token && type == ENTITY_REF)
734  name = code;
735  if (code[0] == '#')
736 
737  {
738  int c = (code[1] == 'x' ? XmlUtils::parseInt (code.substr (2),16)
739  : XmlUtils::parseInt (code.substr (1)));
740  push (c);
741  return;
742  }
743  std::string result = (std::string) entityMap[code];
744  unresolved = result == "";
745  if (unresolved)
746 
747  {
748  if (!token)
749  exception ("unresolved: &" + code + ";");
750  }
751 
752  else
753 
754  {
755  for (unsigned int i = 0; i < result.length (); i++)
756  push (result.at (i));
757  }
758 }
759 
760 
766 void
767 XmlPullParser::pushText (int delimiter, bool resolveEntities)
768 {
769  int next = peekbuf (0);
770  while (next != -1 && next != delimiter) // covers eof, '<', '"'
771  {
772  if (delimiter == ' ')
773  if (next <= ' ' || next == '>')
774  break;
775  if (next == '&')
776 
777  {
778  if (!resolveEntities)
779  break;
780  pushEntity ();
781  }
782 
783  else if (next == '\n' && type == START_TAG)
784 
785  {
786  read ();
787  push (' ');
788  }
789 
790  else
791  push (read ());
792  next = peekbuf (0);
793  }
794 }
795 
796 
797 void
798 XmlPullParser::read (char c)
799 {
800  int a = read ();
801  std::string sa (1, (char) a), sc (1, c);
802  if (a != c)
803  exception ("expected: '" + sc + "' actual: '" + sa + "'");
804 }
805 
806 
807 int
808 XmlPullParser::read ()
809 {
810  int result;
811  if (peekCount == 0)
812  result = peekbuf (0);
813 
814  else
815 
816  {
817  result = peek[0];
818  peek[0] = peek[1];
819  }
820  peekCount--;
821  column++;
822  if (result == '\n')
823 
824  {
825  line++;
826  column = 1;
827  }
828  return result;
829 }
830 
831 
833 int
834 XmlPullParser::peekbuf (int pos)
835 {
836  while (pos >= peekCount)
837 
838  {
839  int nw;
840  if (srcBuflength <= 1)
841  nw = reader.get ();
842 
843  else if (srcPos < srcCount)
844  nw = srcBuf[srcPos++];
845 
846  else
847 
848  {
849  srcCount = reader.read (srcBuf, srcBuflength).gcount ();
850  if (srcCount <= 0)
851  nw = -1;
852 
853  else
854  nw = srcBuf[0];
855  srcPos = 1;
856  }
857  if (nw == '\r')
858 
859  {
860  wasCR = true;
861  peek[peekCount++] = '\n';
862  }
863 
864  else
865 
866  {
867  if (nw == '\n')
868 
869  {
870  if (!wasCR)
871  peek[peekCount++] = '\n';
872  }
873 
874  else
875  peek[peekCount++] = nw;
876  wasCR = false;
877  }
878  }
879  return peek[pos];
880 }
881 
882 
883 std::string XmlPullParser::readName ()
884 {
885  int pos = txtPos;
886  int c = peekbuf (0);
887  if ((c < 'a' || c > 'z')
888  && (c < 'A' || c > 'Z') && c != '_' && c != ':' && c < 0x0c0)
889  exception ("name expected");
890 
891  do
892 
893  {
894  push (read ());
895  c = peekbuf (0);
896  }
897  while ((c >= 'a' && c <= 'z')
898  || (c >= 'A' && c <= 'Z')
899  || (c >= '0' && c <= '9')
900  || c == '_' || c == '-' || c == ':' || c == '.' || c >= 0x0b7);
901  std::string
902  result = get (pos);
903  txtPos = pos;
904  return result;
905 }
906 
907 
908 void
909 XmlPullParser::skip ()
910 {
911  while (true)
912 
913  {
914  int c = peekbuf (0);
915  if (c > ' ' || c == -1)
916  break;
917  read ();
918  }
919 }
920 
921 
922 //--------------- public part starts here... ---------------
923 bool XmlPullParser::getFeature (std::string feature)
924 {
925  if (FEATURE_PROCESS_NAMESPACES == feature)
926  return processNsp;
927 
928  else if (isProp (feature, false, "relaxed"))
929  return relaxed;
930 
931  else
932  return false;
933 }
934 
935 
937 {
938  return encoding;
939 }
940 
941 
942 void
943 XmlPullParser::defineEntityReplacementText (std::string entity, std::string value)
944 {
945  if (entityMap.empty ())
946  exception ("entity replacement text must be defined after setInput!");
947  entityMap[entity] = value;
948 }
949 
950 
951 int
953 {
954  if (d > depth)
955  exception ("IndexOutOfBoundsException");;
956  return nspCounts[d];
957 }
958 
959 
961 {
962  return nspStack[pos << 1];
963 }
964 
965 
966 std::string XmlPullParser::getNamespaceUri (int pos)
967 {
968  return nspStack[(pos << 1) + 1];
969 }
970 
971 
972 std::string XmlPullParser::getNamespace (std::string prefx)
973 {
974  if ("xml" == prefx)
975  return "http://www.w3.org/XML/1998/namespace";
976  if ("xmlns" == prefx)
977  return "http://www.w3.org/2000/xmlns/";
978  for (int i = (getNamespaceCount (depth) << 1) - 2; i >= 0; i -= 2)
979 
980  {
981  if (prefx.empty ())
982 
983  {
984 
985  //cout<<nspStack[i]<<nspStack[i+1]<<endl;
986  if (nspStack[i].empty ())
987  return nspStack[i + 1];
988  }
989 
990  else if (prefx == nspStack[i])
991  return nspStack[i + 1];
992  }
993  return "";
994 }
995 
996 
997 int
999 {
1000  return depth;
1001 }
1002 
1003 
1004 std::string
1006 {
1007  std::ostringstream buf (std::ios::ate);
1008  //vivek,replace 11 by the number of event types
1009  buf << (type < 11 ? state (type) : "Unknown Event");
1010  buf << " ";
1011  if (type == START_TAG || type == END_TAG)
1012 
1013  {
1014  if (degenerated)
1015  buf << "(empty) ";
1016  buf << "<";
1017  if (type == END_TAG)
1018  buf << "/";
1019  if (!prefix.empty ())
1020  buf << "{" << Ns << "}" << prefix << ":";
1021  buf << name;
1022  int
1023  cnt = attributeCount << 2;
1024  for (int i = 0; i < cnt; i += 4)
1025 
1026  {
1027  buf << " ";
1028  if (!attributes[i + 1].empty ())
1029  buf << "{" << attributes[i] << "}" << attributes[i + 1] << ":";
1030  buf << attributes[i + 2] << "='" << attributes[i + 3] << "'";
1031  }
1032  buf << ">";
1033  }
1034 
1035  else if (type == IGNORABLE_WHITESPACE);
1036 
1037  else if (type != TEXT)
1038  buf << getText ();
1039 
1040  else if (isWspace)
1041  buf << "(whitespace)";
1042 
1043  else
1044 
1045  {
1046  std::string
1047  txt = getText ();
1048  if (txt.length () > 16)
1049  txt = txt.substr (0, 16) + "...";
1050  buf << txt;
1051  }
1052  buf << " @" << line << ":" << column;
1053  return buf.str (); //replace buf with an ostream
1054 }
1055 
1056 
1058 {
1059  if (type != TEXT && type != IGNORABLE_WHITESPACE && type != CDSECT)
1060  exception (illegal_type);
1061  return isWspace;
1062 }
1063 
1064 
1066 {
1067  return type < TEXT || (type == ENTITY_REF && unresolved) ? "" : get (0);
1068 }
1069 
1070 
1071 const char *
1073 {
1074  if (type >= TEXT)
1075 
1076  {
1077  if (type == ENTITY_REF)
1078 
1079  {
1080  poslen[0] = 0;
1081  poslen[1] = name.length ();
1082  return name.c_str (); //return name.toCharArray();
1083  }
1084  poslen[0] = 0;
1085  poslen[1] = txtPos;
1086  return txtBuf;
1087  }
1088  poslen[0] = -1;
1089  poslen[1] = -1;
1090  return 0;
1091 }
1092 
1093 
1095 {
1096  if (type != START_TAG)
1097  exception (illegal_type);
1098  return degenerated;
1099 }
1100 
1101 
1103 {
1104  if (index >= attributeCount)
1105  exception ("IndexOutOfBoundsException()");
1106  return attributes[index << 2];
1107 }
1108 
1109 
1110 std::string XmlPullParser::getAttributeName (int index)
1111 {
1112  if (index >= attributeCount)
1113  exception ("IndexOutOfBoundsException()");
1114  return attributes[(index << 2) + 2];
1115 }
1116 
1117 
1118 std::string XmlPullParser::getAttributePrefix (int index)
1119 {
1120  if (index >= attributeCount)
1121  exception ("IndexOutOfBoundsException()");
1122  return attributes[(index << 2) + 1];
1123 }
1124 
1125 
1126 std::string XmlPullParser::getAttributeValue (int index)
1127 {
1128  if (index >= attributeCount)
1129  exception ("IndexOutOfBoundsException()");
1130  return attributes[(index << 2) + 3];
1131 }
1132 
1133 
1134 std::string XmlPullParser::getAttributeValue (std::string ns, std::string nam)
1135 {
1136  for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4)
1137 
1138  {
1139  if (attributes[i + 2] == nam && (ns.empty () || attributes[i] == ns))
1140  return attributes[i + 3];
1141  }
1142  return "";
1143 }
1144 
1145 
1146 int
1148 {
1149  txtPos = 0;
1150  isWspace = true;
1151  int minType = 9999;
1152  token = false;
1153 
1154  do
1155 
1156  {
1157  nextImpl ();
1158  if (type < minType)
1159  minType = type;
1160 
1161 // if (curr <= TEXT) type = curr;
1162  }
1163  while (minType > CDSECT // ignorable
1164  || (minType >= TEXT && peekType () >= TEXT));
1165  type = minType;
1166  if (type > TEXT)
1167  type = TEXT;
1168  return type;
1169 }
1170 
1171 
1172 int
1174 {
1175  isWspace = true;
1176  txtPos = 0;
1177  token = true;
1178  nextImpl ();
1179  return type;
1180 }
1181 
1182 void
1184 {
1185  skipNextTag=true;
1186 }
1187 
1188 //----------------------------------------------------------------------
1189 // utility methods to make XML parsing easier ...
1190 int
1192 {
1193  if(skipNextTag){
1194  skipNextTag = false;
1195  return type;
1196  }
1197  next ();
1198  if (type == TEXT && isWspace)
1199  next ();
1200  if (type != END_TAG && type != START_TAG && type != END_DOCUMENT)
1201  exception ("unexpected type");
1202  return type;
1203 }
1204 
1205 
1206 void
1207 XmlPullParser::require (int Type, std::string ns, std::string nam)
1208 {
1209  if (Type != type || (!ns.empty () && ns != getNamespace ())
1210  || (!nam.empty () && nam != getName ()))
1211  exception ("expected: " + state (Type) + " {" + ns + "}" + nam);
1212 }
1213 
1214 
1216 {
1217  if (type != START_TAG)
1218  exception ("precondition: START_TAG");
1219  next ();
1220  std::string
1221  result;
1222  if (type == TEXT)
1223 
1224  {
1225  result = getText ();
1226  next ();
1227  }
1228 
1229  else
1230  result = "";
1231  if (type != END_TAG)
1232  exception ("END_TAG expected");
1233  return result;
1234 }
1235 
1236 
1237 void
1238 XmlPullParser::setFeature (std::string feature, bool value)
1239 {
1240  if (FEATURE_PROCESS_NAMESPACES == feature)
1241  processNsp = value;
1242 
1243  else if (isProp (feature, false, "relaxed"))
1244  relaxed = value;
1245 
1246  else
1247  exception ("unsupported feature: " + feature);
1248 }
1249 
1250 /*
1251 void
1252 XmlPullParser::setProperty(std::string property, std::string value)
1253 {
1254  if(isProp(property, true, "location"))
1255  {
1256  location = value;
1257  }
1258  else
1259  exception ("unsupported property: " + property);
1260 }
1261 */
1262 
1268 // Implementation copied from Alek's mail...
1269 
1270 void
1272  require(START_TAG, "", "");
1273  int level = 1;
1274  while (level > 0) {
1275  int eventType = next();
1276  if (eventType == END_TAG) {
1277  --level;
1278  }
1279  else if (eventType == START_TAG) {
1280  ++level;
1281  }
1282  }
1283 }
1284 
const int RESIZE_BUFFER
Definition: XmlPullParser.h:36
#define FEATURE_PROCESS_NAMESPACES
Definition: XmlPullParser.h:40
#define NO_NAMESPACE
Definition: XmlPullParser.h:44
std::string getNamespace()
Definition: XmlPullParser.h:75
std::string nextText()
const char * getTextCharacters(int *poslen)
bool getFeature(std::string feature)
void require(int type, std::string ns, std::string name)
std::string getName()
Definition: XmlPullParser.h:79
std::string getInputEncoding()
std::string getAttributeValue(int index)
std::string getPositionDescription()
std::string getText()
std::string getNamespaceUri(int pos)
std::string getAttributeNamespace(int index)
std::string getAttributePrefix(int index)
int getNamespaceCount(int depth)
bool isEmptyElementTag()
std::string getAttributeName(int index)
void defineEntityReplacementText(std::string entity, std::string value)
std::string getNamespacePrefix(int pos)
void setFeature(std::string feature, bool value)
Type
Definition: Schema.h:60
int parseInt(std::string s, int radix=10)
Definition: XmlUtils.cpp:57