Simplification to the ISO8610 parser in the imnplementation of date/time

functions.

FossilOrigin-Name: b9159f42a517a95ae52464c96431708c00b7bb36
This commit is contained in:
drh 2016-01-14 19:32:46 +00:00
parent 83a2253409
commit 3349620e9e
3 changed files with 51 additions and 35 deletions

View File

@ -1,5 +1,5 @@
C Minor\sadjustments\sto\sthe\sMSVC\smakefile.
D 2016-01-14T18:01:16.348
C Simplification\sto\sthe\sISO8610\sparser\sin\sthe\simnplementation\sof\sdate/time\nfunctions.
D 2016-01-14T19:32:46.777
F Makefile.in cfa1ac03c4b414992fd53f24d978b45b0c21de55
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 2d8b2ad5a03315940bcb9e64145ab70850d66b4d
@ -288,7 +288,7 @@ F src/build.c 9d497ff4bf3c82cecb520436e0e9963785627583
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
F src/date.c e4655393bb403fa310eef66cc4583d75d4d7fd93
F src/date.c 997651e3ee6c2818fbf7fcdb7156cef9eb3ece20
F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78
F src/delete.c 00af9f08a15ddc5cba5962d3d3e5bf2d67b2e7da
F src/expr.c fe55c489362d1429c364e98c877514f4455f45a6
@ -1412,7 +1412,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 8dedff3b9ac3e6bf9c131fee19f7d26dc1ebd61f
R ed5fce327e310c7f92985b6ea8c3a0f4
U mistachkin
Z a106ef292e4f8d6ed0328b1e83183a0f
P e2cba1bbfdcb24e35b2275e29071d8a4e4943417
R 79fbdde13a17c7cb82657d609276debb
U drh
Z 2e5da468d29690cad1fa7e36751b6984

View File

@ -1 +1 @@
e2cba1bbfdcb24e35b2275e29071d8a4e4943417
b9159f42a517a95ae52464c96431708c00b7bb36

View File

@ -70,34 +70,49 @@ struct DateTime {
/*
** Convert zDate into one or more integers. Additional arguments
** come in groups of 5 as follows:
** Convert zDate into one or more integers according to the conversion
** specifier zFormat.
**
** N number of digits in the integer
** min minimum allowed value of the integer
** max maximum allowed value of the integer
** nextC first character after the integer
** pVal where to write the integers value.
** zFormat[] contains 4 characters for each integer converted, except for
** the last integer which is specified by three characters. The meaning
** of a four-character format specifiers ABCD is:
**
** A: number of digits to convert. Always "2" or "4".
** B: minimum value. Always "0" or "1".
** C: maximum value, decoded as:
** a: 12
** b: 14
** c: 24
** d: 31
** e: 59
** f: 9999
** D: the separator character, or \000 to indicate this is the
** last number to convert.
**
** Example: To translate an ISO-8601 date YYYY-MM-DD, the format would
** be "40f-21a-20c". The "40f-" indicates the 4-digit year followed by "-".
** The "21a-" indicates the 2-digit month followed by "-". The "20c" indicates
** the 2-digit day which is the last integer in the set.
**
** Conversions continue until one with nextC==0 is encountered.
** The function returns the number of successful conversions.
*/
static int getDigits(const char *zDate, ...){
static int getDigits(const char *zDate, const char *zFormat, ...){
/* The aMx[] array translates the 3rd character of each format
** spec into a max size: a b c d e f */
static const u16 aMx[] = { 12, 14, 24, 31, 59, 9999 };
va_list ap;
int val;
int N;
int min;
int max;
int nextC;
int *pVal;
int cnt = 0;
va_start(ap, zDate);
char nextC;
va_start(ap, zFormat);
do{
N = va_arg(ap, int);
min = va_arg(ap, int);
max = va_arg(ap, int);
nextC = va_arg(ap, int);
pVal = va_arg(ap, int*);
char N = zFormat[0] - '0';
char min = zFormat[1] - '0';
int val = 0;
u16 max;
assert( zFormat[2]>='a' && zFormat[2]<='f' );
max = aMx[zFormat[2] - 'a'];
nextC = zFormat[3];
val = 0;
while( N-- ){
if( !sqlite3Isdigit(*zDate) ){
@ -106,12 +121,13 @@ static int getDigits(const char *zDate, ...){
val = val*10 + *zDate - '0';
zDate++;
}
if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
if( val<(int)min || val>(int)max || (nextC!=0 && nextC!=*zDate) ){
goto end_getDigits;
}
*pVal = val;
*va_arg(ap,int*) = val;
zDate++;
cnt++;
zFormat += 4;
}while( nextC );
end_getDigits:
va_end(ap);
@ -152,7 +168,7 @@ static int parseTimezone(const char *zDate, DateTime *p){
return c!=0;
}
zDate++;
if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
if( getDigits(zDate, "20b:20e", &nHr, &nMn)!=2 ){
return 1;
}
zDate += 5;
@ -173,13 +189,13 @@ zulu_time:
static int parseHhMmSs(const char *zDate, DateTime *p){
int h, m, s;
double ms = 0.0;
if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
if( getDigits(zDate, "20c:20e", &h, &m)!=2 ){
return 1;
}
zDate += 5;
if( *zDate==':' ){
zDate++;
if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
if( getDigits(zDate, "20e", &s)!=1 ){
return 1;
}
zDate += 2;
@ -267,7 +283,7 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
}else{
neg = 0;
}
if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
if( getDigits(zDate, "40f-21a-21d", &Y, &M, &D)!=3 ){
return 1;
}
zDate += 10;