1012 lines
28 KiB
C++
1012 lines
28 KiB
C++
|
/* ---------------------------------------------------------------------------
|
||
|
Nullsoft Database Engine
|
||
|
--------------------
|
||
|
codename: Near Death Experience
|
||
|
--------------------------------------------------------------------------- */
|
||
|
|
||
|
/* ---------------------------------------------------------------------------
|
||
|
|
||
|
IntegerField Class
|
||
|
Windows implementation
|
||
|
|
||
|
Field data layout:
|
||
|
[4 bytes] value
|
||
|
--------------------------------------------------------------------------- */
|
||
|
|
||
|
#include "../nde.h"
|
||
|
#include "Query.h"
|
||
|
#include <time.h>
|
||
|
#include <malloc.h>
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
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 {
|
||
|
const wchar_t *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...
|
||
|
{L"ago", TOKEN_AGO},
|
||
|
{L"now", TOKEN_NOW},
|
||
|
{L"am", TOKEN_AM},
|
||
|
{L"pm", TOKEN_PM},
|
||
|
{L"this", TOKEN_THIS},
|
||
|
{L"date", TOKEN_DATE},
|
||
|
{L"time", TOKEN_TIME},
|
||
|
{L"of", TOKEN_OF},
|
||
|
{L"at", TOKEN_AT},
|
||
|
{L"the", TOKEN_THE},
|
||
|
{L"yesterday", TOKEN_YESTERDAY},
|
||
|
{L"tomorrow", TOKEN_TOMORROW},
|
||
|
{L"today", TOKEN_TODAY},
|
||
|
{L"from", TOKEN_FROM},
|
||
|
{L"before", TOKEN_BEFORE},
|
||
|
{L"after", TOKEN_AFTER},
|
||
|
{L"past", TOKEN_AFTER},
|
||
|
{L"monday", TOKEN_MONDAY},
|
||
|
{L"mon", TOKEN_MONDAY},
|
||
|
{L"tuesday", TOKEN_TUESDAY},
|
||
|
{L"tue", TOKEN_TUESDAY},
|
||
|
{L"wednesday", TOKEN_WEDNESDAY},
|
||
|
{L"wed", TOKEN_WEDNESDAY},
|
||
|
{L"thursday", TOKEN_THURSDAY},
|
||
|
{L"thu", TOKEN_THURSDAY},
|
||
|
{L"friday", TOKEN_FRIDAY},
|
||
|
{L"fri", TOKEN_FRIDAY},
|
||
|
{L"saturday", TOKEN_SATURDAY},
|
||
|
{L"sat", TOKEN_SATURDAY},
|
||
|
{L"sunday", TOKEN_SUNDAY},
|
||
|
{L"sun", TOKEN_SUNDAY},
|
||
|
{L"midnight", TOKEN_MIDNIGHT},
|
||
|
{L"noon", TOKEN_NOON},
|
||
|
{L"second", TOKEN_SECOND},
|
||
|
{L"seconds", TOKEN_SECOND},
|
||
|
{L"sec", TOKEN_SECOND},
|
||
|
{L"s", TOKEN_SECOND},
|
||
|
{L"minute", TOKEN_MINUTE},
|
||
|
{L"minutes", TOKEN_MINUTE},
|
||
|
{L"min", TOKEN_MINUTE},
|
||
|
{L"mn", TOKEN_MINUTE},
|
||
|
{L"m", TOKEN_MINUTE},
|
||
|
{L"hour", TOKEN_HOUR},
|
||
|
{L"hours", TOKEN_HOUR},
|
||
|
{L"h", TOKEN_HOUR},
|
||
|
{L"day", TOKEN_DAY},
|
||
|
{L"days", TOKEN_DAY},
|
||
|
{L"d", TOKEN_DAY},
|
||
|
{L"week", TOKEN_WEEK},
|
||
|
{L"weeks", TOKEN_WEEK},
|
||
|
{L"w", TOKEN_WEEK},
|
||
|
{L"month", TOKEN_MONTH},
|
||
|
{L"months", TOKEN_MONTH},
|
||
|
{L"year", TOKEN_YEAR},
|
||
|
{L"years", TOKEN_YEAR},
|
||
|
{L"y", TOKEN_YEAR},
|
||
|
{L"january", TOKEN_JANUARY},
|
||
|
{L"jan", TOKEN_JANUARY},
|
||
|
{L"february", TOKEN_FEBRUARY},
|
||
|
{L"feb", TOKEN_FEBRUARY},
|
||
|
{L"march", TOKEN_MARCH},
|
||
|
{L"mar", TOKEN_MARCH},
|
||
|
{L"april", TOKEN_APRIL},
|
||
|
{L"apr", TOKEN_APRIL},
|
||
|
{L"may", TOKEN_MAY},
|
||
|
{L"june", TOKEN_JUNE},
|
||
|
{L"jun", TOKEN_JUNE},
|
||
|
{L"july", TOKEN_JULY},
|
||
|
{L"jul", TOKEN_JULY},
|
||
|
{L"august", TOKEN_AUGUST},
|
||
|
{L"aug", TOKEN_AUGUST},
|
||
|
{L"september", TOKEN_SEPTEMBER},
|
||
|
{L"sep", TOKEN_SEPTEMBER},
|
||
|
{L"october", TOKEN_OCTOBER},
|
||
|
{L"oct", TOKEN_OCTOBER},
|
||
|
{L"november", TOKEN_NOVEMBER},
|
||
|
{L"nov", TOKEN_NOVEMBER},
|
||
|
{L"december", TOKEN_DECEMBER},
|
||
|
{L"dec", TOKEN_DECEMBER},
|
||
|
};
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
int IntegerField::LookupToken(const wchar_t *t) {
|
||
|
for (int i=0;i<sizeof(Int_Tokens)/sizeof(tokenstruct);i++) {
|
||
|
if (!_wcsicmp(Int_Tokens[i].token, t))
|
||
|
return Int_Tokens[i].tid;
|
||
|
}
|
||
|
return TOKEN_IDENTIFIER;
|
||
|
}
|
||
|
|
||
|
static int myatoi(const wchar_t *p, int len) {
|
||
|
wchar_t *w = (wchar_t *)_malloca((len+1)*sizeof(wchar_t));
|
||
|
wcsncpy(w, p, len);
|
||
|
w[len] = 0;
|
||
|
int a = (w ? wcstol(w, 0, 10) : 0);
|
||
|
_freea(w);
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
static int isallnum(const wchar_t *p)
|
||
|
{
|
||
|
while (p && *p) {
|
||
|
if (*p < L'0' || *p > L'9') return 0;
|
||
|
p++;
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
int IntegerField::ApplyConversion(const wchar_t *format, TimeParse *tp) {
|
||
|
int size;
|
||
|
|
||
|
int value = GetValue();
|
||
|
wchar_t *token = 0;
|
||
|
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 wchar_t *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 = wcstol(token,0,10);
|
||
|
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.
|
||
|
wchar_t *z;
|
||
|
int tokenLen=(int)wcslen(token);
|
||
|
if (tokenLen>=2)
|
||
|
{
|
||
|
z = token+tokenLen-2;
|
||
|
if (!_wcsicmp(z, L"st") || !_wcsicmp(z, L"nd") || !_wcsicmp(z, L"rd") || !_wcsicmp(z, L"th")) {
|
||
|
int j = myatoi(token, (int)(z-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 (##:##:##)
|
||
|
z = wcschr(token, L':');
|
||
|
if (z)
|
||
|
{
|
||
|
if (tp) tp->absolute_hastime = 1;
|
||
|
wchar_t *zz = wcschr(z+1, L':');
|
||
|
int a, b = 0, 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;
|
||
|
}
|
||
|
|
||
|
// check for a date string in the format ##/##/##
|
||
|
z = wcschr(token, L'/');
|
||
|
if (z) {
|
||
|
if (tp) tp->absolute_hasdate = 1;
|
||
|
wchar_t *zz = wcschr(z+1, L'/');
|
||
|
int a, b = 0, 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;
|
||
|
}
|
||
|
|
||
|
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((int)o);
|
||
|
ndestring_release(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((int)o);
|
||
|
|
||
|
ndestring_release(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((int)o);
|
||
|
|
||
|
ndestring_release(token);
|
||
|
|
||
|
if (tp) tp->absolute_datetime = GetValue();
|
||
|
return 1;
|
||
|
}
|
||
|
ndestring_release(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()
|
||
|
{
|
||
|
}
|