Query.cpp 20 KB

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