IntegerField.cpp 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. /* ---------------------------------------------------------------------------
  2. Nullsoft Database Engine
  3. --------------------
  4. codename: Near Death Experience
  5. --------------------------------------------------------------------------- */
  6. /* ---------------------------------------------------------------------------
  7. IntegerField Class
  8. --------------------------------------------------------------------------- */
  9. #include "nde.h"
  10. #include "Query.h"
  11. #include <time.h>
  12. #ifdef _WIN32
  13. #include <malloc.h> // for alloca
  14. #endif
  15. //---------------------------------------------------------------------------
  16. IntegerField::IntegerField(int Val)
  17. {
  18. InitField();
  19. Type = FIELD_INTEGER;
  20. Value = Val;
  21. }
  22. //---------------------------------------------------------------------------
  23. void IntegerField::InitField(void)
  24. {
  25. Type = FIELD_INTEGER;
  26. Value=0;
  27. }
  28. //---------------------------------------------------------------------------
  29. IntegerField::IntegerField()
  30. {
  31. InitField();
  32. }
  33. //---------------------------------------------------------------------------
  34. IntegerField::~IntegerField()
  35. {
  36. }
  37. //---------------------------------------------------------------------------
  38. void IntegerField::ReadTypedData(const uint8_t *data, size_t len)
  39. {
  40. CHECK_INT(len);
  41. Value = *((int *)data);
  42. }
  43. //---------------------------------------------------------------------------
  44. void IntegerField::WriteTypedData(uint8_t *data, size_t len)
  45. {
  46. CHECK_INT(len);
  47. *((int *)data) = Value;
  48. }
  49. //---------------------------------------------------------------------------
  50. int IntegerField::GetValue(void)
  51. {
  52. return Value;
  53. }
  54. //---------------------------------------------------------------------------
  55. void IntegerField::SetValue(int Val)
  56. {
  57. Value = Val;
  58. }
  59. #include <limits.h>
  60. //---------------------------------------------------------------------------
  61. size_t IntegerField::GetDataSize(void)
  62. {
  63. return 4;
  64. }
  65. //---------------------------------------------------------------------------
  66. int IntegerField::Compare(Field *Entry)
  67. {
  68. if (!Entry) return -1;
  69. return GetValue() < ((IntegerField*)Entry)->GetValue() ? -1 : (GetValue() > ((IntegerField*)Entry)->GetValue() ? 1 : 0);
  70. }
  71. //---------------------------------------------------------------------------
  72. bool IntegerField::ApplyFilter(Field *Data, int op)
  73. {
  74. bool r;
  75. switch (op)
  76. {
  77. case FILTER_EQUALS:
  78. r = Value == ((IntegerField *)Data)->GetValue();
  79. break;
  80. case FILTER_NOTEQUALS:
  81. r = Value != ((IntegerField *)Data)->GetValue();
  82. break;
  83. case FILTER_NOTCONTAINS:
  84. r = (bool)!(Value & ((IntegerField *)Data)->GetValue());
  85. break;
  86. case FILTER_CONTAINS:
  87. r = !!(Value & ((IntegerField *)Data)->GetValue());
  88. break;
  89. case FILTER_ABOVE:
  90. r = (bool)(Value > ((IntegerField *)Data)->GetValue());
  91. break;
  92. case FILTER_BELOW:
  93. r = (bool)(Value < ((IntegerField *)Data)->GetValue());
  94. break;
  95. case FILTER_BELOWOREQUAL:
  96. r = (bool)(Value <= ((IntegerField *)Data)->GetValue());
  97. break;
  98. case FILTER_ABOVEOREQUAL:
  99. r = (bool)(Value >= ((IntegerField *)Data)->GetValue());
  100. break;
  101. case FILTER_ISEMPTY:
  102. r = (Value == 0 || Value == -1);
  103. break;
  104. case FILTER_ISNOTEMPTY:
  105. r = !(Value == 0 || Value == -1);
  106. break;
  107. default:
  108. r = true;
  109. break;
  110. }
  111. return r;
  112. }
  113. //---------------------------------------------------------------------------
  114. typedef struct {
  115. CFStringRef token;
  116. int tid;
  117. } tokenstruct;
  118. enum {
  119. TOKEN_AGO = 128,
  120. TOKEN_NOW,
  121. TOKEN_YESTERDAY,
  122. TOKEN_TOMORROW,
  123. TOKEN_TODAY,
  124. TOKEN_OF,
  125. TOKEN_THE,
  126. TOKEN_DATE,
  127. TOKEN_FROM,
  128. TOKEN_BEFORE,
  129. TOKEN_AFTER,
  130. TOKEN_THIS,
  131. TOKEN_SUNDAY,
  132. TOKEN_MONDAY,
  133. TOKEN_TUESDAY,
  134. TOKEN_WEDNESDAY,
  135. TOKEN_THURSDAY,
  136. TOKEN_FRIDAY,
  137. TOKEN_SATURDAY,
  138. TOKEN_MIDNIGHT,
  139. TOKEN_NOON,
  140. TOKEN_AM,
  141. TOKEN_PM,
  142. TOKEN_JANUARY,
  143. TOKEN_FEBRUARY,
  144. TOKEN_MARCH,
  145. TOKEN_APRIL,
  146. TOKEN_MAY,
  147. TOKEN_JUNE,
  148. TOKEN_JULY,
  149. TOKEN_AUGUST,
  150. TOKEN_SEPTEMBER,
  151. TOKEN_OCTOBER,
  152. TOKEN_NOVEMBER,
  153. TOKEN_DECEMBER,
  154. TOKEN_TIME,
  155. TOKEN_SECOND,
  156. TOKEN_MINUTE,
  157. TOKEN_HOUR,
  158. TOKEN_DAY,
  159. TOKEN_WEEK,
  160. TOKEN_MONTH,
  161. TOKEN_YEAR,
  162. TOKEN_AT,
  163. };
  164. tokenstruct Int_Tokens[] = { // Feel free to add more...
  165. {CFSTR("ago"), TOKEN_AGO},
  166. {CFSTR("now"), TOKEN_NOW},
  167. {CFSTR("am"), TOKEN_AM},
  168. {CFSTR("pm"), TOKEN_PM},
  169. {CFSTR("this"), TOKEN_THIS},
  170. {CFSTR("date"), TOKEN_DATE},
  171. {CFSTR("time"), TOKEN_TIME},
  172. {CFSTR("of"), TOKEN_OF},
  173. {CFSTR("at"), TOKEN_AT},
  174. {CFSTR("the"), TOKEN_THE},
  175. {CFSTR("yesterday"), TOKEN_YESTERDAY},
  176. {CFSTR("tomorrow"), TOKEN_TOMORROW},
  177. {CFSTR("today"), TOKEN_TODAY},
  178. {CFSTR("from"), TOKEN_FROM},
  179. {CFSTR("before"), TOKEN_BEFORE},
  180. {CFSTR("after"), TOKEN_AFTER},
  181. {CFSTR("past"), TOKEN_AFTER},
  182. {CFSTR("monday"), TOKEN_MONDAY},
  183. {CFSTR("mon"), TOKEN_MONDAY},
  184. {CFSTR("tuesday"), TOKEN_TUESDAY},
  185. {CFSTR("tue"), TOKEN_TUESDAY},
  186. {CFSTR("wednesday"), TOKEN_WEDNESDAY},
  187. {CFSTR("wed"), TOKEN_WEDNESDAY},
  188. {CFSTR("thursday"), TOKEN_THURSDAY},
  189. {CFSTR("thu"), TOKEN_THURSDAY},
  190. {CFSTR("friday"), TOKEN_FRIDAY},
  191. {CFSTR("fri"), TOKEN_FRIDAY},
  192. {CFSTR("saturday"), TOKEN_SATURDAY},
  193. {CFSTR("sat"), TOKEN_SATURDAY},
  194. {CFSTR("sunday"), TOKEN_SUNDAY},
  195. {CFSTR("sun"), TOKEN_SUNDAY},
  196. {CFSTR("midnight"), TOKEN_MIDNIGHT},
  197. {CFSTR("noon"), TOKEN_NOON},
  198. {CFSTR("second"), TOKEN_SECOND},
  199. {CFSTR("seconds"), TOKEN_SECOND},
  200. {CFSTR("sec"), TOKEN_SECOND},
  201. {CFSTR("s"), TOKEN_SECOND},
  202. {CFSTR("minute"), TOKEN_MINUTE},
  203. {CFSTR("minutes"), TOKEN_MINUTE},
  204. {CFSTR("min"), TOKEN_MINUTE},
  205. {CFSTR("mn"), TOKEN_MINUTE},
  206. {CFSTR("m"), TOKEN_MINUTE},
  207. {CFSTR("hour"), TOKEN_HOUR},
  208. {CFSTR("hours"), TOKEN_HOUR},
  209. {CFSTR("h"), TOKEN_HOUR},
  210. {CFSTR("day"), TOKEN_DAY},
  211. {CFSTR("days"), TOKEN_DAY},
  212. {CFSTR("d"), TOKEN_DAY},
  213. {CFSTR("week"), TOKEN_WEEK},
  214. {CFSTR("weeks"), TOKEN_WEEK},
  215. {CFSTR("w"), TOKEN_WEEK},
  216. {CFSTR("month"), TOKEN_MONTH},
  217. {CFSTR("months"), TOKEN_MONTH},
  218. {CFSTR("year"), TOKEN_YEAR},
  219. {CFSTR("years"), TOKEN_YEAR},
  220. {CFSTR("y"), TOKEN_YEAR},
  221. {CFSTR("january"), TOKEN_JANUARY},
  222. {CFSTR("jan"), TOKEN_JANUARY},
  223. {CFSTR("february"), TOKEN_FEBRUARY},
  224. {CFSTR("feb"), TOKEN_FEBRUARY},
  225. {CFSTR("march"), TOKEN_MARCH},
  226. {CFSTR("mar"), TOKEN_MARCH},
  227. {CFSTR("april"), TOKEN_APRIL},
  228. {CFSTR("apr"), TOKEN_APRIL},
  229. {CFSTR("may"), TOKEN_MAY},
  230. {CFSTR("june"), TOKEN_JUNE},
  231. {CFSTR("jun"), TOKEN_JUNE},
  232. {CFSTR("july"), TOKEN_JULY},
  233. {CFSTR("jul"), TOKEN_JULY},
  234. {CFSTR("august"), TOKEN_AUGUST},
  235. {CFSTR("aug"), TOKEN_AUGUST},
  236. {CFSTR("september"), TOKEN_SEPTEMBER},
  237. {CFSTR("sep"), TOKEN_SEPTEMBER},
  238. {CFSTR("october"), TOKEN_OCTOBER},
  239. {CFSTR("oct"), TOKEN_OCTOBER},
  240. {CFSTR("november"), TOKEN_NOVEMBER},
  241. {CFSTR("nov"), TOKEN_NOVEMBER},
  242. {CFSTR("december"), TOKEN_DECEMBER},
  243. {CFSTR("dec"), TOKEN_DECEMBER},
  244. };
  245. //---------------------------------------------------------------------------
  246. int IntegerField::LookupToken(CFStringRef t) {
  247. for (int i=0;i<sizeof(Int_Tokens)/sizeof(tokenstruct);i++) {
  248. if (CFStringCompare(Int_Tokens[i].token, t, kCFCompareCaseInsensitive) == kCFCompareEqualTo)
  249. return Int_Tokens[i].tid;
  250. }
  251. return TOKEN_IDENTIFIER;
  252. }
  253. static int isallnum(CFStringRef p)
  254. {
  255. // TODO: ideally we should cache this or create it during initialization (but need to b be careful about thread safety)
  256. CFCharacterSetRef set = CFCharacterSetCreateInvertedSet(NULL, CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit));
  257. CFRange range;
  258. Boolean ret = CFStringFindCharacterFromSet(p, set, CFRangeMake(0, CFStringGetLength(p)), 0, &range);
  259. CFRelease(set);
  260. return ret;
  261. }
  262. static bool Ends(CFStringRef str1, CFStringRef str2)
  263. {
  264. CFRange findRange = CFStringFind(str1, str2, kCFCompareCaseInsensitive|kCFCompareAnchored|kCFCompareBackwards);
  265. if (findRange.location == kCFNotFound)
  266. return false;
  267. else
  268. return findRange.location != 0;
  269. }
  270. //---------------------------------------------------------------------------
  271. int IntegerField::ApplyConversion(const char *format, TimeParse *tp) {
  272. size_t size;
  273. int value = GetValue();
  274. CFStringRef token = NULL;
  275. bool ago = false;
  276. bool from = false;
  277. bool kthis = false;
  278. int what = TOKEN_MINUTE;
  279. int lastnumber = value;
  280. if (tp) {
  281. tp->is_relative = 0;
  282. tp->offset_value = 0;
  283. tp->offset_whence = -1;
  284. tp->offset_what = -1;
  285. tp->offset_used = 0;
  286. tp->relative_year = -1;
  287. tp->relative_month = -1;
  288. tp->relative_day = -1;
  289. tp->relative_hour = -1;
  290. tp->relative_min = -1;
  291. tp->relative_sec = -1;
  292. tp->relative_kwday = -1;
  293. tp->absolute_hastime = 0;
  294. tp->absolute_hasdate = 0;
  295. }
  296. time_t now;
  297. time(&now);
  298. struct tm *o = localtime(&now);
  299. struct tm origin = *o;
  300. struct tm origin_flags = {0,0,0,0,0,0,0,0,0};
  301. struct tm onow = *o;
  302. const char *p = format;
  303. int t = -1;
  304. int lastt = -1;
  305. origin.tm_isdst = -1;
  306. while (1) {
  307. int save_lastt = lastt;
  308. lastt = t;
  309. t = Scanner::Query_GetNextToken(p, &size, &token, 1);
  310. if (t == TOKEN_EOQ) break;
  311. switch (t) {
  312. case TOKEN_THIS:
  313. kthis = true;
  314. break;
  315. case TOKEN_AGO:
  316. case TOKEN_BEFORE: // before defaults to before now (= ago)
  317. ago = true;
  318. if (tp) {
  319. tp->is_relative = 1;
  320. tp->offset_whence = 1;
  321. tp->offset_used = 1;
  322. }
  323. break;
  324. case TOKEN_AFTER: // if after, ago is discarded, coz 5 mn ago after x has no meaning, so we get it as 5 mn after x
  325. ago = false;
  326. // no break
  327. case TOKEN_FROM:
  328. from = true;
  329. if (tp) {
  330. tp->is_relative = 1;
  331. tp->offset_whence = 0;
  332. tp->offset_used = 1;
  333. }
  334. break;
  335. case TOKEN_DATE: {
  336. if (!kthis) break;
  337. kthis = false;
  338. origin.tm_year = onow.tm_year;
  339. origin_flags.tm_year = 1;
  340. origin.tm_mon = onow.tm_mon;
  341. origin_flags.tm_mon = 1;
  342. origin.tm_mday = onow.tm_mday - onow.tm_wday;
  343. origin_flags.tm_mday = 1;
  344. if (!origin_flags.tm_hour)
  345. origin.tm_hour = 0;
  346. if (!origin_flags.tm_min)
  347. origin.tm_min = 0;
  348. if (!origin_flags.tm_sec)
  349. origin.tm_sec = 0;
  350. if (tp) {
  351. tp->relative_year = -1;
  352. tp->relative_month = -1;
  353. tp->relative_day = -1;
  354. }
  355. break;
  356. }
  357. case TOKEN_TIME: {
  358. if (!kthis) break;
  359. kthis = false;
  360. origin.tm_hour = onow.tm_hour;
  361. origin_flags.tm_hour = 1;
  362. origin.tm_min = onow.tm_min;
  363. origin_flags.tm_min = 1;
  364. origin.tm_sec = onow.tm_sec;
  365. origin_flags.tm_sec = 1;
  366. if (tp) {
  367. tp->relative_sec = -1;
  368. tp->relative_min = -1;
  369. tp->relative_hour = -1;
  370. }
  371. break;
  372. }
  373. case TOKEN_SECOND:
  374. case TOKEN_MINUTE:
  375. case TOKEN_HOUR:
  376. case TOKEN_DAY:
  377. case TOKEN_WEEK:
  378. case TOKEN_MONTH:
  379. case TOKEN_YEAR:
  380. if (kthis) {
  381. kthis = false;
  382. switch (t) {
  383. case TOKEN_SECOND:
  384. origin.tm_sec = onow.tm_sec;
  385. origin_flags.tm_sec = 1;
  386. if (tp) tp->relative_sec = -1;
  387. break;
  388. case TOKEN_MINUTE:
  389. origin.tm_min = onow.tm_min;
  390. origin_flags.tm_min = 1;
  391. if (!origin_flags.tm_sec)
  392. origin.tm_sec = 0;
  393. if (tp) tp->relative_min = -1;
  394. break;
  395. case TOKEN_HOUR:
  396. origin.tm_hour = onow.tm_hour;
  397. origin_flags.tm_hour = 1;
  398. if (!origin_flags.tm_min)
  399. origin.tm_min = 0;
  400. if (!origin_flags.tm_sec)
  401. origin.tm_sec = 0;
  402. if (tp) tp->relative_hour = -1;
  403. break;
  404. case TOKEN_DAY:
  405. origin.tm_mday = onow.tm_mday;
  406. origin_flags.tm_mday = 1;
  407. if (!origin_flags.tm_hour)
  408. origin.tm_hour = 0;
  409. if (!origin_flags.tm_min)
  410. origin.tm_min = 0;
  411. if (!origin_flags.tm_sec)
  412. origin.tm_sec = 0;
  413. if (tp) tp->relative_day = -1;
  414. break;
  415. case TOKEN_WEEK:
  416. origin.tm_mday = onow.tm_mday - onow.tm_wday;
  417. origin_flags.tm_mday = 1;
  418. if (!origin_flags.tm_hour)
  419. origin.tm_hour = 0;
  420. if (!origin_flags.tm_min)
  421. origin.tm_min = 0;
  422. if (!origin_flags.tm_sec)
  423. origin.tm_sec = 0;
  424. if (tp) tp->relative_day = -2;
  425. break;
  426. case TOKEN_MONTH:
  427. origin.tm_mon = onow.tm_mon;
  428. origin_flags.tm_mon = 1;
  429. if (!origin_flags.tm_mday)
  430. origin.tm_mday = 1;
  431. if (!origin_flags.tm_hour)
  432. origin.tm_hour = 0;
  433. if (!origin_flags.tm_min)
  434. origin.tm_min = 0;
  435. if (!origin_flags.tm_sec)
  436. origin.tm_sec = 0;
  437. if (tp) tp->relative_month = -1;
  438. break;
  439. case TOKEN_YEAR:
  440. origin.tm_year = onow.tm_year;
  441. origin_flags.tm_year = 1;
  442. if (!origin_flags.tm_mon)
  443. origin.tm_mon = 0;
  444. if (!origin_flags.tm_mday)
  445. origin.tm_mday = 1;
  446. if (!origin_flags.tm_hour)
  447. origin.tm_hour = 0;
  448. if (!origin_flags.tm_min)
  449. origin.tm_min = 0;
  450. if (!origin_flags.tm_sec)
  451. origin.tm_sec = 0;
  452. if (tp) tp->relative_year = -1;
  453. break;
  454. }
  455. break;
  456. }
  457. if (lastnumber > 0) {
  458. value = lastnumber;
  459. lastnumber = 0;
  460. if (tp) tp->offset_value = value;
  461. }
  462. what = t;
  463. if (tp) {
  464. switch (what) {
  465. case TOKEN_SECOND:
  466. tp->offset_what = 6; break;
  467. case TOKEN_MINUTE:
  468. tp->offset_what = 5; break;
  469. case TOKEN_HOUR:
  470. tp->offset_what = 4; break;
  471. case TOKEN_DAY:
  472. tp->offset_what = 3; break;
  473. case TOKEN_WEEK:
  474. tp->offset_what = 2; break;
  475. case TOKEN_MONTH:
  476. tp->offset_what = 1; break;
  477. case TOKEN_YEAR:
  478. tp->offset_what = 0; break;
  479. }
  480. }
  481. break;
  482. case TOKEN_SUNDAY:
  483. case TOKEN_MONDAY:
  484. case TOKEN_TUESDAY:
  485. case TOKEN_WEDNESDAY:
  486. case TOKEN_THURSDAY:
  487. case TOKEN_FRIDAY:
  488. case TOKEN_SATURDAY: {
  489. kthis = false;
  490. int dow = t-TOKEN_MONDAY;
  491. if (dow > onow.tm_mday)
  492. origin.tm_mday = 7 - (dow - onow.tm_mday);
  493. else
  494. origin.tm_mday = dow;
  495. origin_flags.tm_mday = 1;
  496. if (!origin_flags.tm_hour)
  497. origin.tm_hour = 0;
  498. if (!origin_flags.tm_min)
  499. origin.tm_min = 0;
  500. if (!origin_flags.tm_sec)
  501. origin.tm_sec = 0;
  502. }
  503. if (tp) tp->relative_kwday = t-TOKEN_SUNDAY;
  504. break;
  505. case TOKEN_MIDNIGHT:
  506. kthis = false;
  507. origin.tm_hour = 0;
  508. origin_flags.tm_hour = 1;
  509. if (!origin_flags.tm_min) {
  510. if (tp) tp->relative_min = 0;
  511. origin.tm_min = 0;
  512. origin_flags.tm_min = 1;
  513. }
  514. if (!origin_flags.tm_sec) {
  515. if (tp) tp->relative_sec = 0;
  516. origin.tm_sec = 0;
  517. origin_flags.tm_sec = 1;
  518. }
  519. if (tp) tp->relative_hour = 0;
  520. break;
  521. case TOKEN_NOON:
  522. kthis = false;
  523. origin.tm_hour = 12;
  524. origin_flags.tm_hour = 1;
  525. if (!origin_flags.tm_min) {
  526. if (tp) tp->relative_min = 0;
  527. origin.tm_min = 0;
  528. origin_flags.tm_min = 1;
  529. }
  530. if (!origin_flags.tm_sec) {
  531. if (tp) tp->relative_sec = 0;
  532. origin.tm_sec = 0;
  533. origin_flags.tm_sec = 1;
  534. }
  535. if (tp) tp->relative_hour = 12;
  536. break;
  537. case TOKEN_AM:
  538. kthis = false;
  539. if (lastnumber > 0) {
  540. origin.tm_hour = lastnumber;
  541. if (!origin_flags.tm_min) {
  542. if (tp) tp->relative_min = 0;
  543. origin.tm_min = 0;
  544. origin_flags.tm_min = 1;
  545. }
  546. if (!origin_flags.tm_sec) {
  547. if (tp) tp->relative_sec = 0;
  548. origin.tm_sec = 0;
  549. origin_flags.tm_sec = 1;
  550. }
  551. if (tp) tp->relative_hour = lastnumber;
  552. lastnumber = 0;
  553. } else {
  554. if (origin.tm_hour > 12) origin.tm_hour -= 12;
  555. if (tp) tp->relative_hour = origin.tm_hour;
  556. }
  557. origin_flags.tm_hour = 1;
  558. break;
  559. case TOKEN_PM:
  560. kthis = false;
  561. if (lastnumber > 0) {
  562. origin.tm_hour = lastnumber > 12 ? lastnumber : lastnumber + 12;
  563. if (!origin_flags.tm_min) {
  564. if (tp) tp->relative_min = 0;
  565. origin.tm_min = 0;
  566. origin_flags.tm_min = 1;
  567. }
  568. if (!origin_flags.tm_sec) {
  569. if (tp) tp->relative_sec = 0;
  570. origin.tm_sec = 0;
  571. origin_flags.tm_sec = 1;
  572. }
  573. if (tp) tp->relative_hour = lastnumber;
  574. lastnumber = 0;
  575. } else {
  576. if (origin.tm_hour <= 12) origin.tm_hour += 12;
  577. if (tp) tp->relative_hour = origin.tm_hour;
  578. }
  579. origin_flags.tm_hour = 1;
  580. break;
  581. case TOKEN_NOW:
  582. kthis = false;
  583. if (!origin_flags.tm_year) {
  584. if (tp) tp->relative_year = -1;
  585. origin.tm_year = onow.tm_year;
  586. }
  587. origin_flags.tm_year = 1;
  588. if (!origin_flags.tm_mon) {
  589. if (tp) tp->relative_month = -1;
  590. origin.tm_mon = onow.tm_mon;
  591. }
  592. origin_flags.tm_mon = 1;
  593. if (!origin_flags.tm_mday) {
  594. if (tp) tp->relative_day = -1;
  595. origin.tm_mday = onow.tm_mday;
  596. }
  597. origin_flags.tm_mday = 1;
  598. if (!origin_flags.tm_hour) {
  599. if (tp) tp->relative_hour = -1;
  600. origin.tm_hour = onow.tm_hour;
  601. }
  602. origin_flags.tm_hour = 1;
  603. if (!origin_flags.tm_min) {
  604. if (tp) tp->relative_min = -1;
  605. origin.tm_min = onow.tm_min;
  606. }
  607. origin_flags.tm_min = 1;
  608. if (!origin_flags.tm_sec) {
  609. if (tp) tp->relative_sec = -1;
  610. origin.tm_sec = onow.tm_sec;
  611. }
  612. break;
  613. case TOKEN_YESTERDAY:
  614. kthis = false;
  615. origin.tm_mday = onow.tm_mday - 1;
  616. origin_flags.tm_mday = 1;
  617. if (tp) tp->relative_kwday = 7;
  618. break;
  619. case TOKEN_TODAY:
  620. origin.tm_mday = onow.tm_mday;
  621. origin_flags.tm_mday = 1;
  622. if (tp) tp->relative_kwday = 8;
  623. break;
  624. case TOKEN_TOMORROW:
  625. kthis = false;
  626. origin.tm_mday = onow.tm_mday + 1;
  627. origin_flags.tm_mday = 1;
  628. if (tp) tp->relative_kwday = 9;
  629. break;
  630. case TOKEN_JANUARY:
  631. case TOKEN_FEBRUARY:
  632. case TOKEN_MARCH:
  633. case TOKEN_APRIL:
  634. case TOKEN_MAY:
  635. case TOKEN_JUNE:
  636. case TOKEN_JULY:
  637. case TOKEN_AUGUST:
  638. case TOKEN_SEPTEMBER:
  639. case TOKEN_OCTOBER:
  640. case TOKEN_NOVEMBER:
  641. case TOKEN_DECEMBER:
  642. kthis = false;
  643. if (lastnumber > 0) {
  644. origin.tm_mday = lastnumber;
  645. origin_flags.tm_mday = 1;
  646. lastnumber = 0;
  647. }
  648. origin.tm_mon = t-TOKEN_JANUARY;
  649. if (!origin_flags.tm_mday)
  650. origin.tm_mday = 1;
  651. if (!origin_flags.tm_hour)
  652. origin.tm_hour = 0;
  653. if (!origin_flags.tm_min)
  654. origin.tm_min = 0;
  655. if (!origin_flags.tm_sec)
  656. origin.tm_sec = 0;
  657. origin_flags.tm_mon = 1;
  658. if (tp) tp->relative_month = t-TOKEN_JANUARY;
  659. break;
  660. case TOKEN_IDENTIFIER:
  661. {
  662. kthis = false;
  663. // check for a year value
  664. int i = CFStringGetIntValue(token);
  665. if (i > 1970 && i < 2038 && isallnum(token)) { // max time_t range
  666. origin.tm_year = i-1900;
  667. if (!origin_flags.tm_mday)
  668. origin.tm_mday = 1;
  669. if (!origin_flags.tm_mon)
  670. origin.tm_mon = 0;
  671. if (!origin_flags.tm_hour)
  672. origin.tm_hour = 0;
  673. if (!origin_flags.tm_min)
  674. origin.tm_min = 0;
  675. if (!origin_flags.tm_sec)
  676. origin.tm_sec = 0;
  677. if (tp) tp->relative_year = i;
  678. break;
  679. }
  680. // check for 1st, 2nd, 3rd, 4th, etc.
  681. if (Ends(token, CFSTR("st")) | Ends(token, CFSTR("nd")) | Ends(token, CFSTR("rd")) | Ends(token, CFSTR("th")))
  682. {
  683. int j = CFStringGetIntValue(token);
  684. if (j >= 1 && j <= 31)
  685. {
  686. origin.tm_mday = j;
  687. origin_flags.tm_mday = 1;
  688. if (tp) tp->relative_day = j;
  689. break;
  690. }
  691. }
  692. // check for a time string (##:##:##)
  693. #ifdef _WIN32
  694. z = wcschr(token, L':');
  695. if (z)
  696. {
  697. if (tp) tp->absolute_hastime = 1;
  698. wchar_t *zz = wcschr(z+1, L':');
  699. int a, b, c=0;
  700. a = myatoi(token, (int)(z-token));
  701. if (zz && *(zz+1) == 0) zz = NULL;
  702. if (zz && !isallnum(zz+1)) zz = NULL;
  703. if (zz) { b = myatoi(z+1, (int)(zz-(z+1))); c = wcstol(zz+1,0,10); }
  704. else b = wcstol(z+1,0,10);
  705. origin.tm_hour = a;
  706. origin.tm_min = b;
  707. if (tp) {
  708. tp->relative_hour = a;
  709. tp->relative_min = b;
  710. }
  711. if (zz && !origin_flags.tm_sec) {
  712. origin.tm_sec = c;
  713. if (tp) tp->relative_sec = c;
  714. } else if (!origin_flags.tm_sec) {
  715. origin.tm_sec = 0;
  716. }
  717. origin_flags.tm_sec = 1;
  718. origin_flags.tm_hour = 1;
  719. origin_flags.tm_min = 1;
  720. break;
  721. }
  722. #else
  723. // TODO!!! maybe CFDateFormatterGetAbsoluteTimeFromString ?
  724. #endif
  725. // check for a date string in the format ##/##/##
  726. #ifdef _WIN32
  727. z = wcschr(token, L'/');
  728. if (z) {
  729. if (tp) tp->absolute_hasdate = 1;
  730. wchar_t *zz = wcschr(z+1, L'/');
  731. int a, b, c=onow.tm_year;
  732. a = myatoi(token, (int)(z-token));
  733. if (zz && !isallnum(zz+1)) zz = NULL;
  734. if (zz && *(zz+1) == 0) zz = NULL;
  735. if (zz) { b = myatoi(z+1, (int)(zz-(z+1))); c = wcstol(zz+1,0,10); }
  736. else b = _wtoi(z+1);
  737. if (b > 1969 && b < 2038) {
  738. // mm/yyyy
  739. origin.tm_year = b-1900;
  740. origin_flags.tm_year = 1;
  741. origin.tm_mon = a-1;
  742. origin_flags.tm_mon = 1;
  743. if (!origin_flags.tm_mday)
  744. origin.tm_mday = 1;
  745. if (!origin_flags.tm_hour)
  746. origin.tm_hour = 0;
  747. if (!origin_flags.tm_min)
  748. origin.tm_min = 0;
  749. if (!origin_flags.tm_sec)
  750. origin.tm_sec = 0;
  751. if (tp) {
  752. tp->relative_year = b;
  753. tp->relative_month = a-1;
  754. }
  755. } else {
  756. // mm/dd(/yy[yy])
  757. if (c < 70) c += 100;
  758. if (c > 138) c -= 1900;
  759. origin.tm_year = c;
  760. origin.tm_mon = a-1;
  761. origin.tm_mday = b == 0 ? 1 : b;
  762. origin_flags.tm_year = 1;
  763. origin_flags.tm_mon = 1;
  764. origin_flags.tm_mday = 1;
  765. if (!origin_flags.tm_hour)
  766. origin.tm_hour = 0;
  767. if (!origin_flags.tm_min)
  768. origin.tm_min = 0;
  769. if (!origin_flags.tm_sec)
  770. origin.tm_sec = 0;
  771. if (tp) {
  772. tp->relative_year = c+1900;
  773. tp->relative_month = a-1;
  774. tp->relative_day = b;
  775. }
  776. }
  777. origin_flags.tm_year = 1;
  778. origin_flags.tm_mon = 1;
  779. origin_flags.tm_mday = 1;
  780. break;
  781. }
  782. #else
  783. // TODO!!! maybe CFDateFormatterCreateDateFromString ?
  784. #endif
  785. if (isallnum(token))
  786. {
  787. lastnumber = i;
  788. switch (lastt) {
  789. case TOKEN_JANUARY:
  790. case TOKEN_FEBRUARY:
  791. case TOKEN_MARCH:
  792. case TOKEN_APRIL:
  793. case TOKEN_MAY:
  794. case TOKEN_JUNE:
  795. case TOKEN_JULY:
  796. case TOKEN_AUGUST:
  797. case TOKEN_SEPTEMBER:
  798. case TOKEN_OCTOBER:
  799. case TOKEN_NOVEMBER:
  800. case TOKEN_DECEMBER:
  801. origin.tm_mday = lastnumber;
  802. origin_flags.tm_mday = 1;
  803. lastnumber = 0;
  804. if (!origin_flags.tm_hour)
  805. origin.tm_hour = 0;
  806. if (!origin_flags.tm_min)
  807. origin.tm_min = 0;
  808. if (!origin_flags.tm_sec)
  809. origin.tm_sec = 0;
  810. if (tp) tp->relative_day = lastnumber;
  811. break;
  812. case TOKEN_AT: {
  813. origin.tm_hour = lastnumber;
  814. origin.tm_min = 0;
  815. origin.tm_sec = 0;
  816. origin_flags.tm_hour = 1;
  817. origin_flags.tm_min = 1;
  818. origin_flags.tm_sec = 1;
  819. if (tp) {
  820. tp->relative_hour = lastnumber;
  821. tp->relative_min = 0;
  822. tp->relative_sec = 0;
  823. }
  824. lastnumber = 0;
  825. break;
  826. }
  827. }
  828. }
  829. break;
  830. }
  831. default:
  832. lastt = save_lastt;
  833. break;
  834. }
  835. p += size;
  836. }
  837. if (lastnumber) {
  838. switch (lastt) {
  839. case TOKEN_JANUARY:
  840. case TOKEN_FEBRUARY:
  841. case TOKEN_MARCH:
  842. case TOKEN_APRIL:
  843. case TOKEN_MAY:
  844. case TOKEN_JUNE:
  845. case TOKEN_JULY:
  846. case TOKEN_AUGUST:
  847. case TOKEN_SEPTEMBER:
  848. case TOKEN_OCTOBER:
  849. case TOKEN_NOVEMBER:
  850. case TOKEN_DECEMBER:
  851. origin.tm_mday = lastnumber;
  852. lastnumber = 0;
  853. if (!origin_flags.tm_hour)
  854. origin.tm_hour = 0;
  855. if (!origin_flags.tm_min)
  856. origin.tm_min = 0;
  857. if (!origin_flags.tm_sec)
  858. origin.tm_sec = 0;
  859. if (tp) tp->relative_day = lastnumber;
  860. break;
  861. }
  862. }
  863. if (ago) { // if ago (or before), from is optional since if it wasn't specified we use now
  864. switch (what) {
  865. case TOKEN_SECOND:
  866. origin.tm_sec -= value;
  867. break;
  868. case TOKEN_MINUTE:
  869. origin.tm_min -= value;
  870. break;
  871. case TOKEN_HOUR:
  872. origin.tm_hour -= value;
  873. break;
  874. case TOKEN_DAY:
  875. origin.tm_mday -= value;
  876. break;
  877. case TOKEN_WEEK:
  878. origin.tm_mday -= value*7;
  879. break;
  880. case TOKEN_MONTH:
  881. origin.tm_mon -= value;
  882. break;
  883. case TOKEN_YEAR:
  884. origin.tm_year -= value;
  885. break;
  886. }
  887. time_t o = mktime(&origin);
  888. SetValue(o);
  889. if (token) CFRelease(token);
  890. if (tp) tp->absolute_datetime = GetValue();
  891. return 1;
  892. } else if (from) { // from (or after) was specified, but not ago, 5 mn from x is x + 5 mn
  893. switch (what) {
  894. case TOKEN_SECOND:
  895. origin.tm_sec += value;
  896. break;
  897. case TOKEN_MINUTE:
  898. origin.tm_min += value;
  899. break;
  900. case TOKEN_HOUR:
  901. origin.tm_hour += value;
  902. break;
  903. case TOKEN_DAY:
  904. origin.tm_mday += value;
  905. break;
  906. case TOKEN_WEEK:
  907. origin.tm_mday += value*7;
  908. break;
  909. case TOKEN_MONTH:
  910. origin.tm_mon += value;
  911. break;
  912. case TOKEN_YEAR:
  913. origin.tm_year += value;
  914. break;
  915. }
  916. time_t o = mktime(&origin);
  917. SetValue(o);
  918. if (token) CFRelease(token);
  919. if (tp) tp->absolute_datetime = GetValue();
  920. return 1;
  921. } else { // none of ago/from/before/after were specified, just make a date/time with what we got and ignore our old value
  922. time_t o = mktime(&origin);
  923. SetValue(o);
  924. if (token) CFRelease(token);
  925. if (tp) tp->absolute_datetime = GetValue();
  926. return 1;
  927. }
  928. if (token) CFRelease(token);
  929. if (tp) tp->absolute_datetime = GetValue();
  930. return 0;
  931. }
  932. //---------------------------------------------------------------------------
  933. DateTimeField::DateTimeField(int Val) : IntegerField(Val)
  934. {
  935. Type = FIELD_DATETIME;
  936. }
  937. //---------------------------------------------------------------------------
  938. DateTimeField::DateTimeField()
  939. {
  940. Type = FIELD_DATETIME;
  941. }
  942. //---------------------------------------------------------------------------
  943. DateTimeField::~DateTimeField()
  944. {
  945. }
  946. //---------------------------------------------------------------------------
  947. LengthField::LengthField(int Val) : IntegerField(Val)
  948. {
  949. Type = FIELD_LENGTH;
  950. }
  951. //---------------------------------------------------------------------------
  952. LengthField::LengthField()
  953. {
  954. Type = FIELD_LENGTH;
  955. }
  956. //---------------------------------------------------------------------------
  957. LengthField::~LengthField()
  958. {
  959. }