1 /**
2 * Phoebe DOM Implementation.
3 *
4 * This is a C++ approximation of the W3C DOM model, which follows
5 * fairly closely the specifications in the various .idl files, copies of
6 * which are provided for reference. Most important is this one:
7 *
8 * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
9 *
10 * Authors:
11 * Bob Jamison
12 *
13 * Copyright (C) 2006-2008 Bob Jamison
14 *
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2.1 of the License, or (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 */
31 #include "xpathtoken.h"
32 #include <stdio.h>
36 namespace org
37 {
38 namespace w3c
39 {
40 namespace dom
41 {
42 namespace xpath
43 {
47 //########################################################################
48 //# X P A T H T O K E N
49 //########################################################################
51 //########################################################################
52 //# X P A T H T O K E N T Y P E S
53 //########################################################################
57 //###########################
58 //# V A L U E S
59 //###########################
61 /**
62 * The following functions are called by a token's execute()
63 * method. These functions are what differentiate one token
64 * from another and give each its personality.
65 */
67 static bool tokStr(Token &tok, Stack &stack)
68 {
69 StackItem item;
70 item.sval = tok.sval;
71 stack.push(item);
72 return true;
73 }
75 static bool tokFloat(Token &tok, Stack &stack)
76 {
77 StackItem item;
78 item.dval = tok.dval;
79 stack.push(item);
80 return true;
81 }
83 static bool tokInt(Token &tok, Stack &stack)
84 {
85 StackItem item;
86 item.ival = tok.ival;
87 stack.push(item);
88 return true;
89 }
91 static bool tokAnd(Token &/*tok*/, Stack &stack)
92 {
93 StackItem item1 = stack.pop();
94 StackItem item2 = stack.pop();
95 item1.ival = item1.ival && item2.ival;
96 stack.push(item1);
97 return true;
98 }
100 static bool tokOr(Token &/*tok*/, Stack &stack)
101 {
102 StackItem item1 = stack.pop();
103 StackItem item2 = stack.pop();
104 item1.ival = item1.ival || item2.ival;
105 stack.push(item1);
106 return true;
107 }
109 static bool tokMod(Token &/*tok*/, Stack &stack)
110 {
111 StackItem item1 = stack.pop();
112 StackItem item2 = stack.pop();
113 item1.dval = fmod(item1.dval, item2.dval);
114 stack.push(item1);
115 return true;
116 }
119 static bool tokDiv(Token &/*tok*/, Stack &stack)
120 {
121 StackItem item1 = stack.pop();
122 StackItem item2 = stack.pop();
123 item1.dval /= item2.dval;
124 stack.push(item1);
125 return true;
126 }
128 static bool tokMul(Token &/*tok*/, Stack &stack)
129 {
130 StackItem item1 = stack.pop();
131 StackItem item2 = stack.pop();
132 item1.dval *= item2.dval;
133 stack.push(item1);
134 return true;
135 }
137 static bool tokPlus(Token &/*tok*/, Stack &stack)
138 {
139 StackItem item1 = stack.pop();
140 StackItem item2 = stack.pop();
141 item1.dval += item2.dval;
142 stack.push(item1);
143 return true;
144 }
146 static bool tokMinus(Token &/*tok*/, Stack &stack)
147 {
148 StackItem item1 = stack.pop();
149 StackItem item2 = stack.pop();
150 item1.dval -= item2.dval;
151 stack.push(item1);
152 return true;
153 }
156 static bool tokNeg(Token &/*tok*/, Stack &stack)
157 {
158 StackItem item = stack.pop();
159 item.dval = -item.dval;
160 item.ival = -item.ival;
161 stack.push(item);
162 return true;
163 }
166 static bool tokEquals(Token &/*tok*/, Stack &stack)
167 {
168 StackItem item1 = stack.pop();
169 StackItem item2 = stack.pop();
170 item1.ival = (item1.dval == item2.dval);
171 stack.push(item1);
172 return true;
173 }
176 static bool tokNotEquals(Token &/*tok*/, Stack &stack)
177 {
178 StackItem item1 = stack.pop();
179 StackItem item2 = stack.pop();
180 item1.ival = (item1.dval != item2.dval);
181 stack.push(item1);
182 return true;
183 }
186 static bool tokLessThan(Token &/*tok*/, Stack &stack)
187 {
188 StackItem item1 = stack.pop();
189 StackItem item2 = stack.pop();
190 item1.ival = (item1.dval < item2.dval);
191 stack.push(item1);
192 return true;
193 }
196 static bool tokLessThanEquals(Token &/*tok*/, Stack &stack)
197 {
198 StackItem item1 = stack.pop();
199 StackItem item2 = stack.pop();
200 item1.ival = (item1.dval <= item2.dval);
201 stack.push(item1);
202 return true;
203 }
206 static bool tokGreaterThanEquals(Token &/*tok*/, Stack &stack)
207 {
208 StackItem item1 = stack.pop();
209 StackItem item2 = stack.pop();
210 item1.ival = (item1.dval >= item2.dval);
211 stack.push(item1);
212 return true;
213 }
216 static bool tokGreaterThan(Token &/*tok*/, Stack &stack)
217 {
218 StackItem item1 = stack.pop();
219 StackItem item2 = stack.pop();
220 item1.ival = (item1.dval > item2.dval);
221 stack.push(item1);
222 return true;
223 }
230 //###########################
231 //# X P A T H I T E M S
232 //###########################
234 static bool tokAbsolute(Token &/*tok*/, Stack &/*stack*/)
235 {
236 return true;
237 }
239 static bool tokRelative(Token &/*tok*/, Stack &/*stack*/)
240 {
241 return true;
242 }
244 static bool tokStep(Token &/*tok*/, Stack &/*stack*/)
245 {
246 return true;
247 }
249 static bool tokNameTest(Token &/*tok*/, Stack &/*stack*/)
250 {
251 return true;
252 }
254 static bool tokExpr(Token &/*tok*/, Stack &/*stack*/)
255 {
256 return true;
257 }
259 static bool tokUnion(Token &/*tok*/, Stack &/*stack*/)
260 {
261 return true;
262 }
267 //###########################
268 //# A X I S
269 //###########################
272 static bool tokAxisAncestorOrSelf(Token &/*tok*/, Stack &/*stack*/)
273 {
274 return true;
275 }
278 static bool tokAxisAncestor(Token &/*tok*/, Stack &/*stack*/)
279 {
280 return true;
281 }
284 static bool tokAxisAttribute(Token &/*tok*/, Stack &/*stack*/)
285 {
286 return true;
287 }
290 static bool tokAxisChild(Token &/*tok*/, Stack &/*stack*/)
291 {
292 return true;
293 }
296 static bool tokAxisDescendantOrSelf(Token &/*tok*/, Stack &/*stack*/)
297 {
298 return true;
299 }
302 static bool tokAxisDescendant(Token &/*tok*/, Stack &/*stack*/)
303 {
304 return true;
305 }
308 static bool tokAxisFollowingSibling(Token &/*tok*/, Stack &/*stack*/)
309 {
310 return true;
311 }
314 static bool tokAxisFollowing(Token &/*tok*/, Stack &/*stack*/)
315 {
316 return true;
317 }
320 static bool tokAxisNamespace(Token &/*tok*/, Stack &/*stack*/)
321 {
322 return true;
323 }
326 static bool tokAxisParent(Token &/*tok*/, Stack &/*stack*/)
327 {
328 return true;
329 }
332 static bool tokAxisPrecedingSibling(Token &/*tok*/, Stack &/*stack*/)
333 {
334 return true;
335 }
338 static bool tokAxisPreceding(Token &/*tok*/, Stack &/*stack*/)
339 {
340 return true;
341 }
344 static bool tokAxisSelf(Token &/*tok*/, Stack &/*stack*/)
345 {
346 return true;
347 }
351 //###########################
352 //# F U N C T I O N S
353 //###########################
356 static bool tokFuncLast(Token &/*tok*/, Stack &/*stack*/)
357 {
358 return true;
359 }
362 static bool tokFuncPosition(Token &/*tok*/, Stack &/*stack*/)
363 {
364 return true;
365 }
368 static bool tokFuncCount(Token &/*tok*/, Stack &/*stack*/)
369 {
370 return true;
371 }
374 static bool tokFuncId(Token &/*tok*/, Stack &/*stack*/)
375 {
376 return true;
377 }
380 static bool tokFuncLocalName(Token &/*tok*/, Stack &/*stack*/)
381 {
382 return true;
383 }
386 static bool tokFuncNamespaceUri(Token &/*tok*/, Stack &/*stack*/)
387 {
388 return true;
389 }
392 static bool tokFuncName(Token &/*tok*/, Stack &/*stack*/)
393 {
394 return true;
395 }
398 static bool tokFuncString(Token &/*tok*/, Stack &/*stack*/)
399 {
400 return true;
401 }
404 static bool tokFuncConcat(Token &/*tok*/, Stack &/*stack*/)
405 {
406 return true;
407 }
410 static bool tokFuncStartsWith(Token &/*tok*/, Stack &/*stack*/)
411 {
412 return true;
413 }
416 static bool tokFuncContains(Token &/*tok*/, Stack &/*stack*/)
417 {
418 return true;
419 }
422 static bool tokFuncSubstringBefore(Token &/*tok*/, Stack &/*stack*/)
423 {
424 return true;
425 }
428 static bool tokFuncSubstringAfter(Token &/*tok*/, Stack &/*stack*/)
429 {
430 return true;
431 }
434 static bool tokFuncSubstring(Token &/*tok*/, Stack &/*stack*/)
435 {
436 return true;
437 }
440 static bool tokFuncStringLength(Token &/*tok*/, Stack &/*stack*/)
441 {
442 return true;
443 }
446 static bool tokFuncNormalizeSpace(Token &/*tok*/, Stack &/*stack*/)
447 {
448 return true;
449 }
452 static bool tokFuncTranslate(Token &/*tok*/, Stack &/*stack*/)
453 {
454 return true;
455 }
458 static bool tokFuncBoolean(Token &/*tok*/, Stack &/*stack*/)
459 {
460 return true;
461 }
464 static bool tokFuncNot(Token &/*tok*/, Stack &/*stack*/)
465 {
466 return true;
467 }
470 static bool tokFuncTrue(Token &/*tok*/, Stack &/*stack*/)
471 {
472 return true;
473 }
476 static bool tokFuncFalse(Token &/*tok*/, Stack &/*stack*/)
477 {
478 return true;
479 }
482 static bool tokFuncLang(Token &/*tok*/, Stack &/*stack*/)
483 {
484 return true;
485 }
488 static bool tokFuncNumber(Token &/*tok*/, Stack &/*stack*/)
489 {
490 return true;
491 }
494 static bool tokFuncSum(Token &/*tok*/, Stack &/*stack*/)
495 {
496 return true;
497 }
500 static bool tokFuncFloor(Token &/*tok*/, Stack &/*stack*/)
501 {
502 return true;
503 }
506 static bool tokFuncCeiling(Token &/*tok*/, Stack &/*stack*/)
507 {
508 return true;
509 }
512 static bool tokFuncRound(Token &/*tok*/, Stack &/*stack*/)
513 {
514 return true;
515 }
519 /**
520 * An entry for the token 'personality' table
521 */
522 typedef struct
523 {
524 int ival;
525 char const *sval;
526 TokenFunc tokenFunc;
527 } TokenTableEntry;
530 /**
531 * The token personality table
532 */
533 static TokenTableEntry tokenTable[] =
534 {
535 //### primitives
536 {
537 Token::TOK_NOP,
538 "nop",
539 NULL
540 },
541 {
542 Token::TOK_STR,
543 "str",
544 tokStr
545 },
546 {
547 Token::TOK_INT,
548 "int",
549 tokInt
550 },
551 {
552 Token::TOK_FLOAT,
553 "float",
554 tokFloat
555 },
557 //### operators
558 {
559 Token::TOK_AND,
560 "and",
561 tokAnd
562 },
563 {
564 Token::TOK_OR,
565 "or",
566 tokOr
567 },
568 {
569 Token::TOK_MOD,
570 "mod",
571 tokMod
572 },
573 {
574 Token::TOK_DIV,
575 "div",
576 tokDiv
577 },
578 {
579 Token::TOK_MUL,
580 "multiply",
581 tokMul
582 },
583 {
584 Token::TOK_DOUBLE_SLASH,
585 "double-slash",
586 NULL
587 },
588 {
589 Token::TOK_SLASH,
590 "slash",
591 NULL
592 },
593 {
594 Token::TOK_PIPE,
595 "pipe",
596 NULL
597 },
598 {
599 Token::TOK_PLUS,
600 "plus",
601 tokPlus
602 },
603 {
604 Token::TOK_MINUS,
605 "minus",
606 tokMinus
607 },
608 {
609 Token::TOK_NEG,
610 "neg",
611 tokNeg
612 },
613 {
614 Token::TOK_EQUALS,
615 "equals",
616 tokEquals
617 },
618 {
619 Token::TOK_NOT_EQUALS,
620 "not-equals",
621 tokNotEquals
622 },
623 {
624 Token::TOK_LESS_THAN_EQUALS,
625 "less-than-equals",
626 tokLessThanEquals
627 },
628 {
629 Token::TOK_LESS_THAN,
630 "less-than",
631 tokLessThan
632 },
633 {
634 Token::TOK_GREATER_THAN_EQUALS,
635 "greater-than-equals",
636 tokGreaterThanEquals
637 },
638 {
639 Token::TOK_GREATER_THAN,
640 "greater-than",
641 tokGreaterThan
642 },
644 //### path types
645 {
646 Token::TOK_ABSOLUTE,
647 "absolute",
648 tokAbsolute
649 },
650 {
651 Token::TOK_RELATIVE,
652 "relative",
653 tokRelative
654 },
655 {
656 Token::TOK_STEP,
657 "step",
658 tokStep
659 },
660 {
661 Token::TOK_NAME_TEST,
662 "name-test",
663 tokNameTest
664 },
665 {
666 Token::TOK_EXPR,
667 "expr",
668 tokExpr
669 },
670 {
671 Token::TOK_UNION,
672 "union",
673 tokUnion
674 },
676 //### axis types
677 {
678 Token::TOK_AXIS_ANCESTOR_OR_SELF,
679 "axis-ancestor-or-self",
680 tokAxisAncestorOrSelf
681 },
682 {
683 Token::TOK_AXIS_ANCESTOR,
684 "axis-ancestor",
685 tokAxisAncestor
686 },
687 {
688 Token::TOK_AXIS_ATTRIBUTE,
689 "axis-attribute",
690 tokAxisAttribute
691 },
692 {
693 Token::TOK_AXIS_CHILD,
694 "axis-child",
695 tokAxisChild
696 },
697 {
698 Token::TOK_AXIS_DESCENDANT_OR_SELF,
699 "axis-descendant-or-self",
700 tokAxisDescendantOrSelf
701 },
702 {
703 Token::TOK_AXIS_DESCENDANT,
704 "axis-descendant",
705 tokAxisDescendant
706 },
707 {
708 Token::TOK_AXIS_FOLLOWING_SIBLING,
709 "axis-following-sibling",
710 tokAxisFollowingSibling
711 },
712 {
713 Token::TOK_AXIS_FOLLOWING,
714 "axis-following",
715 tokAxisFollowing
716 },
717 {
718 Token::TOK_AXIS_NAMESPACE,
719 "axis-namespace",
720 tokAxisNamespace
721 },
722 {
723 Token::TOK_AXIS_PARENT,
724 "axis-parent",
725 tokAxisParent
726 },
727 {
728 Token::TOK_AXIS_PRECEDING_SIBLING,
729 "axis-preceding-sibling",
730 tokAxisPrecedingSibling
731 },
732 {
733 Token::TOK_AXIS_PRECEDING,
734 "axis-preceding",
735 tokAxisPreceding
736 },
737 {
738 Token::TOK_AXIS_SELF,
739 "axis-self",
740 tokAxisSelf
741 },
743 //### function types
744 {
745 Token::TOK_FUNC_LAST,
746 "func-last",
747 tokFuncLast
748 },
749 {
750 Token::TOK_FUNC_POSITION,
751 "func-position",
752 tokFuncPosition
753 },
754 {
755 Token::TOK_FUNC_COUNT,
756 "func-count",
757 tokFuncCount
758 },
759 {
760 Token::TOK_FUNC_ID,
761 "func-id",
762 tokFuncId
763 },
764 {
765 Token::TOK_FUNC_LOCAL_NAME,
766 "func-local-name",
767 tokFuncLocalName
768 },
769 {
770 Token::TOK_FUNC_NAMESPACE_URI,
771 "func-namespace-uri",
772 tokFuncNamespaceUri
773 },
774 {
775 Token::TOK_FUNC_NAME,
776 "func-name",
777 tokFuncName
778 },
779 {
780 Token::TOK_FUNC_STRING,
781 "func-string",
782 tokFuncString
783 },
784 {
785 Token::TOK_FUNC_CONCAT,
786 "func-concat",
787 tokFuncConcat
788 },
789 {
790 Token::TOK_FUNC_STARTS_WITH,
791 "func-starts-with",
792 tokFuncStartsWith
793 },
794 {
795 Token::TOK_FUNC_CONTAINS,
796 "func-contains",
797 tokFuncContains
798 },
799 {
800 Token::TOK_FUNC_SUBSTRING_BEFORE,
801 "func-substring-before",
802 tokFuncSubstringBefore
803 },
804 {
805 Token::TOK_FUNC_SUBSTRING_AFTER,
806 "func-substring-after",
807 tokFuncSubstringAfter
808 },
809 {
810 Token::TOK_FUNC_SUBSTRING,
811 "func-substring",
812 tokFuncSubstring
813 },
814 {
815 Token::TOK_FUNC_STRING_LENGTH,
816 "func-string-length",
817 tokFuncStringLength
818 },
819 {
820 Token::TOK_FUNC_NORMALIZE_SPACE,
821 "func-normalize-space",
822 tokFuncNormalizeSpace
823 },
824 {
825 Token::TOK_FUNC_TRANSLATE,
826 "func-translate",
827 tokFuncTranslate
828 },
829 {
830 Token::TOK_FUNC_BOOLEAN,
831 "func-boolean",
832 tokFuncBoolean
833 },
834 {
835 Token::TOK_FUNC_NOT,
836 "func-not",
837 tokFuncNot
838 },
839 {
840 Token::TOK_FUNC_TRUE,
841 "func-true",
842 tokFuncTrue
843 },
844 {
845 Token::TOK_FUNC_FALSE,
846 "func-false",
847 tokFuncFalse
848 },
849 {
850 Token::TOK_FUNC_LANG,
851 "func-lang",
852 tokFuncLang
853 },
854 {
855 Token::TOK_FUNC_NUMBER,
856 "func-number",
857 tokFuncNumber
858 },
859 {
860 Token::TOK_FUNC_SUM,
861 "func-sum",
862 tokFuncSum
863 },
864 {
865 Token::TOK_FUNC_FLOOR,
866 "func-floor",
867 tokFuncFloor
868 },
869 {
870 Token::TOK_FUNC_CEILING,
871 "func-ceiling",
872 tokFuncCeiling
873 },
874 {
875 Token::TOK_FUNC_ROUND,
876 "func-round",
877 tokFuncRound
878 },
880 { -1,
881 (char *)0,
882 NULL
883 }
884 };
887 /**
888 * Return the string TokenType of this token
889 * (in the .cpp file)
890 */
891 DOMString Token::getTypeString()
892 {
893 DOMString ret = "unknown";
894 for (TokenTableEntry *entry = tokenTable ; entry->sval ; entry++)
895 {
896 if (entry->ival == type)
897 {
898 ret = entry->sval;
899 break;
900 }
901 }
902 return ret;
903 }
906 /**
907 * Create a token of the given type, giving it
908 * the data and personalities it needs
909 */
910 Token Token::create(int type, long ival,
911 double dval, const DOMString &sval)
912 {
913 Token tok(type, ival, dval, sval);
914 for (TokenTableEntry *entry = tokenTable ; entry->sval ; entry++)
915 {
916 if (entry->ival == type)
917 {
918 tok.tokenFunc = entry->tokenFunc;
919 break;
920 }
921 }
923 return tok;
924 }
933 //########################################################################
934 //# X P A T H E X E C U T O R
935 //########################################################################
937 /**
938 *
939 */
940 TokenExecutor::TokenExecutor()
941 {
942 reset();
943 }
946 /**
947 *
948 */
949 TokenExecutor::TokenExecutor(const TokenExecutor &other)
950 {
951 reset();
952 assign(other);
953 }
956 /**
957 *
958 */
959 TokenExecutor::~TokenExecutor()
960 {
961 }
964 /**
965 *
966 */
967 void TokenExecutor::assign(const TokenExecutor &other)
968 {
969 tokenList = other.tokenList;
970 }
973 /**
974 *
975 */
976 void TokenExecutor::reset()
977 {
978 }
983 /**
984 * Execute a list upon a given node. For each Axis encountered,
985 * get the nodes encountered so far, and execute the rest of the
986 * list of tokens upon each of the nodes.
987 */
988 int TokenExecutor::execute(std::vector<Token> &tokens,
989 int position,
990 const NodePtr /*node*/,
991 NodeList &result)
992 {
993 Stack stack(*this);
995 NodeList contextNodes;
997 int length = (int) tokens.size();
999 for ( ; position < length ; position ++)
1000 {
1001 Token tok = tokens[position];
1002 if (tok.isAxis())
1003 {
1004 int pos2 = 0;
1005 //Do rest of tokens with the nodes we have found so far
1006 for (unsigned int i = 0 ; i<contextNodes.getLength() ; i++)
1007 {
1008 NodePtr contextNode = contextNodes.item(i);
1009 pos2 = execute(tokens, position, contextNode, result);
1010 if (pos2 < 0)
1011 {
1012 return -1;
1013 }
1014 }
1015 position = pos2;
1016 }
1017 else
1018 {
1019 if (!tok.execute(stack))
1020 {
1021 return -1;
1022 }
1023 }
1025 }//for
1027 return position;
1028 }
1031 /**
1032 * Execute the tokens in a TokenList upon a given node
1033 */
1034 bool TokenExecutor::execute(TokenList &tokenList,
1035 const NodePtr node,
1036 NodeList &result)
1037 {
1039 NodeList nodelist;
1041 std::vector<Token> &tokens = tokenList.getTokens();
1042 if (execute(tokens, 0, node, nodeList) < 0)
1043 {
1044 //error message
1045 return false;
1046 }
1048 result = nodeList;
1050 return true;
1051 }
1065 } // namespace xpath
1066 } // namespace dom
1067 } // namespace w3c
1068 } // namespace org
1069 //########################################################################
1070 //# E N D O F F I L E
1071 //########################################################################