Code

Make curvature work again by fixing a minor omission
[inkscape.git] / src / dom / xpathtoken.cpp
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)
102     StackItem item1 = stack.pop();
103     StackItem item2 = stack.pop();
104     item1.ival = item1.ival || item2.ival;
105     stack.push(item1);
106     return true;
109 static bool tokMod(Token &/*tok*/, Stack &stack)
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;
119 static bool tokDiv(Token &/*tok*/, Stack &stack)
121     StackItem item1 = stack.pop();
122     StackItem item2 = stack.pop();
123     item1.dval /= item2.dval;
124     stack.push(item1);
125     return true;
128 static bool tokMul(Token &/*tok*/, Stack &stack)
130     StackItem item1 = stack.pop();
131     StackItem item2 = stack.pop();
132     item1.dval *= item2.dval;
133     stack.push(item1);
134     return true;
137 static bool tokPlus(Token &/*tok*/, Stack &stack)
139     StackItem item1 = stack.pop();
140     StackItem item2 = stack.pop();
141     item1.dval += item2.dval;
142     stack.push(item1);
143     return true;
146 static bool tokMinus(Token &/*tok*/, Stack &stack)
148     StackItem item1 = stack.pop();
149     StackItem item2 = stack.pop();
150     item1.dval -= item2.dval;
151     stack.push(item1);
152     return true;
156 static bool tokNeg(Token &/*tok*/, Stack &stack)
158     StackItem item = stack.pop();
159     item.dval = -item.dval;
160     item.ival = -item.ival;
161     stack.push(item);
162     return true;
166 static bool tokEquals(Token &/*tok*/, Stack &stack)
168     StackItem item1 = stack.pop();
169     StackItem item2 = stack.pop();
170     item1.ival = (item1.dval == item2.dval);
171     stack.push(item1);
172     return true;
176 static bool tokNotEquals(Token &/*tok*/, Stack &stack)
178     StackItem item1 = stack.pop();
179     StackItem item2 = stack.pop();
180     item1.ival = (item1.dval != item2.dval);
181     stack.push(item1);
182     return true;
186 static bool tokLessThan(Token &/*tok*/, Stack &stack)
188     StackItem item1 = stack.pop();
189     StackItem item2 = stack.pop();
190     item1.ival = (item1.dval < item2.dval);
191     stack.push(item1);
192     return true;
196 static bool tokLessThanEquals(Token &/*tok*/, Stack &stack)
198     StackItem item1 = stack.pop();
199     StackItem item2 = stack.pop();
200     item1.ival = (item1.dval <= item2.dval);
201     stack.push(item1);
202     return true;
206 static bool tokGreaterThanEquals(Token &/*tok*/, Stack &stack)
208     StackItem item1 = stack.pop();
209     StackItem item2 = stack.pop();
210     item1.ival = (item1.dval >= item2.dval);
211     stack.push(item1);
212     return true;
216 static bool tokGreaterThan(Token &/*tok*/, Stack &stack)
218     StackItem item1 = stack.pop();
219     StackItem item2 = stack.pop();
220     item1.ival = (item1.dval > item2.dval);
221     stack.push(item1);
222     return true;
230 //###########################
231 //# X P A T H    I T E M S
232 //###########################
234 static bool tokAbsolute(Token &/*tok*/, Stack &/*stack*/)
236     return true;
239 static bool tokRelative(Token &/*tok*/, Stack &/*stack*/)
241     return true;
244 static bool tokStep(Token &/*tok*/, Stack &/*stack*/)
246     return true;
249 static bool tokNameTest(Token &/*tok*/, Stack &/*stack*/)
251     return true;
254 static bool tokExpr(Token &/*tok*/, Stack &/*stack*/)
256     return true;
259 static bool tokUnion(Token &/*tok*/, Stack &/*stack*/)
261     return true;
267 //###########################
268 //# A X I S
269 //###########################
272 static bool tokAxisAncestorOrSelf(Token &/*tok*/, Stack &/*stack*/)
274     return true;
278 static bool tokAxisAncestor(Token &/*tok*/, Stack &/*stack*/)
280     return true;
284 static bool tokAxisAttribute(Token &/*tok*/, Stack &/*stack*/)
286     return true;
290 static bool tokAxisChild(Token &/*tok*/, Stack &/*stack*/)
292     return true;
296 static bool tokAxisDescendantOrSelf(Token &/*tok*/, Stack &/*stack*/)
298     return true;
302 static bool tokAxisDescendant(Token &/*tok*/, Stack &/*stack*/)
304     return true;
308 static bool tokAxisFollowingSibling(Token &/*tok*/, Stack &/*stack*/)
310     return true;
314 static bool tokAxisFollowing(Token &/*tok*/, Stack &/*stack*/)
316     return true;
320 static bool tokAxisNamespace(Token &/*tok*/, Stack &/*stack*/)
322     return true;
326 static bool tokAxisParent(Token &/*tok*/, Stack &/*stack*/)
328     return true;
332 static bool tokAxisPrecedingSibling(Token &/*tok*/, Stack &/*stack*/)
334     return true;
338 static bool tokAxisPreceding(Token &/*tok*/, Stack &/*stack*/)
340     return true;
344 static bool tokAxisSelf(Token &/*tok*/, Stack &/*stack*/)
346     return true;
351 //###########################
352 //# F U N C T I O N S
353 //###########################
356 static bool tokFuncLast(Token &/*tok*/, Stack &/*stack*/)
358     return true;
362 static bool tokFuncPosition(Token &/*tok*/, Stack &/*stack*/)
364     return true;
368 static bool tokFuncCount(Token &/*tok*/, Stack &/*stack*/)
370     return true;
374 static bool tokFuncId(Token &/*tok*/, Stack &/*stack*/)
376     return true;
380 static bool tokFuncLocalName(Token &/*tok*/, Stack &/*stack*/)
382     return true;
386 static bool tokFuncNamespaceUri(Token &/*tok*/, Stack &/*stack*/)
388     return true;
392 static bool tokFuncName(Token &/*tok*/, Stack &/*stack*/)
394     return true;
398 static bool tokFuncString(Token &/*tok*/, Stack &/*stack*/)
400     return true;
404 static bool tokFuncConcat(Token &/*tok*/, Stack &/*stack*/)
406     return true;
410 static bool tokFuncStartsWith(Token &/*tok*/, Stack &/*stack*/)
412     return true;
416 static bool tokFuncContains(Token &/*tok*/, Stack &/*stack*/)
418     return true;
422 static bool tokFuncSubstringBefore(Token &/*tok*/, Stack &/*stack*/)
424     return true;
428 static bool tokFuncSubstringAfter(Token &/*tok*/, Stack &/*stack*/)
430     return true;
434 static bool tokFuncSubstring(Token &/*tok*/, Stack &/*stack*/)
436     return true;
440 static bool tokFuncStringLength(Token &/*tok*/, Stack &/*stack*/)
442     return true;
446 static bool tokFuncNormalizeSpace(Token &/*tok*/, Stack &/*stack*/)
448     return true;
452 static bool tokFuncTranslate(Token &/*tok*/, Stack &/*stack*/)
454     return true;
458 static bool tokFuncBoolean(Token &/*tok*/, Stack &/*stack*/)
460     return true;
464 static bool tokFuncNot(Token &/*tok*/, Stack &/*stack*/)
466     return true;
470 static bool tokFuncTrue(Token &/*tok*/, Stack &/*stack*/)
472     return true;
476 static bool tokFuncFalse(Token &/*tok*/, Stack &/*stack*/)
478     return true;
482 static bool tokFuncLang(Token &/*tok*/, Stack &/*stack*/)
484     return true;
488 static bool tokFuncNumber(Token &/*tok*/, Stack &/*stack*/)
490     return true;
494 static bool tokFuncSum(Token &/*tok*/, Stack &/*stack*/)
496     return true;
500 static bool tokFuncFloor(Token &/*tok*/, Stack &/*stack*/)
502     return true;
506 static bool tokFuncCeiling(Token &/*tok*/, Stack &/*stack*/)
508     return true;
512 static bool tokFuncRound(Token &/*tok*/, Stack &/*stack*/)
514     return true;
519 /**
520  * An entry for the token 'personality' table
521  */
522 typedef struct
524     int ival;
525     char const *sval;
526     TokenFunc tokenFunc;
527 } TokenTableEntry;
530 /**
531  * The token personality table
532  */
533 static TokenTableEntry tokenTable[] =
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()
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;
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)
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         }
922     
923     return tok;
933 //########################################################################
934 //# X P A T H    E X E C U T O R
935 //########################################################################
937 /**
938  *
939  */
940 TokenExecutor::TokenExecutor()
942     reset();
946 /**
947  *
948  */
949 TokenExecutor::TokenExecutor(const TokenExecutor &other)
951     reset();
952     assign(other);
956 /**
957  *
958  */
959 TokenExecutor::~TokenExecutor()
964 /**
965  *
966  */
967 void TokenExecutor::assign(const TokenExecutor &other)
969     tokenList   = other.tokenList;
973 /**
974  *
975  */
976 void TokenExecutor::reset()
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)
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;
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)
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;
1065 } // namespace xpath
1066 } // namespace dom
1067 } // namespace w3c
1068 } // namespace org
1069 //########################################################################
1070 //# E N D    O F    F I L E
1071 //########################################################################