1
0

Query.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  1. #include "../nde.h"
  2. #include "../NDEString.h"
  3. #include "Query.h"
  4. //---------------------------------------------------------------------------
  5. bool Scanner::Query(const char *query)
  6. {
  7. if (!query) return false;
  8. ndestring_release(last_query);
  9. last_query = ndestring_wcsdup(query);
  10. RemoveFilters();
  11. in_query_parser = 1;
  12. bool r = Query_Parse(query);
  13. if (r == false)
  14. {
  15. if (!disable_date_resolution) RemoveFilters();
  16. last_query_failed = true;
  17. }
  18. in_query_parser = 0;
  19. Query_CleanUp();
  20. return r & CheckFilters();
  21. }
  22. const char *Scanner::GetLastQuery()
  23. {
  24. return last_query;
  25. }
  26. typedef struct
  27. {
  28. const char *token;
  29. int tid;
  30. } tokenstruct;
  31. tokenstruct Tokens[] = // Feel free to add more...
  32. {
  33. {"AND", TOKEN_AND },
  34. {"OR", TOKEN_OR },
  35. {"HAS", TOKEN_CONTAINS },
  36. {"NOTHAS",TOKEN_NOTCONTAINS},
  37. {"BEGINS", TOKEN_BEGINS },
  38. {"ENDS", TOKEN_ENDS },
  39. {"ISEMPTY", TOKEN_ISEMPTY},
  40. {"ISNOTEMPTY",TOKEN_ISNOTEMPTY},
  41. {"LIKE", TOKEN_LIKE},
  42. {"BEGINSLIKE", TOKEN_BEGINSLIKE},
  43. };
  44. typedef struct
  45. {
  46. int Op;
  47. int Level;
  48. } OpLevel;
  49. static int Query_ParseLength(const char *str)
  50. {
  51. int i = atoi(str);
  52. const char *p;
  53. if ((p=strstr(str,":")))
  54. {
  55. i*=60;
  56. i+=atoi(++p);
  57. if ((p=strstr(p,":")))
  58. {
  59. i*=60;
  60. i+=atoi(++p);
  61. }
  62. }
  63. return i;
  64. }
  65. /*
  66. our state machine
  67. &, |
  68. ----------<-------------------------<----------------------<-----------
  69. | |
  70. v ID (Col) =, >, <... ID / Data / [f] ) |
  71. ---->(0) ----->-----> (1) ------>-----> (2) ------>------> (3) ------>-----> (4) <--
  72. | |^ \isempty------------->------------/ |^ | |
  73. | !( || ||---- | ) |
  74. --<-- ---------<---------------------------<-------------<-| | -->--
  75. &, | v [f] |
  76. -->--
  77. */
  78. //---------------------------------------------------------------------------
  79. bool Scanner::Query_Parse(const char *query)
  80. {
  81. const char *p = query; // pointer on next token to read
  82. int size;
  83. int state = 0;
  84. int pcount = 0;
  85. VListEntry<OpLevel> *entry;
  86. if (pstack.GetNElements() > 0)
  87. Query_CleanUp();
  88. while (1)
  89. {
  90. p = Query_EatSpace(p);
  91. int t = Query_GetNextToken(p, &size, &token);
  92. if (t == TOKEN_UNKNOWN)
  93. {
  94. Query_SyntaxError((int)(p-query));
  95. return false;
  96. }
  97. if (t == TOKEN_EOQ)
  98. break;
  99. switch (state)
  100. {
  101. case 0:
  102. switch (t)
  103. {
  104. case TOKEN_PAROPEN:
  105. state = 0;
  106. // check too many parenthesis open
  107. if (pcount == 255)
  108. {
  109. Query_SyntaxError((int)(p-query)); // should not be _syntax_ error
  110. return false;
  111. }
  112. // up one level
  113. pcount++;
  114. break;
  115. case TOKEN_NOT:
  116. // push not in this level
  117. OpLevel o;
  118. o.Op = FILTER_NOT;
  119. o.Level = pcount;
  120. entry = new VListEntry<OpLevel>;
  121. entry->SetVal(o);
  122. pstack.AddEntry(entry, true);
  123. state = 0;
  124. break;
  125. case TOKEN_IDENTIFIER:
  126. state = 1;
  127. // create filter column
  128. if (AddFilterByName(token, NULL, FILTER_NONE) == ADDFILTER_FAILED)
  129. {
  130. Query_SyntaxError((int)(p-query));
  131. return false;
  132. }
  133. break;
  134. default:
  135. Query_SyntaxError((int)(p-query));
  136. return false;
  137. }
  138. break;
  139. case 1:
  140. switch (t)
  141. {
  142. case TOKEN_EQUAL:
  143. {
  144. state = 2;
  145. // set filter op
  146. Filter *f = GetLastFilter();
  147. f->SetOp(FILTER_EQUALS);
  148. break;
  149. }
  150. case TOKEN_ABOVE:
  151. {
  152. state = 2;
  153. // set filter op
  154. Filter *f = GetLastFilter();
  155. f->SetOp(FILTER_ABOVE);
  156. break;
  157. }
  158. case TOKEN_BELOW:
  159. {
  160. state = 2;
  161. // set filter op
  162. Filter *f = GetLastFilter();
  163. f->SetOp(FILTER_BELOW);
  164. break;
  165. }
  166. case TOKEN_CONTAINS:
  167. {
  168. state = 2;
  169. // set filter op
  170. Filter *f = GetLastFilter();
  171. f->SetOp(FILTER_CONTAINS);
  172. break;
  173. }
  174. case TOKEN_NOTCONTAINS:
  175. {
  176. state = 2;
  177. // set filter op
  178. Filter *f = GetLastFilter();
  179. f->SetOp(FILTER_NOTCONTAINS);
  180. break;
  181. }
  182. case TOKEN_AOREQUAL:
  183. {
  184. state = 2;
  185. // set filter op
  186. Filter *f = GetLastFilter();
  187. f->SetOp(FILTER_ABOVEOREQUAL);
  188. break;
  189. }
  190. case TOKEN_BOREQUAL:
  191. {
  192. state = 2;
  193. // set filter op
  194. Filter *f = GetLastFilter();
  195. f->SetOp(FILTER_BELOWOREQUAL);
  196. break;
  197. }
  198. case TOKEN_NOTEQUAL:
  199. {
  200. state = 2;
  201. // set filter op
  202. Filter *f = GetLastFilter();
  203. f->SetOp(FILTER_NOTEQUALS);
  204. break;
  205. }
  206. case TOKEN_BEGINS:
  207. {
  208. state = 2;
  209. Filter *f = GetLastFilter();
  210. f->SetOp(FILTER_BEGINS);
  211. }
  212. break;
  213. case TOKEN_ENDS:
  214. {
  215. state = 2;
  216. Filter *f = GetLastFilter();
  217. f->SetOp(FILTER_ENDS);
  218. }
  219. break;
  220. case TOKEN_LIKE:
  221. {
  222. state = 2;
  223. // set filter op
  224. Filter *f = GetLastFilter();
  225. f->SetOp(FILTER_LIKE);
  226. break;
  227. }
  228. case TOKEN_BEGINSLIKE:
  229. {
  230. state = 2;
  231. // set filter op
  232. Filter *f = GetLastFilter();
  233. f->SetOp(FILTER_BEGINSLIKE);
  234. break;
  235. }
  236. case TOKEN_ISNOTEMPTY:
  237. case TOKEN_ISEMPTY:
  238. {
  239. state = 3;
  240. Filter *f = GetLastFilter();
  241. f->SetOp(t==TOKEN_ISEMPTY ? FILTER_ISEMPTY : FILTER_ISNOTEMPTY);
  242. // pop all operators in this level beginning by the last inserted
  243. entry = (VListEntry<OpLevel> *)pstack.GetFoot();
  244. while (entry)
  245. {
  246. if (entry->GetVal().Level == pcount)
  247. {
  248. AddFilterOp(entry->GetVal().Op);
  249. VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
  250. pstack.RemoveEntry(entry);
  251. entry = _entry;
  252. }
  253. else
  254. break;
  255. }
  256. }
  257. break;
  258. default:
  259. Query_SyntaxError((int)(p-query));
  260. return false;
  261. }
  262. break;
  263. case 2:
  264. if (t == TOKEN_SQBRACKETOPEN)
  265. {
  266. state = 3;
  267. const char *s = strchr(p, ']');
  268. if (!s)
  269. {
  270. Query_SyntaxError((int)(p-query));
  271. return false;
  272. }
  273. p = Query_EatSpace(p);
  274. if (*p == '[') p++;
  275. char *format = ndestring_malloc((s-p+1)*sizeof(char));
  276. strncpy(format, p, s-p);
  277. format[s-p] = 0;
  278. Filter *f = GetLastFilter();
  279. int id = f->GetId();
  280. ColumnField *c = GetColumnById(id);
  281. int tt = c ? c->GetDataType() : -1;
  282. if (disable_date_resolution || !c || (tt != FIELD_INTEGER && tt != FIELD_DATETIME && tt != FIELD_LENGTH && tt != FIELD_BOOLEAN))
  283. {
  284. if (disable_date_resolution)
  285. {
  286. StringField *field = (StringField *)f->Data();
  287. if (!field)
  288. {
  289. // format was used without a value, assume value is 0
  290. f->SetData(new StringField(""));
  291. entry = (VListEntry<OpLevel> *)pstack.GetFoot();
  292. while (entry)
  293. {
  294. if (entry->GetVal().Level == pcount)
  295. {
  296. AddFilterOp(entry->GetVal().Op);
  297. VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
  298. pstack.RemoveEntry(entry);
  299. entry = _entry;
  300. }
  301. else
  302. break;
  303. }
  304. field = (StringField*)f->Data();
  305. }
  306. field->SetNDEString(format);
  307. ndestring_release(format);
  308. p = s+1;
  309. continue;
  310. }
  311. ndestring_release(format);
  312. Query_SyntaxError((int)(p-query));
  313. return false;
  314. }
  315. IntegerField *field = (IntegerField *)f->Data();
  316. if (!field)
  317. {
  318. // format was used without a value, assume value is 0
  319. f->SetData(new IntegerField(0));
  320. entry = (VListEntry<OpLevel> *)pstack.GetFoot();
  321. while (entry)
  322. {
  323. if (entry->GetVal().Level == pcount)
  324. {
  325. AddFilterOp(entry->GetVal().Op);
  326. VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
  327. pstack.RemoveEntry(entry);
  328. entry = _entry;
  329. }
  330. else
  331. break;
  332. }
  333. field = (IntegerField *)f->Data();
  334. }
  335. int r = field->ApplyConversion(format);
  336. ndestring_release(format);
  337. if (!r)
  338. {
  339. Query_SyntaxError((int)(p-query));
  340. return false;
  341. }
  342. p = s+1;
  343. continue;
  344. }
  345. // switch (t) {
  346. // case TOKEN_IDENTIFIER:
  347. else // JF> we make this relaxed, so anything is valid as a value
  348. {
  349. state = 3;
  350. // set filter data
  351. Filter *f = GetLastFilter();
  352. int id = f->GetId();
  353. ColumnField *c = GetColumnById(id);
  354. switch (c ? c->GetDataType() : -1)
  355. {
  356. case FIELD_DATETIME:
  357. if (disable_date_resolution)
  358. goto field_string_override;
  359. case FIELD_LENGTH:
  360. {
  361. int i;
  362. IntegerField *i_f = new IntegerField();
  363. i = Query_ParseLength(token);
  364. i_f->SetValue(i);
  365. f->SetData(i_f);
  366. }
  367. break;
  368. case FIELD_BOOLEAN:
  369. case FIELD_INTEGER:
  370. {
  371. int i;
  372. IntegerField *i_f = new IntegerField();
  373. i = atoi(token);
  374. i_f->SetValue(i);
  375. f->SetData(i_f);
  376. }
  377. break;
  378. case FIELD_INT64:
  379. {
  380. int64_t i;
  381. Int64Field *i_f = new Int64Field();
  382. i = strtoull(token, 0, 10); // todo: Replace with own conversion and error checking
  383. i_f->SetValue(i);
  384. f->SetData(i_f);
  385. }
  386. break;
  387. case FIELD_FILENAME:
  388. {
  389. FilenameField *s_f = new FilenameField();
  390. s_f->SetNDEString(token);
  391. f->SetData(s_f);
  392. }
  393. break;
  394. case FIELD_STRING:
  395. field_string_override:
  396. {
  397. StringField *s_f = new StringField();
  398. s_f->SetNDEString(token);
  399. f->SetData(s_f);
  400. }
  401. break;
  402. default:
  403. Query_SyntaxError((int)(p-query));
  404. return false;
  405. break;
  406. }
  407. // pop all operators in this level beginning by the last inserted
  408. entry = (VListEntry<OpLevel> *)pstack.GetFoot();
  409. while (entry)
  410. {
  411. if (entry->GetVal().Level == pcount)
  412. {
  413. AddFilterOp(entry->GetVal().Op);
  414. VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
  415. pstack.RemoveEntry(entry);
  416. entry = _entry;
  417. }
  418. else
  419. break;
  420. }
  421. break;
  422. }
  423. // default:
  424. // Query_SyntaxError(p-query);
  425. // return false;
  426. // }
  427. break;
  428. case 3:
  429. switch (t)
  430. {
  431. case TOKEN_SQBRACKETOPEN:
  432. {
  433. const char *s = strchr(p, ']');
  434. if (!s)
  435. {
  436. Query_SyntaxError((int)(p-query));
  437. return false;
  438. }
  439. p = Query_EatSpace(p);
  440. if (*p == '[') p++;
  441. char *format = ndestring_malloc((s-p+1)*sizeof(char));
  442. strncpy(format, p, s-p);
  443. format[s-p] = 0;
  444. Filter *f = GetLastFilter();
  445. int id = f->GetId();
  446. ColumnField *c = GetColumnById(id);
  447. int tt = c ? c->GetDataType() : -1;
  448. if (disable_date_resolution || !c || (tt != FIELD_INTEGER && tt != FIELD_DATETIME && tt != FIELD_LENGTH && tt != FIELD_BOOLEAN))
  449. {
  450. if (disable_date_resolution)
  451. {
  452. StringField *field = (StringField *)f->Data();
  453. if (!field)
  454. {
  455. // format was used without a value, assume value is 0
  456. f->SetData(new StringField(""));
  457. entry = (VListEntry<OpLevel> *)pstack.GetFoot();
  458. while (entry)
  459. {
  460. if (entry->GetVal().Level == pcount)
  461. {
  462. AddFilterOp(entry->GetVal().Op);
  463. VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
  464. pstack.RemoveEntry(entry);
  465. entry = _entry;
  466. }
  467. else
  468. break;
  469. }
  470. field = (StringField *)f->Data();
  471. }
  472. field->SetNDEString(format);
  473. ndestring_release(format);
  474. p = s+1;
  475. continue;
  476. }
  477. ndestring_release(format);
  478. Query_SyntaxError((int)(p-query));
  479. return false;
  480. }
  481. IntegerField *field = (IntegerField *)f->Data();
  482. if (!field)
  483. {
  484. // format was used without a value, assume value is 0
  485. f->SetData(new IntegerField(0));
  486. entry = (VListEntry<OpLevel> *)pstack.GetFoot();
  487. while (entry)
  488. {
  489. if (entry->GetVal().Level == pcount)
  490. {
  491. AddFilterOp(entry->GetVal().Op);
  492. VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
  493. pstack.RemoveEntry(entry);
  494. entry = _entry;
  495. }
  496. else
  497. break;
  498. }
  499. field = (IntegerField *)f->Data();
  500. }
  501. int r = field->ApplyConversion(format);
  502. ndestring_release(format);
  503. if (!r)
  504. {
  505. Query_SyntaxError((int)(p-query));
  506. return false;
  507. }
  508. p = s+1;
  509. continue;
  510. }
  511. break;
  512. case TOKEN_PARCLOSE:
  513. state = 4;
  514. // check parenthesis count
  515. if (pcount == 0)
  516. {
  517. Query_SyntaxError((int)(p-query));
  518. return false;
  519. }
  520. // down one level
  521. pcount--;
  522. // pop all operators in this level, beginning by the last inserted
  523. while (entry)
  524. {
  525. if (entry->GetVal().Level == pcount)
  526. {
  527. AddFilterOp(entry->GetVal().Op);
  528. VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
  529. pstack.RemoveEntry(entry);
  530. entry = _entry;
  531. }
  532. else
  533. break;
  534. }
  535. break;
  536. case TOKEN_AND:
  537. {
  538. state = 0;
  539. // push and
  540. OpLevel o;
  541. o.Op = FILTER_AND;
  542. o.Level = pcount;
  543. entry = new VListEntry<OpLevel>;
  544. entry->SetVal(o);
  545. pstack.AddEntry(entry, true);
  546. break;
  547. }
  548. case TOKEN_OR:
  549. {
  550. state = 0;
  551. // push or
  552. OpLevel o;
  553. o.Op = FILTER_OR;
  554. o.Level = pcount;
  555. entry = new VListEntry<OpLevel>;
  556. entry->SetVal(o);
  557. pstack.AddEntry(entry, true);
  558. break;
  559. }
  560. default:
  561. Query_SyntaxError((int)(p-query));
  562. return false;
  563. }
  564. break;
  565. case 4:
  566. switch (t)
  567. {
  568. case TOKEN_AND:
  569. {
  570. state = 0;
  571. // push and
  572. OpLevel o;
  573. o.Op = FILTER_AND;
  574. o.Level = pcount;
  575. entry = new VListEntry<OpLevel>;
  576. entry->SetVal(o);
  577. pstack.AddEntry(entry, true);
  578. break;
  579. }
  580. case TOKEN_OR:
  581. {
  582. state = 0;
  583. // push or
  584. OpLevel o;
  585. o.Op = FILTER_OR;
  586. o.Level = pcount;
  587. entry = new VListEntry<OpLevel>;
  588. entry->SetVal(o);
  589. pstack.AddEntry(entry, true);
  590. break;
  591. }
  592. case TOKEN_PARCLOSE:
  593. state = 4;
  594. // check parenthesis count
  595. if (pcount == 0)
  596. {
  597. Query_SyntaxError((int)(p-query));
  598. return false;
  599. }
  600. // down one level
  601. pcount--;
  602. // pop all operators in this level, beginning by the last inserted
  603. while (entry)
  604. {
  605. if (entry->GetVal().Level == pcount)
  606. {
  607. AddFilterOp(entry->GetVal().Op);
  608. VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
  609. pstack.RemoveEntry(entry);
  610. entry = _entry;
  611. }
  612. else
  613. break;
  614. }
  615. break;
  616. default:
  617. Query_SyntaxError((int)(p-query));
  618. return false;
  619. }
  620. break;
  621. default:
  622. // Ahem... :/
  623. break;
  624. }
  625. p += size;
  626. }
  627. if (pcount > 0)
  628. {
  629. Query_SyntaxError((int)(p-query));
  630. return false;
  631. }
  632. return true;
  633. }
  634. //---------------------------------------------------------------------------
  635. void Scanner::Query_SyntaxError(int c)
  636. {
  637. }
  638. //---------------------------------------------------------------------------
  639. void Scanner::Query_CleanUp()
  640. {
  641. while (pstack.GetNElements() > 0)
  642. {
  643. VListEntry<int> *e;
  644. e = (VListEntry<int> *)pstack.GetHead();
  645. pstack.RemoveEntry(e);
  646. }
  647. }
  648. //---------------------------------------------------------------------------
  649. const char *Scanner::Query_EatSpace(const char *p)
  650. {
  651. while (*p && *p == ' ') p++;
  652. return p;
  653. }
  654. //---------------------------------------------------------------------------
  655. const char *Scanner::Query_ProbeNonAlphaNum(const char *p)
  656. {
  657. int inquote=0;
  658. while (*p && (!Query_isControlChar(*p) || (inquote)))
  659. {
  660. if (*p == '\"')
  661. {
  662. if (!inquote)
  663. inquote = 1;
  664. else
  665. return p+1;
  666. }
  667. p++;
  668. }
  669. return p;
  670. }
  671. //---------------------------------------------------------------------------
  672. int Scanner::Query_isControlChar(char p)
  673. {
  674. switch (p)
  675. {
  676. case '&':
  677. case '|':
  678. case '!':
  679. case '(':
  680. case '[':
  681. case ')':
  682. case ']':
  683. case '>':
  684. case '<':
  685. case '=':
  686. case ',':
  687. case ' ':
  688. return true;
  689. }
  690. return false;
  691. }
  692. //---------------------------------------------------------------------------
  693. char *Scanner::Query_ProbeAlphaNum(char *p)
  694. {
  695. while (*p && Query_isControlChar(*p)) p++;
  696. return p;
  697. }
  698. //---------------------------------------------------------------------------
  699. char *Scanner::Query_ProbeSpace(char *p)
  700. {
  701. while (*p && *p != ' ') p++;
  702. return p;
  703. }
  704. //---------------------------------------------------------------------------
  705. int Scanner::Query_LookupToken(const char *t)
  706. {
  707. for (int i=0;i<sizeof(Tokens)/sizeof(tokenstruct);i++)
  708. {
  709. if (!_stricmp(Tokens[i].token, t))
  710. return Tokens[i].tid;
  711. }
  712. return TOKEN_IDENTIFIER;
  713. }
  714. //---------------------------------------------------------------------------
  715. int Scanner::Query_GetNextToken(const char *p, int *size, char **_token, int tokentable)
  716. {
  717. int t = TOKEN_EOQ;
  718. const char *startptr = p;
  719. if (!*p) return TOKEN_EOQ;
  720. p = Query_EatSpace(p);
  721. const char *e = Query_ProbeNonAlphaNum(p);
  722. if (e != p) // We have a word
  723. {
  724. size_t token_length = e-p;
  725. if (*_token) ndestring_release(*_token);
  726. *_token = ndestring_wcsndup(p, token_length);
  727. if (*(*_token) == '\"' && (*_token)[token_length-1] == '\"') // check for quoted string
  728. {
  729. size_t l=token_length-2;
  730. if (l>0)
  731. {
  732. memcpy(*_token,(*_token)+1,l*sizeof(char));
  733. (*_token)[l]=0;
  734. Query_Unescape(*_token);
  735. }
  736. else
  737. (*_token)[0]=0;// we have an empty string
  738. }
  739. switch (tokentable)
  740. {
  741. case -1:
  742. t = TOKEN_IDENTIFIER;
  743. break;
  744. case 0:
  745. t = Query_LookupToken(*_token);
  746. break;
  747. case 1:
  748. t = IntegerField::LookupToken(*_token);
  749. }
  750. p = e;
  751. }
  752. else // We have a symbol
  753. {
  754. switch (*p)
  755. {
  756. case '&':
  757. if (*(p+1) == '&') p++;
  758. t = TOKEN_AND;
  759. break;
  760. case '|':
  761. if (*(p+1) == '|') p++;
  762. t = TOKEN_OR;
  763. break;
  764. case '!':
  765. if (*(p+1) == '=')
  766. {
  767. p++;
  768. t = TOKEN_NOTEQUAL;
  769. break;
  770. }
  771. t = TOKEN_NOT;
  772. break;
  773. case '(':
  774. t = TOKEN_PAROPEN;
  775. break;
  776. case ')':
  777. t = TOKEN_PARCLOSE;
  778. break;
  779. case '[':
  780. t = TOKEN_SQBRACKETOPEN;
  781. break;
  782. case ']':
  783. t = TOKEN_SQBRACKETCLOSE;
  784. break;
  785. case ',':
  786. t = TOKEN_COMMA;
  787. break;
  788. case '>':
  789. if (*(p+1) == '=')
  790. {
  791. p++;
  792. t = TOKEN_AOREQUAL;
  793. break;
  794. }
  795. if (*(p+1) == '<')
  796. {
  797. p++;
  798. t = TOKEN_NOTEQUAL;
  799. break;
  800. }
  801. t = TOKEN_ABOVE;
  802. break;
  803. case '<':
  804. if (*(p+1) == '=')
  805. {
  806. p++;
  807. t = TOKEN_BOREQUAL;
  808. break;
  809. }
  810. if (*(p+1) == '>')
  811. {
  812. p++;
  813. t = TOKEN_NOTEQUAL;
  814. break;
  815. }
  816. t = TOKEN_BELOW;
  817. break;
  818. case '=':
  819. if (*(p+1) == '>')
  820. {
  821. p++;
  822. t = TOKEN_AOREQUAL;
  823. break;
  824. }
  825. if (*(p+1) == '<')
  826. {
  827. p++;
  828. t = TOKEN_BOREQUAL;
  829. break;
  830. }
  831. if (*(p+1) == '!')
  832. {
  833. p++;
  834. t = TOKEN_NOTEQUAL;
  835. break;
  836. }
  837. if (*(p+1) == '=') p++;
  838. t = TOKEN_EQUAL;
  839. break;
  840. default:
  841. t = TOKEN_UNKNOWN;
  842. break;
  843. }
  844. p++;
  845. }
  846. *size = (int)(p - startptr);
  847. return t;
  848. }
  849. static uint8_t quickhex(char c)
  850. {
  851. int hexvalue = c;
  852. if (hexvalue & 0x10)
  853. hexvalue &= ~0x30;
  854. else
  855. {
  856. hexvalue &= 0xF;
  857. hexvalue += 9;
  858. }
  859. return hexvalue;
  860. }
  861. static uint8_t DecodeEscape(const char *&str)
  862. {
  863. uint8_t a = quickhex(*++str);
  864. uint8_t b = quickhex(*++str);
  865. str++;
  866. return a * 16 + b;
  867. }
  868. static void DecodeEscapedUTF8(char *&output, const char *&input)
  869. {
  870. bool error=false;
  871. while (*input == '%')
  872. {
  873. if (isxdigit(input[1]) && isxdigit(input[2]))
  874. {
  875. *output++=DecodeEscape(input);
  876. }
  877. else if (input[1] == '%')
  878. {
  879. input+=2;
  880. *output++='%';
  881. }
  882. else
  883. {
  884. error = true;
  885. break;
  886. }
  887. }
  888. if (error)
  889. {
  890. *output++ = *input++;
  891. }
  892. }
  893. // benski> We have the luxury of knowing that decoding will ALWAYS produce smaller strings
  894. // so we can do it in-place
  895. void Query_Unescape(char *str)
  896. {
  897. const char *itr = str;
  898. while (*itr)
  899. {
  900. switch (*itr)
  901. {
  902. case '%':
  903. DecodeEscapedUTF8(str, itr);
  904. break;
  905. default:
  906. *str++ = *itr++;
  907. break;
  908. }
  909. }
  910. *str = 0;
  911. }