Query.cpp 21 KB

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