00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <spl/Debug.h>
00018 #include <spl/Log.h>
00019 #include <spl/xml/xpath/private/XPathLex.h>
00020
00021 #ifdef DEBUG
00022
00023 const char* const _theNumericTestInput[] =
00024 {
00025 "9 + 7 - 6 * 42 + 36 div 3 + 100 - 2 * 6",
00026 "9 + 7 - 6 + 3 + 24 - 32 - 89 + 123 - 12256 + 89957",
00027 "0 + 0",
00028 "1 div 2",
00029 "1 * 0.25",
00030 "3 * 3 * 3",
00031 "9 div 3 div 3",
00032 "15.95 - 13.56",
00033 0
00034 };
00035
00036 const double _theNumericTestExpectedOutput[] =
00037 {
00038 -136.0,
00039 77740.0,
00040 0,
00041 0.5,
00042 0.25,
00043 27,
00044 1,
00045 15.95 - 13.56,
00046 0
00047 };
00048
00049 const char* const _theBooleanTestInput[] =
00050 {
00051 "0 < 2 < 3",
00052 "0 < 2 > 3",
00053 "1 < 2 < 3",
00054
00055 "0 div 0 != 0 div 0",
00056 "0 div 0 = 0 div 0",
00057 "1 < 0 div 0",
00058 "1 <= 0 div 0",
00059 "2 > 0 div 0",
00060 "2 >= 0 div 0",
00061
00062 "1 < 2",
00063 "1500 < 657",
00064 "1465787676 < 5 div 0",
00065 "4657 div 0 < 4563745658",
00066
00067 "1000 <= 256000",
00068 "1000 <= 1000",
00069 "200564 <= 1999",
00070 "5768594 <= 56 div 0",
00071 "564783 div 0 <= 6758494857",
00072
00073 "2015 > 100",
00074 "56478 > 240000",
00075 "4657 div 0 > 57683946",
00076 "573068574 > 5 div 0",
00077
00078 "46000 >= 1500",
00079 "56983 >= 56983",
00080 "460983 >= 1500000",
00081 "67594876 div 0 >= 576849",
00082
00083 "1465787676 >= 5 div 0",
00084 "-1465787676 >= -5 div 0",
00085 "-1679 < -87 div 0",
00086
00087 "1 = 2 = 0",
00088 "1 = 2 != 0",
00089
00090 0
00091 };
00092
00093 const bool _theBooleanTestExpectedOutput[] =
00094 {
00095 true,
00096 false,
00097 true,
00098
00099 true,
00100 false,
00101 false,
00102 false,
00103 false,
00104 false,
00105
00106 true,
00107 false,
00108 true,
00109 false,
00110
00111 true,
00112 true,
00113 false,
00114 true,
00115 false,
00116
00117 true,
00118 false,
00119 true,
00120 false,
00121
00122 true,
00123 true,
00124 false,
00125 true,
00126
00127 false,
00128 true,
00129 false,
00130
00131 true,
00132 false,
00133
00134 0
00135 };
00136
00137 const char* const _theStringTestInput[] =
00138 {
00139 "string(0)",
00140 "string(1.5)",
00141 "string(-1.5)",
00142 "string(0.5)",
00143 "string(-0.5)",
00144 "string(9)",
00145 "string(-9)",
00146 "string(\"9\")",
00147 "string(0.25)",
00148
00149 "concat(\"foo\", \"bar\")",
00150 "concat(\"foo\", \"bar\", \"sky\")",
00151
00152 "contains(\"foobar\", \"oba\")",
00153 "contains(\"LotusXSL4C is great\", \"boag\")",
00154
00155 "starts-with(\"foobar\", \"foo\")",
00156 "starts-with(\"LotusXSL4C is great\", \"boag\")",
00157
00158 "substring-after(\"1999/04/01\", \"/\")",
00159 "substring-after(\"1999/04/01\", \"19\")",
00160
00161 "substring-before(\"1999/04/01\", \"/\")",
00162 "substring-before(\"1999/04/01\", \"01\")",
00163
00164 "substring(\"12345\", 1.5, 2.6)",
00165 "substring(\"12345\", 0, 3)",
00166 "substring(\"12345\", 5, 29)",
00167 "substring(\"12345\", -1, 2)",
00168 "substring(\"12345\", -2, -1)",
00169 "substring(\"12345\", -2)",
00170
00171 "normalize-space(\" aa a \")",
00172
00173 "translate(\"---aaa--\", \"abc-\", \"ABC\")",
00174
00175 "5 = 0",
00176 "5 = 5",
00177 0
00178 };
00179
00180 const char* const _theStringTestExpectedOutput[] =
00181 {
00182 "0",
00183 "1.5",
00184 "-1.5",
00185 "0.5",
00186 "-0.5",
00187 "9",
00188 "-9",
00189 "9",
00190 "0.25",
00191
00192 "foobar",
00193 "foobarsky",
00194
00195 "true",
00196 "false",
00197
00198 "true",
00199 "false",
00200
00201 "04/01",
00202 "99/04/01",
00203
00204 "1999",
00205 "1999/04/",
00206
00207 "234",
00208 "12",
00209 "5",
00210 "",
00211 "",
00212 "12345",
00213
00214 "aa a",
00215
00216 "AAA",
00217
00218 "false",
00219 "true",
00220 0
00221 };
00222
00223 static void _TestXPathLexNumeric()
00224 {
00225 XPathLex lex;
00226
00227
00228 lex.Tokenize(_theNumericTestInput[0]);
00229
00230 DEBUG_CLEAR_MEM_CHECK_POINTS();
00231 lex.CheckMem();
00232 UNIT_ASSERT_MEM_NOTED("_TestXPathLexNumeric");
00233
00234 UNIT_ASSERT("9", lex.CurrentLexum() == "9");
00235 UNIT_ASSERT("9", lex.CurrentToken() == XPathLex::XP_INT);
00236 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00237
00238 UNIT_ASSERT("+", lex.Match(XPathLex::XP_INT) == XPathLex::XP_PLUS);
00239 UNIT_ASSERT("+", lex.CurrentLexum() == "+");
00240 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00241
00242 UNIT_ASSERT("7", lex.Match(XPathLex::XP_PLUS) == XPathLex::XP_INT);
00243 UNIT_ASSERT("7", lex.CurrentLexum() == "7");
00244 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00245
00246 UNIT_ASSERT("-", lex.Match(XPathLex::XP_INT) == XPathLex::XP_MIN);
00247 UNIT_ASSERT("-", lex.CurrentLexum() == "-");
00248 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00249
00250 UNIT_ASSERT("6", lex.Match(XPathLex::XP_MIN) == XPathLex::XP_INT);
00251 UNIT_ASSERT("6", lex.CurrentLexum() == "6");
00252 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00253
00254 UNIT_ASSERT("*", lex.Match(XPathLex::XP_INT) == XPathLex::XP_STAR);
00255 UNIT_ASSERT("*", lex.CurrentLexum() == "*");
00256 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00257
00258 UNIT_ASSERT("42", lex.Match(XPathLex::XP_STAR) == XPathLex::XP_INT);
00259 UNIT_ASSERT("42", lex.CurrentLexum() == "42");
00260 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00261
00262 UNIT_ASSERT("+", lex.Match(XPathLex::XP_INT) == XPathLex::XP_PLUS);
00263 UNIT_ASSERT("+", lex.CurrentLexum() == "+");
00264 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00265
00266 UNIT_ASSERT("36", lex.Match(XPathLex::XP_PLUS) == XPathLex::XP_INT);
00267 UNIT_ASSERT("36", lex.CurrentLexum() == "36");
00268 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00269
00270 UNIT_ASSERT("div", lex.Match(XPathLex::XP_INT) == XPathLex::XP_LITERAL);
00271 UNIT_ASSERT("div", lex.CurrentLexum() == "div");
00272 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00273
00274 UNIT_ASSERT("3", lex.Match(XPathLex::XP_LITERAL) == XPathLex::XP_INT);
00275 UNIT_ASSERT("3", lex.CurrentLexum() == "3");
00276 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00277
00278 UNIT_ASSERT("+", lex.Match(XPathLex::XP_INT) == XPathLex::XP_PLUS);
00279 UNIT_ASSERT("+", lex.CurrentLexum() == "+");
00280 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00281
00282 UNIT_ASSERT("100", lex.Match(XPathLex::XP_PLUS) == XPathLex::XP_INT);
00283 UNIT_ASSERT("100", lex.CurrentLexum() == "100");
00284 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00285
00286 UNIT_ASSERT("-", lex.Match(XPathLex::XP_INT) == XPathLex::XP_MIN);
00287 UNIT_ASSERT("-", lex.CurrentLexum() == "-");
00288 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00289
00290 UNIT_ASSERT("2", lex.Match(XPathLex::XP_MIN) == XPathLex::XP_INT);
00291 UNIT_ASSERT("2", lex.CurrentLexum() == "2");
00292 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00293
00294 UNIT_ASSERT("*", lex.Match(XPathLex::XP_INT) == XPathLex::XP_STAR);
00295 UNIT_ASSERT("*", lex.CurrentLexum() == "*");
00296 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00297
00298 UNIT_ASSERT("6", lex.Match(XPathLex::XP_STAR) == XPathLex::XP_INT);
00299 UNIT_ASSERT("6", lex.CurrentLexum() == "6");
00300 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00301
00302 UNIT_ASSERT("EOF", lex.Match(XPathLex::XP_INT) == XPathLex::XP_EOF);
00303 UNIT_ASSERT("EOF", lex.CurrentToken() == XPathLex::XP_EOF);
00304 UNIT_ASSERT("EOF LEX", lex.CurrentLexum() == "");
00305 UNIT_ASSERT("HasMoreTokens", !lex.HasMoreTokens());
00306
00307 Log::SWriteOkFail( "XPathLex numerics 1" );
00308 }
00309
00310 static void _TestXPathLexNumeric2()
00311 {
00312 XPathLex lex;
00313
00314
00315 lex.Tokenize(_theNumericTestInput[7]);
00316 UNIT_ASSERT("15.95", lex.CurrentLexum() == "15.95");
00317 UNIT_ASSERT("15.95", lex.CurrentToken() == XPathLex::XP_FLOAT);
00318 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00319
00320 UNIT_ASSERT("-", lex.Match(XPathLex::XP_FLOAT) == XPathLex::XP_MIN);
00321 UNIT_ASSERT("-", lex.CurrentLexum() == "-");
00322 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00323
00324 UNIT_ASSERT("13.56", lex.Match(XPathLex::XP_MIN) == XPathLex::XP_FLOAT);
00325 UNIT_ASSERT("13.56", lex.CurrentLexum() == "13.56");
00326 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00327
00328 UNIT_ASSERT("EOF", lex.Match(XPathLex::XP_FLOAT) == XPathLex::XP_EOF);
00329 UNIT_ASSERT("EOF", lex.CurrentToken() == XPathLex::XP_EOF);
00330 UNIT_ASSERT("EOF LEX", lex.CurrentLexum() == "");
00331 UNIT_ASSERT("HasMoreTokens", !lex.HasMoreTokens());
00332
00333 Log::SWriteOkFail( "XPathLex numerics 2" );
00334 }
00335
00336 static void _TestXPathLexOperators()
00337 {
00338 XPathLex lex;
00339
00340 lex.Tokenize("-12 < .12 <= -1.0 == 1 != 1 > 2 >= 3");
00341
00342 UNIT_ASSERT("-12", lex.CurrentLexum() == "-12");
00343 UNIT_ASSERT("15.95", lex.CurrentToken() == XPathLex::XP_INT);
00344 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00345
00346 UNIT_ASSERT("<", lex.Match(XPathLex::XP_INT) == XPathLex::XP_LT);
00347 UNIT_ASSERT("<", lex.CurrentLexum() == "<");
00348 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00349
00350 UNIT_ASSERT(".12", lex.Match(XPathLex::XP_LT) == XPathLex::XP_FLOAT);
00351 UNIT_ASSERT(".12", lex.CurrentLexum() == ".12");
00352 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00353
00354 UNIT_ASSERT("<=", lex.Match(XPathLex::XP_FLOAT) == XPathLex::XP_LTEQ);
00355 UNIT_ASSERT("<=", lex.CurrentLexum() == "<=");
00356 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00357
00358 UNIT_ASSERT("-1.0", lex.Match(XPathLex::XP_LTEQ) == XPathLex::XP_FLOAT);
00359 UNIT_ASSERT("-1.0", lex.CurrentLexum() == "-1.0");
00360 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00361
00362 UNIT_ASSERT("==", lex.Match(XPathLex::XP_FLOAT) == XPathLex::XP_EQEQ);
00363 UNIT_ASSERT("==", lex.CurrentLexum() == "==");
00364 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00365
00366 UNIT_ASSERT("1", lex.Match(XPathLex::XP_EQEQ) == XPathLex::XP_INT);
00367 UNIT_ASSERT("1", lex.CurrentLexum() == "1");
00368 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00369
00370 UNIT_ASSERT("!=", lex.Match(XPathLex::XP_INT) == XPathLex::XP_NEQ);
00371 UNIT_ASSERT("!=", lex.CurrentLexum() == "!=");
00372 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00373
00374 UNIT_ASSERT("1", lex.Match(XPathLex::XP_NEQ) == XPathLex::XP_INT);
00375 UNIT_ASSERT("1", lex.CurrentLexum() == "1");
00376 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00377
00378 UNIT_ASSERT(">", lex.Match(XPathLex::XP_INT) == XPathLex::XP_GT);
00379 UNIT_ASSERT(">", lex.CurrentLexum() == ">");
00380 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00381
00382 UNIT_ASSERT("2", lex.Match(XPathLex::XP_GT) == XPathLex::XP_INT);
00383 UNIT_ASSERT("2", lex.CurrentLexum() == "2");
00384 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00385
00386 UNIT_ASSERT(">=", lex.Match(XPathLex::XP_INT) == XPathLex::XP_GTEQ);
00387 UNIT_ASSERT(">=", lex.CurrentLexum() == ">=");
00388 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00389
00390 UNIT_ASSERT("3", lex.Match(XPathLex::XP_GTEQ) == XPathLex::XP_INT);
00391 UNIT_ASSERT("3", lex.CurrentLexum() == "3");
00392 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00393
00394 UNIT_ASSERT("EOF", lex.Match(XPathLex::XP_INT) == XPathLex::XP_EOF);
00395 UNIT_ASSERT("EOF", lex.CurrentToken() == XPathLex::XP_EOF);
00396 UNIT_ASSERT("EOF LEX", lex.CurrentLexum() == "");
00397 UNIT_ASSERT("HasMoreTokens", !lex.HasMoreTokens());
00398
00399 Log::SWriteOkFail( "XPathLex operators" );
00400 }
00401
00402 static void _TestXPathLexExpr()
00403 {
00404 XPathLex lex;
00405
00406 lex.Tokenize("//title[@lang='eng']");
00407
00408 UNIT_ASSERT("//", lex.CurrentLexum() == "//");
00409 UNIT_ASSERT("15.95", lex.CurrentToken() == XPathLex::XP_SLASHSLASH);
00410 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00411
00412 UNIT_ASSERT("title", lex.Match(XPathLex::XP_SLASHSLASH) == XPathLex::XP_LITERAL);
00413 UNIT_ASSERT("title", lex.CurrentLexum() == "title");
00414 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00415
00416 UNIT_ASSERT("[", lex.Match(XPathLex::XP_LITERAL) == XPathLex::XP_LBRAC);
00417 UNIT_ASSERT("[", lex.CurrentLexum() == "[");
00418 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00419
00420 UNIT_ASSERT("@", lex.Match(XPathLex::XP_LBRAC) == XPathLex::XP_AT);
00421 UNIT_ASSERT("@", lex.CurrentLexum() == "@");
00422 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00423
00424 UNIT_ASSERT("lang", lex.Match(XPathLex::XP_AT) == XPathLex::XP_LITERAL);
00425 UNIT_ASSERT("lang", lex.CurrentLexum() == "lang");
00426 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00427
00428 UNIT_ASSERT("=", lex.Match(XPathLex::XP_LITERAL) == XPathLex::XP_EQ);
00429 UNIT_ASSERT("=", lex.CurrentLexum() == "=");
00430 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00431
00432 UNIT_ASSERT("eng", lex.Match(XPathLex::XP_EQ) == XPathLex::XP_STRING);
00433 UNIT_ASSERT("eng", lex.CurrentLexum() == "eng");
00434 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00435
00436 UNIT_ASSERT("]", lex.Match(XPathLex::XP_STRING) == XPathLex::XP_RBRAC);
00437 UNIT_ASSERT("]", lex.CurrentLexum() == "]");
00438 UNIT_ASSERT("HasMoreTokens", lex.HasMoreTokens());
00439
00440 UNIT_ASSERT("EOF", lex.Match(XPathLex::XP_RBRAC) == XPathLex::XP_EOF);
00441 UNIT_ASSERT("EOF", lex.CurrentToken() == XPathLex::XP_EOF);
00442 UNIT_ASSERT("EOF LEX", lex.CurrentLexum() == "");
00443 UNIT_ASSERT("HasMoreTokens", !lex.HasMoreTokens());
00444
00445 Log::SWriteOkFail( "XPathLex expressions" );
00446 }
00447
00448 void _TestXPathLex()
00449 {
00450 _TestXPathLexNumeric();
00451 DEBUG_CLEAR_MEM_CHECK_POINTS();
00452 DEBUG_DUMP_MEM_LEAKS();
00453
00454 _TestXPathLexNumeric2();
00455 DEBUG_CLEAR_MEM_CHECK_POINTS();
00456 DEBUG_DUMP_MEM_LEAKS();
00457
00458 _TestXPathLexOperators();
00459 DEBUG_CLEAR_MEM_CHECK_POINTS();
00460 DEBUG_DUMP_MEM_LEAKS();
00461
00462 _TestXPathLexExpr();
00463 DEBUG_CLEAR_MEM_CHECK_POINTS();
00464 DEBUG_DUMP_MEM_LEAKS();
00465 }
00466
00467 #endif
00468
00469
00470