1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2016-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "nel/misc/eval_num_expr.h"
23 #include "nel/misc/debug.h"
34 // ***************************************************************************
36 CEvalNumExpr::TReturnState
CEvalNumExpr::readDecimal (double &value
)
38 // Read first integer value
39 readIntegerNumberDecimal (value
);
42 char currentChar
= *_ExprPtr
;
43 if (currentChar
== '.')
47 currentChar
= *_ExprPtr
;
48 if (currentChar
< '0' || currentChar
> '9')
49 return NumberSyntaxError
;
51 // Read the decimal part
52 const char *start
= _ExprPtr
;
54 readIntegerNumberDecimal (fract
);
55 fract
/= (double)pow (10.0,(sint
)(_ExprPtr
-start
));
62 // ***************************************************************************
64 void CEvalNumExpr::readIntegerNumberDecimal (double &value
)
67 register double regValue
= 0;
69 // Read the first value
70 char currentChar
= *_ExprPtr
;
71 if ((currentChar
>= '0') && (currentChar
<= '9'))
73 regValue
+= (currentChar
- '0');
75 currentChar
= *_ExprPtr
;
78 while ((currentChar
>= '0') && (currentChar
<= '9'))
81 regValue
+= (currentChar
- '0');
85 currentChar
= *_ExprPtr
;
93 // ***************************************************************************
95 CEvalNumExpr::TReturnState
CEvalNumExpr::getNextToken (TToken
&token
)
97 // Get the current char
98 uint8 currentChar
= *_ExprPtr
;
101 while ((currentChar
!=0) && (currentChar
<=0x20))
104 currentChar
= *_ExprPtr
;
107 // Can be an operator ?
108 if (currentChar
<= 128)
111 _Op
= _OperatorArray
[currentChar
];
114 if (_Op
!= NotOperator
)
119 // Is a 2 characters operator ?
120 if (_Op
!= ExtOperator
)
122 // Return next character
128 // Have a second character ?
129 char secondChar
= *(_ExprPtr
+1);
131 // What kind of 1st character
135 if (secondChar
== '=')
148 if (secondChar
== '&')
161 if (secondChar
== '>')
174 if (secondChar
== '<')
180 else if (secondChar
== '=')
186 else if (secondChar
== '-')
199 if (secondChar
== '=')
206 if (secondChar
== '>')
212 else if (secondChar
== '=')
225 if (secondChar
== '^')
238 if (secondChar
== '|')
252 // Can't found the operator
253 return UnknownOperator
;
256 // Is End, '(', ')', '.' ?
257 else if (currentChar
== 0)
262 else if (currentChar
== '(')
268 else if (currentChar
== ')')
274 else if (currentChar
== ',')
281 else if (((currentChar
>= '0') && (currentChar
<= '9')) || (currentChar
== '.'))
286 // Have a second character ?
287 char secondChar
= *(_ExprPtr
+1);
289 // Is an hexadecimal value ?
290 if ((currentChar
== '0') && (secondChar
== 'x'))
294 currentChar
= *_ExprPtr
;
297 register double regValue
= 0;
298 if ((currentChar
>= '0') && (currentChar
<= '9'))
300 regValue
+= (currentChar
- '0');
302 else if ((currentChar
>= 'a') && (currentChar
<= 'f'))
304 regValue
+= (currentChar
- 'a' + 10);
306 else if ((currentChar
>= 'A') && (currentChar
<= 'F'))
308 regValue
+= (currentChar
- 'A' + 10);
312 // Number syntax error
313 return NumberSyntaxError
;
316 currentChar
= *_ExprPtr
;
321 if ((currentChar
>= '0') && (currentChar
<= '9'))
324 regValue
+= (currentChar
- '0');
326 else if ((currentChar
>= 'a') && (currentChar
<= 'f'))
329 regValue
+= (currentChar
- 'a' + 10);
331 else if ((currentChar
>= 'A') && (currentChar
<= 'F'))
334 regValue
+= (currentChar
- 'A' + 10);
344 currentChar
= *_ExprPtr
;
353 // Is an octal value ?
354 else if ((currentChar
== '0') && (secondChar
>= '0') && (secondChar
<= '9'))
358 currentChar
= *_ExprPtr
;
361 register double regValue
= 0;
363 // Check octal number
364 if (currentChar
> '7')
365 return NumberSyntaxError
;
367 // Read the first value
368 regValue
+= (currentChar
- '0');
370 currentChar
= *_ExprPtr
;
373 while ((currentChar
>= '0') && (currentChar
<= '9'))
375 // Check octal number
376 if (currentChar
> '7')
377 return NumberSyntaxError
;
380 regValue
+= (currentChar
- '0');
384 currentChar
= *_ExprPtr
;
393 // It is a decimal value
397 TReturnState state
= readDecimal (_Value
);
398 if (state
== NoError
)
401 currentChar
= *_ExprPtr
;
402 if ( (currentChar
== 'e') || (currentChar
== 'E') )
408 bool negative
= false;
409 if (*_ExprPtr
== '-')
417 state
= readDecimal (exponent
);
418 if (state
== NoError
)
422 exponent
= -exponent
;
424 // Raise 10 at the power of
425 _Value
*= pow (10.0, exponent
);
443 else if (currentChar
== '"')
445 // Look for the end of the string
447 currentChar
= *_ExprPtr
;
448 const char *start
= _ExprPtr
;
449 while ( (currentChar
!= 0) && (currentChar
!= '"') )
452 currentChar
= *_ExprPtr
;
456 if (currentChar
== 0)
457 return MustBeDoubleQuote
;
459 // This is a user string, copy the string
460 uint size
= (uint
)(_ExprPtr
- start
);
461 if (size
>= (InternalStringLen
-1))
463 _InternalStlString
.resize (size
);
465 for (i
=0; i
<size
; i
++)
466 _InternalStlString
[i
] = start
[i
];
467 _InternalStringPtr
= _InternalStlString
.c_str ();
471 memcpy (_InternalString
, start
, size
);
472 _InternalString
[size
] = 0;
473 _InternalStringPtr
= _InternalString
;
484 const char *start
= _ExprPtr
;
485 while ( (currentChar
>= 128) || _StringChar
[currentChar
] )
488 currentChar
= *_ExprPtr
;
492 if (((_ExprPtr
- start
) == 2) && (start
[0] == 'p') && (start
[1] == 'i'))
495 _Value
= 3.1415926535897932384626433832795;
499 else if (((_ExprPtr
- start
) == 1) && (start
[0] == 'e'))
502 _Value
= 2.7182818284590452353602874713527;
506 // This is a user string, copy the string
507 uint size
= (uint
)(_ExprPtr
- start
);
508 if (size
>= (InternalStringLen
-1))
510 _InternalStlString
.resize (size
);
512 for (i
=0; i
<size
; i
++)
513 _InternalStlString
[i
] = start
[i
];
514 _InternalStringPtr
= _InternalStlString
.c_str ();
518 memcpy (_InternalString
, start
, size
);
519 _InternalString
[size
] = 0;
520 _InternalStringPtr
= _InternalString
;
523 // Search for a reserved word ?
525 uint end
= ReservedWordCount
-1;
526 sint result
= strcmp (_InternalStringPtr
, _ReservedWord
[begin
]);
529 // The first is the good ?
535 result
= strcmp (_InternalStringPtr
, _ReservedWord
[end
]);
538 // The last is the good ?
544 // While there is a middle..
545 while ((end
- begin
) > 1)
547 uint middle
= begin
+ (end
- begin
) / 2;
548 result
= strcmp (_InternalStringPtr
, _ReservedWord
[middle
]);
570 _ReservedWordFound
= (TReservedWord
)begin
;
571 token
= _ReservedWordToken
[begin
];
583 // ***************************************************************************
585 CEvalNumExpr::TReturnState
CEvalNumExpr::evalExpression (const char *expression
, double &result
,
586 int *errorIndex
, uint32 userData
)
589 _ExprPtr
= expression
;
592 TReturnState error
= evalExpression (result
, nextToken
, userData
);
593 if (error
== NoError
)
596 if (nextToken
== End
)
601 *errorIndex
= (int)(_ExprPtr
- expression
);
608 *errorIndex
= (int)(_ExprPtr
- expression
);
613 // ***************************************************************************
615 CEvalNumExpr::TReturnState
CEvalNumExpr::evalExpression (double &finalResult
, TToken
&nextToken
, uint32 userData
)
620 double result
[InternalOperator
];
621 vector
<double> resultSup
;
624 TOperator resultOp
[InternalOperator
];
625 vector
<TOperator
> resultOpSup
;
628 TReturnState error
= getNextToken (nextToken
);
629 if (error
!= NoError
)
634 uint unaryOpCount
= 0;
635 TOperator resultUnaryOp
[InternalOperator
];
636 vector
<TOperator
> resultUnaryOpSup
;
639 for (uint i
= 0; i
< (uint
)InternalOperator
; ++i
) resultUnaryOp
[i
] = NotOperator
;
645 if ( (nextToken
== Operator
) && ( (_Op
== Minus
) || (_Op
== Not
) || (_Op
== Tilde
) ) )
647 // Push the unary operator
648 if (unaryOpCount
<InternalOperator
)
649 resultUnaryOp
[unaryOpCount
] = _Op
;
651 resultUnaryOpSup
.push_back (_Op
);
655 error
= getNextToken (nextToken
);
656 if (error
!= NoError
)
661 if (nextToken
== Open
)
663 // Eval sub expression
664 error
= evalExpression (value
, nextToken
, userData
);
665 if (error
== NoError
)
667 if (nextToken
!= Close
)
674 error
= getNextToken (nextToken
);
675 if (error
!= NoError
)
678 // This is a function ?
679 else if ( (nextToken
== Function1
) || (nextToken
== Function2
) )
681 TToken backupedToken
= nextToken
;
684 TReservedWord reservedWord
= _ReservedWordFound
;
687 error
= getNextToken (nextToken
);
688 if (error
== NoError
)
691 if (nextToken
!= Open
)
696 // Eval an expression
698 error
= evalExpression (arg0
, nextToken
, userData
);
699 if (error
== NoError
)
702 if (backupedToken
== Function2
)
704 if (nextToken
== Coma
)
708 error
= evalExpression (arg1
, nextToken
, userData
);
709 if (error
== NoError
)
711 // Final with close ?
712 if (nextToken
== Close
)
714 switch (reservedWord
)
717 value
= atan2 (arg0
, arg1
);
720 value
= (arg0
>arg1
) ? arg0
: arg1
;
723 value
= (arg0
<arg1
) ? arg0
: arg1
;
726 value
= pow (arg0
, arg1
);
729 value
= arg0
+ (arg1
-arg0
) * (double)rand () / ((double)RAND_MAX
+1.0);
732 // Can't be here after getToken
747 if (nextToken
== Close
)
750 switch (reservedWord
)
776 (void)frexp( arg0
, &exponent
);
777 value
= (double)exponent
;
784 value
= floor (arg0
);
787 value
= (double)(int)(arg0
);
790 value
= log10 (arg0
);
798 value
= frexp( arg0
, &exponent
);
802 value
= floor (arg0
+ 0.5);
823 // Can't be hear after getToken
838 error
= getNextToken (nextToken
);
839 if (error
!= NoError
)
842 else if (nextToken
== Number
)
844 // Save the internal value
848 error
= getNextToken (nextToken
);
849 if (error
!= NoError
)
852 else if (nextToken
== String
)
855 char internalString
[InternalStringLen
];
856 std::string internalStlString
;
857 const char *internalStringPtr
;
858 if (strlen (_InternalStringPtr
) >= InternalStringLen
-1)
860 internalStlString
= _InternalStringPtr
;
861 internalStringPtr
= internalStlString
.c_str ();
865 strcpy (internalString
,_InternalStringPtr
);
866 internalStringPtr
= internalString
;
870 error
= getNextToken (nextToken
);
871 if (error
== NoError
)
874 if (nextToken
== Open
)
876 // Eval an expression
878 error
= evalExpression (arg0
, nextToken
, userData
);
879 if (error
== NoError
)
881 if (nextToken
== Coma
)
885 error
= evalExpression (arg1
, nextToken
, userData
);
886 if (error
== NoError
)
888 // Final with close ?
889 if (nextToken
== Close
)
892 error
= evalFunction (internalStringPtr
, arg0
, arg1
, value
);
893 if (error
!= NoError
)
897 error
= getNextToken (nextToken
);
898 if (error
!= NoError
)
909 if (nextToken
== Close
)
912 error
= evalFunction (internalStringPtr
, arg0
, value
);
913 if (error
!= NoError
)
917 error
= getNextToken (nextToken
);
918 if (error
!= NoError
)
930 // This is a user value
931 error
= evalValue (internalStringPtr
, value
, userData
);
932 if (error
!= NoError
)
941 return MustBeExpression
;
944 // Eval unary operator
946 for (i
=unaryOpCount
-1; i
>=0; i
--)
948 switch ((i
<InternalOperator
)?resultUnaryOp
[i
]:resultUnaryOpSup
[i
-InternalOperator
])
951 value
= (double)(uint
)((floor (value
+0.5)==0.0));
954 value
= (double)(~((uint
)floor (value
+0.5)) & std::numeric_limits
<uint
>::max());
960 // Can't be hear after getToken
966 if (exprCount
< InternalOperator
)
967 result
[exprCount
] = value
;
969 resultSup
.push_back (value
);
972 // Look for an operator
974 if (nextToken
== Operator
)
977 if (opCount
< InternalOperator
)
978 resultOp
[opCount
] = _Op
;
980 resultOpSup
.push_back (_Op
);
985 // Exit the evaluate loop
990 error
= getNextToken (nextToken
);
993 // Reduce the expression
995 while (exprCount
!= 1)
998 TOperator before
= (((index
-1)<InternalOperator
)?resultOp
[index
-1]:resultOpSup
[index
-1-InternalOperator
]);
999 TOperator after
= (index
< opCount
)?(((index
)<InternalOperator
)?resultOp
[index
]:resultOpSup
[index
-InternalOperator
]):NotOperator
;
1000 if ((index
== opCount
) || (_OperatorPrecedence
[before
] <= _OperatorPrecedence
[after
]))
1003 double &v0
= ((index
-1)<InternalOperator
)?result
[index
-1]:resultSup
[index
-1-InternalOperator
];
1004 double &v1
= ((index
)<InternalOperator
)?result
[index
]:resultSup
[index
-InternalOperator
];
1006 // Choose the operator
1011 return NotUnaryOperator
;
1035 v0
= (double)(uint
)(((uint
)floor (v0
+ 0.5))<<((uint
)floor (v1
+ 0.5)));
1038 v0
= (double)(((uint
)floor (v0
+ 0.5))>>((uint
)floor (v1
+ 0.5)));
1041 v0
= (double)(sint
)(((sint
)floor (v0
+ 0.5))<<((sint
)floor (v1
+ 0.5)));
1044 v0
= (double)(((sint
)floor (v0
+ 0.5))>>((sint
)floor (v1
+ 0.5)));
1047 v0
= (v0
<v1
)?1.0:0.0;
1050 v0
= (v0
<=v1
)?1.0:0.0;
1053 v0
= (v0
>v1
)?1.0:0.0;
1056 v0
= (v0
>=v1
)?1.0:0.0;
1059 v0
= (v0
==v1
)?1.0:0.0;
1062 v0
= (v0
!=v1
)?1.0:0.0;
1065 v0
= (double)(((uint
)floor (v0
+ 0.5)) & ((uint
)floor (v1
+ 0.5)));
1068 v0
= (double)(((uint
)floor (v0
+ 0.5)) | ((uint
)floor (v1
+ 0.5)));
1071 v0
= (double)(((uint
)floor (v0
+ 0.5)) ^ ((uint
)floor (v1
+ 0.5)));
1074 v0
= (double)(uint
)((floor (v0
+ 0.5) != 0.0) && (floor (v1
+ 0.5) != 0.0));
1077 v0
= (double)(uint
)((floor (v0
+ 0.5) != 0.0) || (floor (v1
+ 0.5) != 0.0));
1081 bool b0
= floor (v0
+ 0.5) != 0.0;
1082 bool b1
= floor (v1
+ 0.5) != 0.0;
1083 v0
= (double)(uint
)((b0
&&!b1
) || ((!b0
)&&b1
));
1090 // Decal others values
1092 for (; i
<exprCount
-1; i
++)
1095 if (i
<InternalOperator
)
1096 result
[i
] = (i
+1<InternalOperator
)?result
[i
+1]:resultSup
[i
+1-InternalOperator
];
1098 resultSup
[i
-InternalOperator
] = (i
+1<InternalOperator
)?result
[i
+1]:resultSup
[i
+1-InternalOperator
];
1104 for (; i
<opCount
-1; i
++)
1107 if (i
<InternalOperator
)
1108 resultOp
[i
] = (i
+1<InternalOperator
)?resultOp
[i
+1]:resultOpSup
[i
+1-InternalOperator
];
1110 resultOpSup
[i
-InternalOperator
] = (i
+1<InternalOperator
)?resultOp
[i
+1]:resultOpSup
[i
+1-InternalOperator
];
1123 finalResult
= result
[0];
1127 // ***************************************************************************
1129 bool CEvalNumExpr::internalCheck ()
1131 for (uint i
=0; i
<ReservedWordCount
-1; i
++)
1132 if (strcmp (_ReservedWord
[i
], _ReservedWord
[i
+1]) >= 0)
1140 // ***************************************************************************
1145 0 NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI
1146 1 DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
1147 2 ! " # $ % & ' ( ) * + , - . /
1148 3 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
1149 4 @ A B C D E F G H I J K L M N O
1150 5 P Q R S T U V W X Y Z [ \ ] ^ _
1151 6 ` a b c d e f g h i j k l m n o
1152 7 p q r s t u v w x y z { | } ~
1155 // ***************************************************************************
1157 const CEvalNumExpr::TOperator
CEvalNumExpr::_OperatorArray
[128] =
1159 NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
,
1160 NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
,
1161 NotOperator
, ExtOperator
, NotOperator
, NotOperator
, NotOperator
, Remainder
, ExtOperator
, NotOperator
, NotOperator
, NotOperator
, Mul
, Plus
, NotOperator
, ExtOperator
, NotOperator
, Div
,
1162 NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, ExtOperator
, ExtOperator
, ExtOperator
, NotOperator
,
1163 NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
,
1164 NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, ExtOperator
, NotOperator
,
1165 NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
,
1166 NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, NotOperator
, ExtOperator
, NotOperator
, Tilde
, NotOperator
,
1169 // ***************************************************************************
1171 const bool CEvalNumExpr::_StringChar
[128] =
1173 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
1174 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
1175 false, false, true, true, true, false, false, true, false, false, false, false, false, false, false, false,
1176 true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, true,
1177 true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
1178 true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true,
1179 true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
1180 true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, true,
1183 // ***************************************************************************
1185 CEvalNumExpr::TReturnState
CEvalNumExpr::evalValue (const char *value
, double &result
, uint32 userData
)
1187 return UnknownValue
;
1190 // ***************************************************************************
1192 CEvalNumExpr::TReturnState
CEvalNumExpr::evalFunction (const char *funcName
, double arg0
, double &result
)
1194 return UnknownFunction
;
1197 // ***************************************************************************
1199 CEvalNumExpr::TReturnState
CEvalNumExpr::evalFunction (const char *funcName
, double arg0
, double arg1
, double &result
)
1201 return UnknownFunction
;
1204 // ***************************************************************************
1206 const char *CEvalNumExpr::_ReservedWord
[ReservedWordCount
] =
1217 "exponent", // Exponent
1222 "mantissa", // Mantissa
1236 // ***************************************************************************
1238 const CEvalNumExpr::TToken
CEvalNumExpr::_ReservedWordToken
[ReservedWordCount
] =
1249 Function1
, // Exponent
1254 Function1
, // Mantissa
1268 // ***************************************************************************
1270 const char *CEvalNumExpr::_ErrorString
[ReturnValueCount
]=
1274 "Error during user defined value evaluation",
1276 "Error during user defined function evaluation",
1277 "Syntax error in a number expression",
1279 "Should be a open parentesis",
1280 "Should be a close parentesis",
1281 "Should be a coma character",
1282 "Should be an expression",
1283 "Should not be an unary operator",
1284 "Should be the end of the expression",
1285 "Should be a double quote",
1289 // ***************************************************************************
1291 const char* CEvalNumExpr::getErrorString (TReturnState state
) const
1293 return _ErrorString
[state
];
1296 // ***************************************************************************
1298 const int CEvalNumExpr::_OperatorPrecedence
[]=
1323 -1, // OperatorCount
1327 // ***************************************************************************