aboutsummaryrefslogtreecommitdiff
path: root/Src/nde/osx/IntegerField.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/nde/osx/IntegerField.cpp')
-rw-r--r--Src/nde/osx/IntegerField.cpp1018
1 files changed, 1018 insertions, 0 deletions
diff --git a/Src/nde/osx/IntegerField.cpp b/Src/nde/osx/IntegerField.cpp
new file mode 100644
index 00000000..5fd203cc
--- /dev/null
+++ b/Src/nde/osx/IntegerField.cpp
@@ -0,0 +1,1018 @@
+/* ---------------------------------------------------------------------------
+ Nullsoft Database Engine
+ --------------------
+ codename: Near Death Experience
+ --------------------------------------------------------------------------- */
+
+/* ---------------------------------------------------------------------------
+
+ IntegerField Class
+
+ --------------------------------------------------------------------------- */
+
+#include "nde.h"
+#include "Query.h"
+#include <time.h>
+#ifdef _WIN32
+#include <malloc.h> // for alloca
+#endif
+//---------------------------------------------------------------------------
+IntegerField::IntegerField(int Val)
+{
+ InitField();
+ Type = FIELD_INTEGER;
+ Value = Val;
+}
+
+//---------------------------------------------------------------------------
+void IntegerField::InitField(void)
+{
+ Type = FIELD_INTEGER;
+ Value=0;
+}
+
+//---------------------------------------------------------------------------
+IntegerField::IntegerField()
+{
+ InitField();
+}
+
+//---------------------------------------------------------------------------
+IntegerField::~IntegerField()
+{
+}
+
+//---------------------------------------------------------------------------
+void IntegerField::ReadTypedData(const uint8_t *data, size_t len)
+{
+ CHECK_INT(len);
+ Value = *((int *)data);
+}
+
+//---------------------------------------------------------------------------
+void IntegerField::WriteTypedData(uint8_t *data, size_t len)
+{
+ CHECK_INT(len);
+ *((int *)data) = Value;
+}
+
+//---------------------------------------------------------------------------
+int IntegerField::GetValue(void)
+{
+ return Value;
+}
+
+//---------------------------------------------------------------------------
+void IntegerField::SetValue(int Val)
+{
+ Value = Val;
+}
+
+
+#include <limits.h>
+//---------------------------------------------------------------------------
+size_t IntegerField::GetDataSize(void)
+{
+ return 4;
+}
+
+//---------------------------------------------------------------------------
+int IntegerField::Compare(Field *Entry)
+{
+ if (!Entry) return -1;
+ return GetValue() < ((IntegerField*)Entry)->GetValue() ? -1 : (GetValue() > ((IntegerField*)Entry)->GetValue() ? 1 : 0);
+}
+
+//---------------------------------------------------------------------------
+bool IntegerField::ApplyFilter(Field *Data, int op)
+{
+ bool r;
+ switch (op)
+ {
+ case FILTER_EQUALS:
+ r = Value == ((IntegerField *)Data)->GetValue();
+ break;
+ case FILTER_NOTEQUALS:
+ r = Value != ((IntegerField *)Data)->GetValue();
+ break;
+ case FILTER_NOTCONTAINS:
+ r = (bool)!(Value & ((IntegerField *)Data)->GetValue());
+ break;
+ case FILTER_CONTAINS:
+ r = !!(Value & ((IntegerField *)Data)->GetValue());
+ break;
+ case FILTER_ABOVE:
+ r = (bool)(Value > ((IntegerField *)Data)->GetValue());
+ break;
+ case FILTER_BELOW:
+ r = (bool)(Value < ((IntegerField *)Data)->GetValue());
+ break;
+ case FILTER_BELOWOREQUAL:
+ r = (bool)(Value <= ((IntegerField *)Data)->GetValue());
+ break;
+ case FILTER_ABOVEOREQUAL:
+ r = (bool)(Value >= ((IntegerField *)Data)->GetValue());
+ break;
+ case FILTER_ISEMPTY:
+ r = (Value == 0 || Value == -1);
+ break;
+ case FILTER_ISNOTEMPTY:
+ r = !(Value == 0 || Value == -1);
+ break;
+ default:
+ r = true;
+ break;
+ }
+ return r;
+}
+
+//---------------------------------------------------------------------------
+typedef struct {
+ CFStringRef token;
+ int tid;
+} tokenstruct;
+
+enum {
+ TOKEN_AGO = 128,
+ TOKEN_NOW,
+ TOKEN_YESTERDAY,
+ TOKEN_TOMORROW,
+ TOKEN_TODAY,
+ TOKEN_OF,
+ TOKEN_THE,
+ TOKEN_DATE,
+ TOKEN_FROM,
+ TOKEN_BEFORE,
+ TOKEN_AFTER,
+ TOKEN_THIS,
+ TOKEN_SUNDAY,
+ TOKEN_MONDAY,
+ TOKEN_TUESDAY,
+ TOKEN_WEDNESDAY,
+ TOKEN_THURSDAY,
+ TOKEN_FRIDAY,
+ TOKEN_SATURDAY,
+
+ TOKEN_MIDNIGHT,
+ TOKEN_NOON,
+
+ TOKEN_AM,
+ TOKEN_PM,
+
+ TOKEN_JANUARY,
+ TOKEN_FEBRUARY,
+ TOKEN_MARCH,
+ TOKEN_APRIL,
+ TOKEN_MAY,
+ TOKEN_JUNE,
+ TOKEN_JULY,
+ TOKEN_AUGUST,
+ TOKEN_SEPTEMBER,
+ TOKEN_OCTOBER,
+ TOKEN_NOVEMBER,
+ TOKEN_DECEMBER,
+
+ TOKEN_TIME,
+ TOKEN_SECOND,
+ TOKEN_MINUTE,
+ TOKEN_HOUR,
+ TOKEN_DAY,
+ TOKEN_WEEK,
+ TOKEN_MONTH,
+ TOKEN_YEAR,
+ TOKEN_AT,
+};
+
+tokenstruct Int_Tokens[] = { // Feel free to add more...
+ {CFSTR("ago"), TOKEN_AGO},
+ {CFSTR("now"), TOKEN_NOW},
+ {CFSTR("am"), TOKEN_AM},
+ {CFSTR("pm"), TOKEN_PM},
+ {CFSTR("this"), TOKEN_THIS},
+ {CFSTR("date"), TOKEN_DATE},
+ {CFSTR("time"), TOKEN_TIME},
+ {CFSTR("of"), TOKEN_OF},
+ {CFSTR("at"), TOKEN_AT},
+ {CFSTR("the"), TOKEN_THE},
+ {CFSTR("yesterday"), TOKEN_YESTERDAY},
+ {CFSTR("tomorrow"), TOKEN_TOMORROW},
+ {CFSTR("today"), TOKEN_TODAY},
+ {CFSTR("from"), TOKEN_FROM},
+ {CFSTR("before"), TOKEN_BEFORE},
+ {CFSTR("after"), TOKEN_AFTER},
+ {CFSTR("past"), TOKEN_AFTER},
+ {CFSTR("monday"), TOKEN_MONDAY},
+ {CFSTR("mon"), TOKEN_MONDAY},
+ {CFSTR("tuesday"), TOKEN_TUESDAY},
+ {CFSTR("tue"), TOKEN_TUESDAY},
+ {CFSTR("wednesday"), TOKEN_WEDNESDAY},
+ {CFSTR("wed"), TOKEN_WEDNESDAY},
+ {CFSTR("thursday"), TOKEN_THURSDAY},
+ {CFSTR("thu"), TOKEN_THURSDAY},
+ {CFSTR("friday"), TOKEN_FRIDAY},
+ {CFSTR("fri"), TOKEN_FRIDAY},
+ {CFSTR("saturday"), TOKEN_SATURDAY},
+ {CFSTR("sat"), TOKEN_SATURDAY},
+ {CFSTR("sunday"), TOKEN_SUNDAY},
+ {CFSTR("sun"), TOKEN_SUNDAY},
+ {CFSTR("midnight"), TOKEN_MIDNIGHT},
+ {CFSTR("noon"), TOKEN_NOON},
+ {CFSTR("second"), TOKEN_SECOND},
+ {CFSTR("seconds"), TOKEN_SECOND},
+ {CFSTR("sec"), TOKEN_SECOND},
+ {CFSTR("s"), TOKEN_SECOND},
+ {CFSTR("minute"), TOKEN_MINUTE},
+ {CFSTR("minutes"), TOKEN_MINUTE},
+ {CFSTR("min"), TOKEN_MINUTE},
+ {CFSTR("mn"), TOKEN_MINUTE},
+ {CFSTR("m"), TOKEN_MINUTE},
+ {CFSTR("hour"), TOKEN_HOUR},
+ {CFSTR("hours"), TOKEN_HOUR},
+ {CFSTR("h"), TOKEN_HOUR},
+ {CFSTR("day"), TOKEN_DAY},
+ {CFSTR("days"), TOKEN_DAY},
+ {CFSTR("d"), TOKEN_DAY},
+ {CFSTR("week"), TOKEN_WEEK},
+ {CFSTR("weeks"), TOKEN_WEEK},
+ {CFSTR("w"), TOKEN_WEEK},
+ {CFSTR("month"), TOKEN_MONTH},
+ {CFSTR("months"), TOKEN_MONTH},
+ {CFSTR("year"), TOKEN_YEAR},
+ {CFSTR("years"), TOKEN_YEAR},
+ {CFSTR("y"), TOKEN_YEAR},
+ {CFSTR("january"), TOKEN_JANUARY},
+ {CFSTR("jan"), TOKEN_JANUARY},
+ {CFSTR("february"), TOKEN_FEBRUARY},
+ {CFSTR("feb"), TOKEN_FEBRUARY},
+ {CFSTR("march"), TOKEN_MARCH},
+ {CFSTR("mar"), TOKEN_MARCH},
+ {CFSTR("april"), TOKEN_APRIL},
+ {CFSTR("apr"), TOKEN_APRIL},
+ {CFSTR("may"), TOKEN_MAY},
+ {CFSTR("june"), TOKEN_JUNE},
+ {CFSTR("jun"), TOKEN_JUNE},
+ {CFSTR("july"), TOKEN_JULY},
+ {CFSTR("jul"), TOKEN_JULY},
+ {CFSTR("august"), TOKEN_AUGUST},
+ {CFSTR("aug"), TOKEN_AUGUST},
+ {CFSTR("september"), TOKEN_SEPTEMBER},
+ {CFSTR("sep"), TOKEN_SEPTEMBER},
+ {CFSTR("october"), TOKEN_OCTOBER},
+ {CFSTR("oct"), TOKEN_OCTOBER},
+ {CFSTR("november"), TOKEN_NOVEMBER},
+ {CFSTR("nov"), TOKEN_NOVEMBER},
+ {CFSTR("december"), TOKEN_DECEMBER},
+ {CFSTR("dec"), TOKEN_DECEMBER},
+};
+
+//---------------------------------------------------------------------------
+int IntegerField::LookupToken(CFStringRef t) {
+ for (int i=0;i<sizeof(Int_Tokens)/sizeof(tokenstruct);i++) {
+ if (CFStringCompare(Int_Tokens[i].token, t, kCFCompareCaseInsensitive) == kCFCompareEqualTo)
+ return Int_Tokens[i].tid;
+ }
+ return TOKEN_IDENTIFIER;
+}
+
+static int isallnum(CFStringRef p)
+{
+ // TODO: ideally we should cache this or create it during initialization (but need to b be careful about thread safety)
+ CFCharacterSetRef set = CFCharacterSetCreateInvertedSet(NULL, CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit));
+
+ CFRange range;
+ Boolean ret = CFStringFindCharacterFromSet(p, set, CFRangeMake(0, CFStringGetLength(p)), 0, &range);
+ CFRelease(set);
+ return ret;
+}
+
+static bool Ends(CFStringRef str1, CFStringRef str2)
+{
+
+ CFRange findRange = CFStringFind(str1, str2, kCFCompareCaseInsensitive|kCFCompareAnchored|kCFCompareBackwards);
+ if (findRange.location == kCFNotFound)
+ return false;
+ else
+ return findRange.location != 0;
+}
+
+//---------------------------------------------------------------------------
+int IntegerField::ApplyConversion(const char *format, TimeParse *tp) {
+ size_t size;
+
+ int value = GetValue();
+ CFStringRef token = NULL;
+ bool ago = false;
+ bool from = false;
+ bool kthis = false;
+ int what = TOKEN_MINUTE;
+
+ int lastnumber = value;
+
+ if (tp) {
+ tp->is_relative = 0;
+ tp->offset_value = 0;
+ tp->offset_whence = -1;
+ tp->offset_what = -1;
+ tp->offset_used = 0;
+ tp->relative_year = -1;
+ tp->relative_month = -1;
+ tp->relative_day = -1;
+ tp->relative_hour = -1;
+ tp->relative_min = -1;
+ tp->relative_sec = -1;
+ tp->relative_kwday = -1;
+ tp->absolute_hastime = 0;
+ tp->absolute_hasdate = 0;
+ }
+
+ time_t now;
+ time(&now);
+
+ struct tm *o = localtime(&now);
+ struct tm origin = *o;
+ struct tm origin_flags = {0,0,0,0,0,0,0,0,0};
+
+ struct tm onow = *o;
+
+ const char *p = format;
+ int t = -1;
+ int lastt = -1;
+
+ origin.tm_isdst = -1;
+
+ while (1) {
+ int save_lastt = lastt;
+ lastt = t;
+ t = Scanner::Query_GetNextToken(p, &size, &token, 1);
+ if (t == TOKEN_EOQ) break;
+
+ switch (t) {
+ case TOKEN_THIS:
+ kthis = true;
+ break;
+ case TOKEN_AGO:
+ case TOKEN_BEFORE: // before defaults to before now (= ago)
+ ago = true;
+ if (tp) {
+ tp->is_relative = 1;
+ tp->offset_whence = 1;
+ tp->offset_used = 1;
+ }
+ break;
+ 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
+ ago = false;
+ // no break
+ case TOKEN_FROM:
+ from = true;
+ if (tp) {
+ tp->is_relative = 1;
+ tp->offset_whence = 0;
+ tp->offset_used = 1;
+ }
+ break;
+ case TOKEN_DATE: {
+ if (!kthis) break;
+ kthis = false;
+ origin.tm_year = onow.tm_year;
+ origin_flags.tm_year = 1;
+ origin.tm_mon = onow.tm_mon;
+ origin_flags.tm_mon = 1;
+ origin.tm_mday = onow.tm_mday - onow.tm_wday;
+ origin_flags.tm_mday = 1;
+ if (!origin_flags.tm_hour)
+ origin.tm_hour = 0;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ if (tp) {
+ tp->relative_year = -1;
+ tp->relative_month = -1;
+ tp->relative_day = -1;
+ }
+ break;
+ }
+ case TOKEN_TIME: {
+ if (!kthis) break;
+ kthis = false;
+ origin.tm_hour = onow.tm_hour;
+ origin_flags.tm_hour = 1;
+ origin.tm_min = onow.tm_min;
+ origin_flags.tm_min = 1;
+ origin.tm_sec = onow.tm_sec;
+ origin_flags.tm_sec = 1;
+ if (tp) {
+ tp->relative_sec = -1;
+ tp->relative_min = -1;
+ tp->relative_hour = -1;
+ }
+ break;
+ }
+ case TOKEN_SECOND:
+ case TOKEN_MINUTE:
+ case TOKEN_HOUR:
+ case TOKEN_DAY:
+ case TOKEN_WEEK:
+ case TOKEN_MONTH:
+ case TOKEN_YEAR:
+ if (kthis) {
+ kthis = false;
+ switch (t) {
+ case TOKEN_SECOND:
+ origin.tm_sec = onow.tm_sec;
+ origin_flags.tm_sec = 1;
+ if (tp) tp->relative_sec = -1;
+ break;
+ case TOKEN_MINUTE:
+ origin.tm_min = onow.tm_min;
+ origin_flags.tm_min = 1;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ if (tp) tp->relative_min = -1;
+ break;
+ case TOKEN_HOUR:
+ origin.tm_hour = onow.tm_hour;
+ origin_flags.tm_hour = 1;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ if (tp) tp->relative_hour = -1;
+ break;
+ case TOKEN_DAY:
+ origin.tm_mday = onow.tm_mday;
+ origin_flags.tm_mday = 1;
+ if (!origin_flags.tm_hour)
+ origin.tm_hour = 0;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ if (tp) tp->relative_day = -1;
+ break;
+ case TOKEN_WEEK:
+ origin.tm_mday = onow.tm_mday - onow.tm_wday;
+ origin_flags.tm_mday = 1;
+ if (!origin_flags.tm_hour)
+ origin.tm_hour = 0;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ if (tp) tp->relative_day = -2;
+ break;
+ case TOKEN_MONTH:
+ origin.tm_mon = onow.tm_mon;
+ origin_flags.tm_mon = 1;
+ if (!origin_flags.tm_mday)
+ origin.tm_mday = 1;
+ if (!origin_flags.tm_hour)
+ origin.tm_hour = 0;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ if (tp) tp->relative_month = -1;
+ break;
+ case TOKEN_YEAR:
+ origin.tm_year = onow.tm_year;
+ origin_flags.tm_year = 1;
+ if (!origin_flags.tm_mon)
+ origin.tm_mon = 0;
+ if (!origin_flags.tm_mday)
+ origin.tm_mday = 1;
+ if (!origin_flags.tm_hour)
+ origin.tm_hour = 0;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ if (tp) tp->relative_year = -1;
+ break;
+ }
+ break;
+ }
+ if (lastnumber > 0) {
+ value = lastnumber;
+ lastnumber = 0;
+ if (tp) tp->offset_value = value;
+ }
+ what = t;
+ if (tp) {
+ switch (what) {
+ case TOKEN_SECOND:
+ tp->offset_what = 6; break;
+ case TOKEN_MINUTE:
+ tp->offset_what = 5; break;
+ case TOKEN_HOUR:
+ tp->offset_what = 4; break;
+ case TOKEN_DAY:
+ tp->offset_what = 3; break;
+ case TOKEN_WEEK:
+ tp->offset_what = 2; break;
+ case TOKEN_MONTH:
+ tp->offset_what = 1; break;
+ case TOKEN_YEAR:
+ tp->offset_what = 0; break;
+ }
+ }
+ break;
+ case TOKEN_SUNDAY:
+ case TOKEN_MONDAY:
+ case TOKEN_TUESDAY:
+ case TOKEN_WEDNESDAY:
+ case TOKEN_THURSDAY:
+ case TOKEN_FRIDAY:
+ case TOKEN_SATURDAY: {
+ kthis = false;
+ int dow = t-TOKEN_MONDAY;
+ if (dow > onow.tm_mday)
+ origin.tm_mday = 7 - (dow - onow.tm_mday);
+ else
+ origin.tm_mday = dow;
+ origin_flags.tm_mday = 1;
+ if (!origin_flags.tm_hour)
+ origin.tm_hour = 0;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ }
+ if (tp) tp->relative_kwday = t-TOKEN_SUNDAY;
+ break;
+ case TOKEN_MIDNIGHT:
+ kthis = false;
+ origin.tm_hour = 0;
+ origin_flags.tm_hour = 1;
+ if (!origin_flags.tm_min) {
+ if (tp) tp->relative_min = 0;
+ origin.tm_min = 0;
+ origin_flags.tm_min = 1;
+ }
+ if (!origin_flags.tm_sec) {
+ if (tp) tp->relative_sec = 0;
+ origin.tm_sec = 0;
+ origin_flags.tm_sec = 1;
+ }
+ if (tp) tp->relative_hour = 0;
+ break;
+ case TOKEN_NOON:
+ kthis = false;
+ origin.tm_hour = 12;
+ origin_flags.tm_hour = 1;
+ if (!origin_flags.tm_min) {
+ if (tp) tp->relative_min = 0;
+ origin.tm_min = 0;
+ origin_flags.tm_min = 1;
+ }
+ if (!origin_flags.tm_sec) {
+ if (tp) tp->relative_sec = 0;
+ origin.tm_sec = 0;
+ origin_flags.tm_sec = 1;
+ }
+ if (tp) tp->relative_hour = 12;
+ break;
+ case TOKEN_AM:
+ kthis = false;
+ if (lastnumber > 0) {
+ origin.tm_hour = lastnumber;
+ if (!origin_flags.tm_min) {
+ if (tp) tp->relative_min = 0;
+ origin.tm_min = 0;
+ origin_flags.tm_min = 1;
+ }
+ if (!origin_flags.tm_sec) {
+ if (tp) tp->relative_sec = 0;
+ origin.tm_sec = 0;
+ origin_flags.tm_sec = 1;
+ }
+ if (tp) tp->relative_hour = lastnumber;
+ lastnumber = 0;
+ } else {
+ if (origin.tm_hour > 12) origin.tm_hour -= 12;
+ if (tp) tp->relative_hour = origin.tm_hour;
+ }
+ origin_flags.tm_hour = 1;
+ break;
+ case TOKEN_PM:
+ kthis = false;
+ if (lastnumber > 0) {
+ origin.tm_hour = lastnumber > 12 ? lastnumber : lastnumber + 12;
+ if (!origin_flags.tm_min) {
+ if (tp) tp->relative_min = 0;
+ origin.tm_min = 0;
+ origin_flags.tm_min = 1;
+ }
+ if (!origin_flags.tm_sec) {
+ if (tp) tp->relative_sec = 0;
+ origin.tm_sec = 0;
+ origin_flags.tm_sec = 1;
+ }
+ if (tp) tp->relative_hour = lastnumber;
+ lastnumber = 0;
+ } else {
+ if (origin.tm_hour <= 12) origin.tm_hour += 12;
+ if (tp) tp->relative_hour = origin.tm_hour;
+ }
+ origin_flags.tm_hour = 1;
+ break;
+ case TOKEN_NOW:
+ kthis = false;
+ if (!origin_flags.tm_year) {
+ if (tp) tp->relative_year = -1;
+ origin.tm_year = onow.tm_year;
+ }
+ origin_flags.tm_year = 1;
+ if (!origin_flags.tm_mon) {
+ if (tp) tp->relative_month = -1;
+ origin.tm_mon = onow.tm_mon;
+ }
+ origin_flags.tm_mon = 1;
+ if (!origin_flags.tm_mday) {
+ if (tp) tp->relative_day = -1;
+ origin.tm_mday = onow.tm_mday;
+ }
+ origin_flags.tm_mday = 1;
+ if (!origin_flags.tm_hour) {
+ if (tp) tp->relative_hour = -1;
+ origin.tm_hour = onow.tm_hour;
+ }
+ origin_flags.tm_hour = 1;
+ if (!origin_flags.tm_min) {
+ if (tp) tp->relative_min = -1;
+ origin.tm_min = onow.tm_min;
+ }
+ origin_flags.tm_min = 1;
+ if (!origin_flags.tm_sec) {
+ if (tp) tp->relative_sec = -1;
+ origin.tm_sec = onow.tm_sec;
+ }
+ break;
+ case TOKEN_YESTERDAY:
+ kthis = false;
+ origin.tm_mday = onow.tm_mday - 1;
+ origin_flags.tm_mday = 1;
+ if (tp) tp->relative_kwday = 7;
+ break;
+ case TOKEN_TODAY:
+ origin.tm_mday = onow.tm_mday;
+ origin_flags.tm_mday = 1;
+ if (tp) tp->relative_kwday = 8;
+ break;
+ case TOKEN_TOMORROW:
+ kthis = false;
+ origin.tm_mday = onow.tm_mday + 1;
+ origin_flags.tm_mday = 1;
+ if (tp) tp->relative_kwday = 9;
+ break;
+ case TOKEN_JANUARY:
+ case TOKEN_FEBRUARY:
+ case TOKEN_MARCH:
+ case TOKEN_APRIL:
+ case TOKEN_MAY:
+ case TOKEN_JUNE:
+ case TOKEN_JULY:
+ case TOKEN_AUGUST:
+ case TOKEN_SEPTEMBER:
+ case TOKEN_OCTOBER:
+ case TOKEN_NOVEMBER:
+ case TOKEN_DECEMBER:
+ kthis = false;
+ if (lastnumber > 0) {
+ origin.tm_mday = lastnumber;
+ origin_flags.tm_mday = 1;
+ lastnumber = 0;
+ }
+ origin.tm_mon = t-TOKEN_JANUARY;
+ if (!origin_flags.tm_mday)
+ origin.tm_mday = 1;
+ if (!origin_flags.tm_hour)
+ origin.tm_hour = 0;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ origin_flags.tm_mon = 1;
+ if (tp) tp->relative_month = t-TOKEN_JANUARY;
+ break;
+ case TOKEN_IDENTIFIER:
+ {
+ kthis = false;
+
+ // check for a year value
+ int i = CFStringGetIntValue(token);
+ if (i > 1970 && i < 2038 && isallnum(token)) { // max time_t range
+ origin.tm_year = i-1900;
+ if (!origin_flags.tm_mday)
+ origin.tm_mday = 1;
+ if (!origin_flags.tm_mon)
+ origin.tm_mon = 0;
+ if (!origin_flags.tm_hour)
+ origin.tm_hour = 0;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ if (tp) tp->relative_year = i;
+ break;
+ }
+
+ // check for 1st, 2nd, 3rd, 4th, etc.
+ if (Ends(token, CFSTR("st")) | Ends(token, CFSTR("nd")) | Ends(token, CFSTR("rd")) | Ends(token, CFSTR("th")))
+ {
+ int j = CFStringGetIntValue(token);
+ if (j >= 1 && j <= 31)
+ {
+ origin.tm_mday = j;
+ origin_flags.tm_mday = 1;
+ if (tp) tp->relative_day = j;
+ break;
+ }
+ }
+
+ // check for a time string (##:##:##)
+#ifdef _WIN32
+ z = wcschr(token, L':');
+ if (z)
+ {
+ if (tp) tp->absolute_hastime = 1;
+ wchar_t *zz = wcschr(z+1, L':');
+ int a, b, c=0;
+ a = myatoi(token, (int)(z-token));
+ if (zz && *(zz+1) == 0) zz = NULL;
+ if (zz && !isallnum(zz+1)) zz = NULL;
+ if (zz) { b = myatoi(z+1, (int)(zz-(z+1))); c = wcstol(zz+1,0,10); }
+ else b = wcstol(z+1,0,10);
+ origin.tm_hour = a;
+ origin.tm_min = b;
+ if (tp) {
+ tp->relative_hour = a;
+ tp->relative_min = b;
+ }
+ if (zz && !origin_flags.tm_sec) {
+ origin.tm_sec = c;
+ if (tp) tp->relative_sec = c;
+ } else if (!origin_flags.tm_sec) {
+ origin.tm_sec = 0;
+ }
+ origin_flags.tm_sec = 1;
+ origin_flags.tm_hour = 1;
+ origin_flags.tm_min = 1;
+ break;
+ }
+#else
+ // TODO!!! maybe CFDateFormatterGetAbsoluteTimeFromString ?
+#endif
+
+ // check for a date string in the format ##/##/##
+#ifdef _WIN32
+ z = wcschr(token, L'/');
+ if (z) {
+ if (tp) tp->absolute_hasdate = 1;
+ wchar_t *zz = wcschr(z+1, L'/');
+ int a, b, c=onow.tm_year;
+ a = myatoi(token, (int)(z-token));
+ if (zz && !isallnum(zz+1)) zz = NULL;
+ if (zz && *(zz+1) == 0) zz = NULL;
+ if (zz) { b = myatoi(z+1, (int)(zz-(z+1))); c = wcstol(zz+1,0,10); }
+ else b = _wtoi(z+1);
+ if (b > 1969 && b < 2038) {
+ // mm/yyyy
+ origin.tm_year = b-1900;
+ origin_flags.tm_year = 1;
+ origin.tm_mon = a-1;
+ origin_flags.tm_mon = 1;
+ if (!origin_flags.tm_mday)
+ origin.tm_mday = 1;
+ if (!origin_flags.tm_hour)
+ origin.tm_hour = 0;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ if (tp) {
+ tp->relative_year = b;
+ tp->relative_month = a-1;
+ }
+ } else {
+ // mm/dd(/yy[yy])
+ if (c < 70) c += 100;
+ if (c > 138) c -= 1900;
+ origin.tm_year = c;
+ origin.tm_mon = a-1;
+ origin.tm_mday = b == 0 ? 1 : b;
+ origin_flags.tm_year = 1;
+ origin_flags.tm_mon = 1;
+ origin_flags.tm_mday = 1;
+ if (!origin_flags.tm_hour)
+ origin.tm_hour = 0;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ if (tp) {
+ tp->relative_year = c+1900;
+ tp->relative_month = a-1;
+ tp->relative_day = b;
+ }
+ }
+ origin_flags.tm_year = 1;
+ origin_flags.tm_mon = 1;
+ origin_flags.tm_mday = 1;
+ break;
+ }
+#else
+ // TODO!!! maybe CFDateFormatterCreateDateFromString ?
+#endif
+
+ if (isallnum(token))
+ {
+ lastnumber = i;
+ switch (lastt) {
+ case TOKEN_JANUARY:
+ case TOKEN_FEBRUARY:
+ case TOKEN_MARCH:
+ case TOKEN_APRIL:
+ case TOKEN_MAY:
+ case TOKEN_JUNE:
+ case TOKEN_JULY:
+ case TOKEN_AUGUST:
+ case TOKEN_SEPTEMBER:
+ case TOKEN_OCTOBER:
+ case TOKEN_NOVEMBER:
+ case TOKEN_DECEMBER:
+ origin.tm_mday = lastnumber;
+ origin_flags.tm_mday = 1;
+ lastnumber = 0;
+ if (!origin_flags.tm_hour)
+ origin.tm_hour = 0;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ if (tp) tp->relative_day = lastnumber;
+ break;
+ case TOKEN_AT: {
+ origin.tm_hour = lastnumber;
+ origin.tm_min = 0;
+ origin.tm_sec = 0;
+ origin_flags.tm_hour = 1;
+ origin_flags.tm_min = 1;
+ origin_flags.tm_sec = 1;
+ if (tp) {
+ tp->relative_hour = lastnumber;
+ tp->relative_min = 0;
+ tp->relative_sec = 0;
+ }
+ lastnumber = 0;
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ default:
+ lastt = save_lastt;
+ break;
+ }
+ p += size;
+ }
+
+ if (lastnumber) {
+ switch (lastt) {
+ case TOKEN_JANUARY:
+ case TOKEN_FEBRUARY:
+ case TOKEN_MARCH:
+ case TOKEN_APRIL:
+ case TOKEN_MAY:
+ case TOKEN_JUNE:
+ case TOKEN_JULY:
+ case TOKEN_AUGUST:
+ case TOKEN_SEPTEMBER:
+ case TOKEN_OCTOBER:
+ case TOKEN_NOVEMBER:
+ case TOKEN_DECEMBER:
+ origin.tm_mday = lastnumber;
+ lastnumber = 0;
+ if (!origin_flags.tm_hour)
+ origin.tm_hour = 0;
+ if (!origin_flags.tm_min)
+ origin.tm_min = 0;
+ if (!origin_flags.tm_sec)
+ origin.tm_sec = 0;
+ if (tp) tp->relative_day = lastnumber;
+ break;
+ }
+ }
+
+ if (ago) { // if ago (or before), from is optional since if it wasn't specified we use now
+ switch (what) {
+ case TOKEN_SECOND:
+ origin.tm_sec -= value;
+ break;
+ case TOKEN_MINUTE:
+ origin.tm_min -= value;
+ break;
+ case TOKEN_HOUR:
+ origin.tm_hour -= value;
+ break;
+ case TOKEN_DAY:
+ origin.tm_mday -= value;
+ break;
+ case TOKEN_WEEK:
+ origin.tm_mday -= value*7;
+ break;
+ case TOKEN_MONTH:
+ origin.tm_mon -= value;
+ break;
+ case TOKEN_YEAR:
+ origin.tm_year -= value;
+ break;
+ }
+ time_t o = mktime(&origin);
+ SetValue(o);
+ if (token) CFRelease(token);
+
+ if (tp) tp->absolute_datetime = GetValue();
+ return 1;
+ } else if (from) { // from (or after) was specified, but not ago, 5 mn from x is x + 5 mn
+ switch (what) {
+ case TOKEN_SECOND:
+ origin.tm_sec += value;
+ break;
+ case TOKEN_MINUTE:
+ origin.tm_min += value;
+ break;
+ case TOKEN_HOUR:
+ origin.tm_hour += value;
+ break;
+ case TOKEN_DAY:
+ origin.tm_mday += value;
+ break;
+ case TOKEN_WEEK:
+ origin.tm_mday += value*7;
+ break;
+ case TOKEN_MONTH:
+ origin.tm_mon += value;
+ break;
+ case TOKEN_YEAR:
+ origin.tm_year += value;
+ break;
+ }
+ time_t o = mktime(&origin);
+ SetValue(o);
+
+ if (token) CFRelease(token);
+
+ if (tp) tp->absolute_datetime = GetValue();
+ return 1;
+ } else { // none of ago/from/before/after were specified, just make a date/time with what we got and ignore our old value
+ time_t o = mktime(&origin);
+ SetValue(o);
+
+ if (token) CFRelease(token);
+
+ if (tp) tp->absolute_datetime = GetValue();
+ return 1;
+ }
+
+ if (token) CFRelease(token);
+ if (tp) tp->absolute_datetime = GetValue();
+
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+DateTimeField::DateTimeField(int Val) : IntegerField(Val)
+{
+ Type = FIELD_DATETIME;
+}
+
+//---------------------------------------------------------------------------
+DateTimeField::DateTimeField()
+{
+ Type = FIELD_DATETIME;
+}
+
+//---------------------------------------------------------------------------
+DateTimeField::~DateTimeField()
+{
+}
+
+//---------------------------------------------------------------------------
+LengthField::LengthField(int Val) : IntegerField(Val)
+{
+ Type = FIELD_LENGTH;
+}
+
+//---------------------------------------------------------------------------
+LengthField::LengthField()
+{
+ Type = FIELD_LENGTH;
+}
+
+//---------------------------------------------------------------------------
+LengthField::~LengthField()
+{
+}