00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 module mango.convert.Rfc1123;
00041
00042 private import mango.sys.Epoch;
00043
00044 private import mango.convert.Sprint;
00045
00046 extern (C) int memcmp (char *, char *, uint);
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 class Rfc1123 : Epoch
00063 {
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 final static char[] format (char[] buffer, ulong time)
00079 {
00080
00081 if (time == InvalidEpoch)
00082 return "";
00083
00084
00085 Fields fields;
00086 fields.setUtcTime (time);
00087
00088
00089 SprintStruct sprint;
00090 sprint.ctor (buffer);
00091
00092
00093 return sprint ("%.3s, %02d %.3s %04d %02d:%02d:%02d GMT",
00094 fields.toDowName,
00095 fields.day,
00096 fields.toMonthName,
00097 fields.year,
00098 fields.hour,
00099 fields.min,
00100 fields.sec
00101 );
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 static ulong parse (char[] date, uint* ate = null)
00115 {
00116 int len;
00117 ulong value;
00118
00119 if ((len = rfc1123 (date, value)) > 0 ||
00120 (len = rfc850 (date, value)) > 0 ||
00121 (len = asctime (date, value)) > 0)
00122 {
00123 if (ate)
00124 *ate = len;
00125 return value;
00126 }
00127 return InvalidEpoch;
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 private static int rfc1123 (char[] src, inout ulong value)
00140 {
00141 Fields fields;
00142 char* p = src.ptr;
00143
00144 bool date (inout char* p)
00145 {
00146 return cast(bool)
00147 ((fields.day = parseInt(p)) > 0 &&
00148 *p++ == ' ' &&
00149 (fields.month = parseMonth(p)) > 0 &&
00150 *p++ == ' ' &&
00151 (fields.year = parseInt(p)) > 0);
00152 }
00153
00154 if (parseShortDay(p) >= 0 &&
00155 *p++ == ',' &&
00156 *p++ == ' ' &&
00157 date (p) &&
00158 *p++ == ' ' &&
00159 time (fields, p) &&
00160 *p++ == ' ' &&
00161 p[0..3] == "GMT")
00162 {
00163 value = fields.getUtcTime;
00164 return (p+3) - src.ptr;
00165 }
00166
00167 return 0;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 private static int rfc850 (char[] src, inout ulong value)
00179 {
00180 Fields fields;
00181 char* p = src.ptr;
00182
00183 bool date (inout char* p)
00184 {
00185 return cast(bool)
00186 ((fields.day = parseInt(p)) > 0 &&
00187 *p++ == '-' &&
00188 (fields.month = parseMonth(p)) > 0 &&
00189 *p++ == '-' &&
00190 (fields.year = parseInt(p)) > 0);
00191 }
00192
00193 if (parseFullDay(p) >= 0 &&
00194 *p++ == ',' &&
00195 *p++ == ' ' &&
00196 date (p) &&
00197 *p++ == ' ' &&
00198 time (fields, p) &&
00199 *p++ == ' ' &&
00200 p[0..3] == "GMT")
00201 {
00202 if (fields.year <= 70)
00203 fields.year += 2000;
00204 else
00205 if (fields.year <= 99)
00206 fields.year += 1900;
00207
00208 value = fields.getUtcTime;
00209 return (p+3) - src.ptr;
00210 }
00211
00212 return 0;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 private static int asctime (char[] src, inout ulong value)
00224 {
00225 Fields fields;
00226 char* p = src.ptr;
00227
00228 bool date (inout char* p)
00229 {
00230 return cast(bool)
00231 ((fields.month = parseMonth(p)) > 0 &&
00232 *p++ == ' ' &&
00233 ((fields.day = parseInt(p)) > 0 ||
00234 (*p++ == ' ' &&
00235 (fields.day = parseInt(p)) > 0)));
00236 }
00237
00238 if (parseShortDay(p) >= 0 &&
00239 *p++ == ' ' &&
00240 date (p) &&
00241 *p++ == ' ' &&
00242 time (fields, p) &&
00243 *p++ == ' ' &&
00244 (fields.year = parseInt (p)) > 0)
00245 {
00246 value = fields.getUtcTime;
00247 return p - src.ptr;
00248 }
00249
00250 return 0;
00251 }
00252
00253
00254
00255
00256
00257
00258
00259 private static bool time (inout Fields fields, inout char* p)
00260 {
00261 return cast(bool)
00262 ((fields.hour = parseInt(p)) > 0 &&
00263 *p++ == ':' &&
00264 (fields.min = parseInt(p)) > 0 &&
00265 *p++ == ':' &&
00266 (fields.sec = parseInt(p)) > 0);
00267 }
00268
00269
00270
00271
00272
00273
00274
00275 private static int parseMonth (inout char* p)
00276 {
00277 int month;
00278
00279 switch (p[0..3])
00280 {
00281 case "Jan":
00282 month = 1;
00283 break;
00284 case "Feb":
00285 month = 2;
00286 break;
00287 case "Mar":
00288 month = 3;
00289 break;
00290 case "Apr":
00291 month = 4;
00292 break;
00293 case "May":
00294 month = 5;
00295 break;
00296 case "Jun":
00297 month = 6;
00298 break;
00299 case "Jul":
00300 month = 7;
00301 break;
00302 case "Aug":
00303 month = 8;
00304 break;
00305 case "Sep":
00306 month = 9;
00307 break;
00308 case "Oct":
00309 month = 10;
00310 break;
00311 case "Nov":
00312 month = 11;
00313 break;
00314 case "Dec":
00315 month = 12;
00316 break;
00317 default:
00318 return month;
00319 }
00320
00321 p += 3;
00322 return month;
00323 }
00324
00325
00326
00327
00328
00329
00330
00331 private static int parseShortDay (inout char* p)
00332 {
00333 int day;
00334
00335 switch (p[0..3])
00336 {
00337 case "Sun":
00338 day = 0;
00339 break;
00340 case "Mon":
00341 day = 1;
00342 break;
00343 case "Tue":
00344 day = 2;
00345 break;
00346 case "Wed":
00347 day = 3;
00348 break;
00349 case "Thu":
00350 day = 4;
00351 break;
00352 case "Fri":
00353 day = 5;
00354 break;
00355 case "Sat":
00356 day = 6;
00357 break;
00358 default:
00359 return -1;
00360 }
00361
00362 p += 3;
00363 return day;
00364 }
00365
00366
00367
00368
00369
00370
00371
00372 private static int parseFullDay (inout char* p)
00373 {
00374 foreach (int i, char[] day; Fields.Days)
00375 if (memcmp (day, p, day.length) == 0)
00376 {
00377 p += day.length;
00378 return i;
00379 }
00380 return -1;
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390 private static int parseInt (inout char* p)
00391 {
00392 int value;
00393
00394 while (*p >= '0' && *p <= '9')
00395 value = value * 10 + *p++ - '0';
00396 return value;
00397 }
00398 }