date 0.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of date might be problematic. Click here for more details.

@@ -0,0 +1,2998 @@
1
+ /*
2
+ date_parse.c: Coded by Tadayoshi Funaba 2011,2012
3
+ */
4
+
5
+ #include "ruby.h"
6
+ #include "ruby/encoding.h"
7
+ #include "ruby/re.h"
8
+ #include <ctype.h>
9
+
10
+ RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y);
11
+ RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow);
12
+
13
+ /* #define TIGHT_PARSER */
14
+
15
+ #define sizeof_array(o) (sizeof o / sizeof o[0])
16
+
17
+ #define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
18
+ #define f_add(x,y) rb_funcall(x, '+', 1, y)
19
+ #define f_sub(x,y) rb_funcall(x, '-', 1, y)
20
+ #define f_mul(x,y) rb_funcall(x, '*', 1, y)
21
+ #define f_div(x,y) rb_funcall(x, '/', 1, y)
22
+ #define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
23
+ #define f_mod(x,y) rb_funcall(x, '%', 1, y)
24
+ #define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
25
+
26
+ #define f_lt_p(x,y) rb_funcall(x, '<', 1, y)
27
+ #define f_gt_p(x,y) rb_funcall(x, '>', 1, y)
28
+ #define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y)
29
+ #define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y)
30
+
31
+ #define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
32
+
33
+ #define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s)
34
+ #define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i)
35
+ #define f_aref2(o,i,j) rb_funcall(o, rb_intern("[]"), 2, i, j)
36
+ #define f_begin(o,i) rb_funcall(o, rb_intern("begin"), 1, i)
37
+ #define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i)
38
+ #define f_aset(o,i,v) rb_funcall(o, rb_intern("[]="), 2, i, v)
39
+ #define f_aset2(o,i,j,v) rb_funcall(o, rb_intern("[]="), 3, i, j, v)
40
+ #define f_sub_bang(s,r,x) rb_funcall(s, rb_intern("sub!"), 2, r, x)
41
+ #define f_gsub_bang(s,r,x) rb_funcall(s, rb_intern("gsub!"), 2, r, x)
42
+
43
+ #define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
44
+ #define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
45
+ #define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
46
+
47
+ #define cstr2num(s) rb_cstr_to_inum(s, 10, 0)
48
+ #define str2num(s) rb_str_to_inum(s, 10, 0)
49
+
50
+ static const char abbr_days[][4] = {
51
+ "sun", "mon", "tue", "wed",
52
+ "thu", "fri", "sat"
53
+ };
54
+
55
+ static const char abbr_months[][4] = {
56
+ "jan", "feb", "mar", "apr", "may", "jun",
57
+ "jul", "aug", "sep", "oct", "nov", "dec"
58
+ };
59
+
60
+ #define issign(c) ((c) == '-' || (c) == '+')
61
+ #define asp_string() rb_str_new(" ", 1)
62
+ #ifdef TIGHT_PARSER
63
+ #define asuba_string() rb_str_new("\001", 1)
64
+ #define asubb_string() rb_str_new("\002", 1)
65
+ #define asubw_string() rb_str_new("\027", 1)
66
+ #define asubt_string() rb_str_new("\024", 1)
67
+ #endif
68
+
69
+ #define DECDIGIT "0123456789"
70
+
71
+ static void
72
+ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
73
+ {
74
+ VALUE vbuf = 0;
75
+ VALUE c = Qnil;
76
+
77
+ if (!RB_TYPE_P(m, T_STRING))
78
+ m = f_to_s(m);
79
+
80
+ if (!NIL_P(y) && !NIL_P(m) && NIL_P(d)) {
81
+ VALUE oy = y;
82
+ VALUE om = m;
83
+ VALUE od = d;
84
+
85
+ y = od;
86
+ m = oy;
87
+ d = om;
88
+ }
89
+
90
+ if (NIL_P(y)) {
91
+ if (!NIL_P(d) && RSTRING_LEN(d) > 2) {
92
+ y = d;
93
+ d = Qnil;
94
+ }
95
+ if (!NIL_P(d) && *RSTRING_PTR(d) == '\'') {
96
+ y = d;
97
+ d = Qnil;
98
+ }
99
+ }
100
+
101
+ if (!NIL_P(y)) {
102
+ const char *s, *bp, *ep;
103
+ size_t l;
104
+
105
+ s = RSTRING_PTR(y);
106
+ while (!issign((unsigned char)*s) && !isdigit((unsigned char)*s))
107
+ s++;
108
+ bp = s;
109
+ if (issign((unsigned char)*s))
110
+ s++;
111
+ l = strspn(s, DECDIGIT);
112
+ ep = s + l;
113
+ if (*ep) {
114
+ y = d;
115
+ d = rb_str_new(bp, ep - bp);
116
+ }
117
+ }
118
+
119
+ if (!NIL_P(m)) {
120
+ const char *s;
121
+
122
+ s = RSTRING_PTR(m);
123
+ if (*s == '\'' || RSTRING_LEN(m) > 2) {
124
+ /* us -> be */
125
+ VALUE oy = y;
126
+ VALUE om = m;
127
+ VALUE od = d;
128
+
129
+ y = om;
130
+ m = od;
131
+ d = oy;
132
+ }
133
+ }
134
+
135
+ if (!NIL_P(d)) {
136
+ const char *s;
137
+
138
+ s = RSTRING_PTR(d);
139
+ if (*s == '\'' || RSTRING_LEN(d) > 2) {
140
+ VALUE oy = y;
141
+ VALUE od = d;
142
+
143
+ y = od;
144
+ d = oy;
145
+ }
146
+ }
147
+
148
+ if (!NIL_P(y)) {
149
+ const char *s, *bp, *ep;
150
+ int sign = 0;
151
+ size_t l;
152
+ VALUE iy;
153
+
154
+ s = RSTRING_PTR(y);
155
+ while (!issign((unsigned char)*s) && !isdigit((unsigned char)*s))
156
+ s++;
157
+ bp = s;
158
+ if (issign(*s)) {
159
+ s++;
160
+ sign = 1;
161
+ }
162
+ if (sign)
163
+ c = Qfalse;
164
+ l = strspn(s, DECDIGIT);
165
+ ep = s + l;
166
+ if (l > 2)
167
+ c = Qfalse;
168
+ {
169
+ char *buf;
170
+
171
+ buf = ALLOCV_N(char, vbuf, ep - bp + 1);
172
+ memcpy(buf, bp, ep - bp);
173
+ buf[ep - bp] = '\0';
174
+ iy = cstr2num(buf);
175
+ ALLOCV_END(vbuf);
176
+ }
177
+ set_hash("year", iy);
178
+ }
179
+
180
+ if (bc)
181
+ set_hash("_bc", Qtrue);
182
+
183
+ if (!NIL_P(m)) {
184
+ const char *s, *bp, *ep;
185
+ size_t l;
186
+ VALUE im;
187
+
188
+ s = RSTRING_PTR(m);
189
+ while (!isdigit((unsigned char)*s))
190
+ s++;
191
+ bp = s;
192
+ l = strspn(s, DECDIGIT);
193
+ ep = s + l;
194
+ {
195
+ char *buf;
196
+
197
+ buf = ALLOCV_N(char, vbuf, ep - bp + 1);
198
+ memcpy(buf, bp, ep - bp);
199
+ buf[ep - bp] = '\0';
200
+ im = cstr2num(buf);
201
+ ALLOCV_END(vbuf);
202
+ }
203
+ set_hash("mon", im);
204
+ }
205
+
206
+ if (!NIL_P(d)) {
207
+ const char *s, *bp, *ep;
208
+ size_t l;
209
+ VALUE id;
210
+
211
+ s = RSTRING_PTR(d);
212
+ while (!isdigit((unsigned char)*s))
213
+ s++;
214
+ bp = s;
215
+ l = strspn(s, DECDIGIT);
216
+ ep = s + l;
217
+ {
218
+ char *buf;
219
+
220
+ buf = ALLOCV_N(char, vbuf, ep - bp + 1);
221
+ memcpy(buf, bp, ep - bp);
222
+ buf[ep - bp] = '\0';
223
+ id = cstr2num(buf);
224
+ ALLOCV_END(vbuf);
225
+ }
226
+ set_hash("mday", id);
227
+ }
228
+
229
+ if (!NIL_P(c))
230
+ set_hash("_comp", c);
231
+ }
232
+
233
+ #define DAYS "sunday|monday|tuesday|wednesday|thursday|friday|saturday"
234
+ #define MONTHS "january|february|march|april|may|june|july|august|september|october|november|december"
235
+ #define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat"
236
+ #define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec"
237
+
238
+ #ifdef TIGHT_PARSER
239
+ #define VALID_DAYS "(?:" DAYS ")" "|(?:tues|wednes|thurs|thur|" ABBR_DAYS ")\\.?"
240
+ #define VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")\\.?"
241
+ #define DOTLESS_VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")"
242
+ #define BOS "\\A\\s*"
243
+ #define FPA "\\001"
244
+ #define FPB "\\002"
245
+ #define FPW "\\027"
246
+ #define FPT "\\024"
247
+ #define FPW_COM "\\s*(?:" FPW "\\s*,?)?\\s*"
248
+ #define FPT_COM "\\s*(?:" FPT "\\s*,?)?\\s*"
249
+ #define COM_FPW "\\s*(?:,?\\s*" FPW ")?\\s*"
250
+ #define COM_FPT "\\s*(?:,?\\s*(?:@|\\b[aA][tT]\\b)?\\s*" FPT ")?\\s*"
251
+ #define TEE_FPT "\\s*(?:[tT]?" FPT ")?"
252
+ #define EOS "\\s*\\z"
253
+ #endif
254
+
255
+ static VALUE
256
+ regcomp(const char *source, long len, int opt)
257
+ {
258
+ VALUE pat;
259
+
260
+ pat = rb_reg_new(source, len, opt);
261
+ rb_gc_register_mark_object(pat);
262
+ return pat;
263
+ }
264
+
265
+ #define REGCOMP(pat,opt) \
266
+ { \
267
+ if (NIL_P(pat)) \
268
+ pat = regcomp(pat##_source, sizeof pat##_source - 1, opt); \
269
+ }
270
+
271
+ #define REGCOMP_0(pat) REGCOMP(pat, 0)
272
+ #define REGCOMP_I(pat) REGCOMP(pat, ONIG_OPTION_IGNORECASE)
273
+
274
+ #define MATCH(s,p,c) \
275
+ { \
276
+ return match(s, p, hash, c); \
277
+ }
278
+
279
+ static int
280
+ match(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
281
+ {
282
+ VALUE m;
283
+
284
+ m = f_match(pat, str);
285
+
286
+ if (NIL_P(m))
287
+ return 0;
288
+
289
+ (*cb)(m, hash);
290
+
291
+ return 1;
292
+ }
293
+
294
+ static int
295
+ subx(VALUE str, VALUE rep, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
296
+ {
297
+ VALUE m;
298
+
299
+ m = f_match(pat, str);
300
+
301
+ if (NIL_P(m))
302
+ return 0;
303
+
304
+ {
305
+ VALUE be, en;
306
+
307
+ be = f_begin(m, INT2FIX(0));
308
+ en = f_end(m, INT2FIX(0));
309
+ f_aset2(str, be, LONG2NUM(NUM2LONG(en) - NUM2LONG(be)), rep);
310
+ (*cb)(m, hash);
311
+ }
312
+
313
+ return 1;
314
+ }
315
+
316
+ #define SUBS(s,p,c) \
317
+ { \
318
+ return subx(s, asp_string(), p, hash, c); \
319
+ }
320
+
321
+ #ifdef TIGHT_PARSER
322
+ #define SUBA(s,p,c) \
323
+ { \
324
+ return subx(s, asuba_string(), p, hash, c); \
325
+ }
326
+
327
+ #define SUBB(s,p,c) \
328
+ { \
329
+ return subx(s, asubb_string(), p, hash, c); \
330
+ }
331
+
332
+ #define SUBW(s,p,c) \
333
+ { \
334
+ return subx(s, asubw_string(), p, hash, c); \
335
+ }
336
+
337
+ #define SUBT(s,p,c) \
338
+ { \
339
+ return subx(s, asubt_string(), p, hash, c); \
340
+ }
341
+ #endif
342
+
343
+ #include "zonetab.h"
344
+
345
+ static int
346
+ str_end_with(const char *s, long l, const char *w)
347
+ {
348
+ int n = (int)strlen(w);
349
+ return (l >= n && strncmp(s - n, w, n) == 0);
350
+ }
351
+
352
+ VALUE
353
+ date_zone_to_diff(VALUE str)
354
+ {
355
+ VALUE offset = Qnil;
356
+ VALUE vbuf = 0;
357
+
358
+ long l, i;
359
+ char *s, *dest, *d;
360
+ int sp = 1;
361
+
362
+ l = RSTRING_LEN(str);
363
+ s = RSTRING_PTR(str);
364
+
365
+ dest = d = ALLOCV_N(char, vbuf, l + 1);
366
+
367
+ for (i = 0; i < l; i++) {
368
+ if (isspace((unsigned char)s[i]) || s[i] == '\0') {
369
+ if (!sp)
370
+ *d++ = ' ';
371
+ sp = 1;
372
+ }
373
+ else {
374
+ if (isalpha((unsigned char)s[i]))
375
+ *d++ = tolower((unsigned char)s[i]);
376
+ else
377
+ *d++ = s[i];
378
+ sp = 0;
379
+ }
380
+ }
381
+ if (d > dest) {
382
+ if (*(d - 1) == ' ')
383
+ --d;
384
+ *d = '\0';
385
+ }
386
+ l = d - dest;
387
+ s = dest;
388
+ {
389
+ static const char STD[] = " standard time";
390
+ static const char DST1[] = " daylight time";
391
+ static const char DST2[] = " dst";
392
+ int dst = 0;
393
+
394
+ if (str_end_with(d, l, STD)) {
395
+ l -= sizeof(STD) - 1;
396
+ }
397
+ else if (str_end_with(d, l, DST1)) {
398
+ l -= sizeof(DST1) - 1;
399
+ dst = 1;
400
+ }
401
+ else if (str_end_with(d, l, DST2)) {
402
+ l -= sizeof(DST2) - 1;
403
+ dst = 1;
404
+ }
405
+ {
406
+ const struct zone *z = zonetab(s, (unsigned int)l);
407
+ if (z) {
408
+ int d = z->offset;
409
+ if (dst)
410
+ d += 3600;
411
+ offset = INT2FIX(d);
412
+ goto ok;
413
+ }
414
+ }
415
+ {
416
+ char *p;
417
+ int sign = 0;
418
+ long hour = 0, min = 0, sec = 0;
419
+
420
+ if (l > 3 &&
421
+ (strncmp(s, "gmt", 3) == 0 ||
422
+ strncmp(s, "utc", 3) == 0)) {
423
+ s += 3;
424
+ l -= 3;
425
+ }
426
+ if (issign(*s)) {
427
+ sign = *s == '-';
428
+ s++;
429
+ l--;
430
+
431
+ hour = STRTOUL(s, &p, 10);
432
+ if (*p == ':') {
433
+ s = ++p;
434
+ min = STRTOUL(s, &p, 10);
435
+ if (*p == ':') {
436
+ s = ++p;
437
+ sec = STRTOUL(s, &p, 10);
438
+ }
439
+ goto num;
440
+ }
441
+ if (*p == ',' || *p == '.') {
442
+ char *e = 0;
443
+ p++;
444
+ min = STRTOUL(p, &e, 10) * 3600;
445
+ if (sign) {
446
+ hour = -hour;
447
+ min = -min;
448
+ }
449
+ offset = rb_rational_new(INT2FIX(min),
450
+ rb_int_positive_pow(10, (int)(e - p)));
451
+ offset = f_add(INT2FIX(hour * 3600), offset);
452
+ goto ok;
453
+ }
454
+ else if (l > 2) {
455
+ size_t n;
456
+ int ov;
457
+
458
+ if (l >= 1)
459
+ hour = ruby_scan_digits(&s[0], 2 - l % 2, 10, &n, &ov);
460
+ if (l >= 3)
461
+ min = ruby_scan_digits(&s[2 - l % 2], 2, 10, &n, &ov);
462
+ if (l >= 5)
463
+ sec = ruby_scan_digits(&s[4 - l % 2], 2, 10, &n, &ov);
464
+ goto num;
465
+ }
466
+ num:
467
+ sec += min * 60 + hour * 3600;
468
+ if (sign) sec = -sec;
469
+ offset = INT2FIX(sec);
470
+ }
471
+ }
472
+ }
473
+ RB_GC_GUARD(str);
474
+ ok:
475
+ ALLOCV_END(vbuf);
476
+ return offset;
477
+ }
478
+
479
+ static int
480
+ day_num(VALUE s)
481
+ {
482
+ int i;
483
+
484
+ for (i = 0; i < (int)sizeof_array(abbr_days); i++)
485
+ if (strncasecmp(abbr_days[i], RSTRING_PTR(s), 3) == 0)
486
+ break;
487
+ return i;
488
+ }
489
+
490
+ static int
491
+ mon_num(VALUE s)
492
+ {
493
+ int i;
494
+
495
+ for (i = 0; i < (int)sizeof_array(abbr_months); i++)
496
+ if (strncasecmp(abbr_months[i], RSTRING_PTR(s), 3) == 0)
497
+ break;
498
+ return i + 1;
499
+ }
500
+
501
+ static int
502
+ parse_day_cb(VALUE m, VALUE hash)
503
+ {
504
+ VALUE s;
505
+
506
+ s = rb_reg_nth_match(1, m);
507
+ set_hash("wday", INT2FIX(day_num(s)));
508
+ return 1;
509
+ }
510
+
511
+ static int
512
+ parse_day(VALUE str, VALUE hash)
513
+ {
514
+ static const char pat_source[] =
515
+ #ifndef TIGHT_PARSER
516
+ "\\b(" ABBR_DAYS ")[^-/\\d\\s]*"
517
+ #else
518
+ "(" VALID_DAYS ")"
519
+ #endif
520
+ ;
521
+ static VALUE pat = Qnil;
522
+
523
+ REGCOMP_I(pat);
524
+ #ifndef TIGHT_PARSER
525
+ SUBS(str, pat, parse_day_cb);
526
+ #else
527
+ SUBW(str, pat, parse_day_cb);
528
+ #endif
529
+ }
530
+
531
+ static int
532
+ parse_time2_cb(VALUE m, VALUE hash)
533
+ {
534
+ VALUE h, min, s, f, p;
535
+
536
+ h = rb_reg_nth_match(1, m);
537
+ h = str2num(h);
538
+
539
+ min = rb_reg_nth_match(2, m);
540
+ if (!NIL_P(min))
541
+ min = str2num(min);
542
+
543
+ s = rb_reg_nth_match(3, m);
544
+ if (!NIL_P(s))
545
+ s = str2num(s);
546
+
547
+ f = rb_reg_nth_match(4, m);
548
+
549
+ if (!NIL_P(f))
550
+ f = rb_rational_new2(str2num(f),
551
+ f_expt(INT2FIX(10), LONG2NUM(RSTRING_LEN(f))));
552
+
553
+ p = rb_reg_nth_match(5, m);
554
+
555
+ if (!NIL_P(p)) {
556
+ int ih = NUM2INT(h);
557
+ ih %= 12;
558
+ if (*RSTRING_PTR(p) == 'P' || *RSTRING_PTR(p) == 'p')
559
+ ih += 12;
560
+ h = INT2FIX(ih);
561
+ }
562
+
563
+ set_hash("hour", h);
564
+ if (!NIL_P(min))
565
+ set_hash("min", min);
566
+ if (!NIL_P(s))
567
+ set_hash("sec", s);
568
+ if (!NIL_P(f))
569
+ set_hash("sec_fraction", f);
570
+
571
+ return 1;
572
+ }
573
+
574
+ static int
575
+ parse_time_cb(VALUE m, VALUE hash)
576
+ {
577
+ static const char pat_source[] =
578
+ "\\A(\\d+)h?"
579
+ "(?:\\s*:?\\s*(\\d+)m?"
580
+ "(?:"
581
+ "\\s*:?\\s*(\\d+)(?:[,.](\\d+))?s?"
582
+ ")?"
583
+ ")?"
584
+ "(?:\\s*([ap])(?:m\\b|\\.m\\.))?";
585
+ static VALUE pat = Qnil;
586
+ VALUE s1, s2;
587
+
588
+ s1 = rb_reg_nth_match(1, m);
589
+ s2 = rb_reg_nth_match(2, m);
590
+
591
+ if (!NIL_P(s2))
592
+ set_hash("zone", s2);
593
+
594
+ REGCOMP_I(pat);
595
+
596
+ {
597
+ VALUE m = f_match(pat, s1);
598
+
599
+ if (NIL_P(m))
600
+ return 0;
601
+ parse_time2_cb(m, hash);
602
+ }
603
+
604
+ return 1;
605
+ }
606
+
607
+ static int
608
+ parse_time(VALUE str, VALUE hash)
609
+ {
610
+ static const char pat_source[] =
611
+ "("
612
+ "(?:"
613
+ "\\d+\\s*:\\s*\\d+"
614
+ "(?:"
615
+ #ifndef TIGHT_PARSER
616
+ "\\s*:\\s*\\d+(?:[,.]\\d*)?"
617
+ #else
618
+ "\\s*:\\s*\\d+(?:[,.]\\d+)?"
619
+ #endif
620
+ ")?"
621
+ "|"
622
+ "\\d+\\s*h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?"
623
+ ")"
624
+ "(?:"
625
+ "\\s*"
626
+ "[ap](?:m\\b|\\.m\\.)"
627
+ ")?"
628
+ "|"
629
+ "\\d+\\s*[ap](?:m\\b|\\.m\\.)"
630
+ ")"
631
+ "(?:"
632
+ "\\s*"
633
+ "("
634
+ "(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?"
635
+ "|"
636
+ "(?-i:[[:alpha:].\\s]+)(?:standard|daylight)\\stime\\b"
637
+ "|"
638
+ "(?-i:[[:alpha:]]+)(?:\\sdst)?\\b"
639
+ ")"
640
+ ")?";
641
+ static VALUE pat = Qnil;
642
+
643
+ REGCOMP_I(pat);
644
+ #ifndef TIGHT_PARSER
645
+ SUBS(str, pat, parse_time_cb);
646
+ #else
647
+ SUBT(str, pat, parse_time_cb);
648
+ #endif
649
+ }
650
+
651
+ #ifdef TIGHT_PARSER
652
+ static int
653
+ parse_era1_cb(VALUE m, VALUE hash)
654
+ {
655
+ return 1;
656
+ }
657
+
658
+ static int
659
+ parse_era1(VALUE str, VALUE hash)
660
+ {
661
+ static const char pat_source[] =
662
+ "(a(?:d|\\.d\\.))";
663
+ static VALUE pat = Qnil;
664
+
665
+ REGCOMP_I(pat);
666
+ SUBA(str, pat, parse_era1_cb);
667
+ }
668
+
669
+ static int
670
+ parse_era2_cb(VALUE m, VALUE hash)
671
+ {
672
+ VALUE b;
673
+
674
+ b = rb_reg_nth_match(1, m);
675
+ if (*RSTRING_PTR(b) == 'B' ||
676
+ *RSTRING_PTR(b) == 'b')
677
+ set_hash("_bc", Qtrue);
678
+ return 1;
679
+ }
680
+
681
+ static int
682
+ parse_era2(VALUE str, VALUE hash)
683
+ {
684
+ static const char pat_source[] =
685
+ "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|b(?:c|\\.c\\.))";
686
+ static VALUE pat = Qnil;
687
+
688
+ REGCOMP_I(pat);
689
+ SUBB(str, pat, parse_era2_cb);
690
+ }
691
+
692
+ static int
693
+ parse_era(VALUE str, VALUE hash)
694
+ {
695
+ if (parse_era1(str, hash)) /* pre */
696
+ goto ok;
697
+ if (parse_era2(str, hash)) /* post */
698
+ goto ok;
699
+ return 0;
700
+ ok:
701
+ return 1;
702
+ }
703
+ #endif
704
+
705
+ #ifdef TIGHT_PARSER
706
+ static int
707
+ check_year_width(VALUE y)
708
+ {
709
+ char *s;
710
+ size_t l;
711
+
712
+ s = RSTRING_PTR(y);
713
+ l = strcspn(s, DECDIGIT);
714
+ s += l;
715
+ l = strspn(s, DECDIGIT);
716
+ if (l != 2)
717
+ return 0;
718
+ return 1;
719
+ }
720
+
721
+ static int
722
+ check_apost(VALUE a, VALUE b, VALUE c)
723
+ {
724
+ int f = 0;
725
+
726
+ if (!NIL_P(a) && *RSTRING_PTR(a) == '\'') {
727
+ if (!check_year_width(a))
728
+ return 0;
729
+ f++;
730
+ }
731
+ if (!NIL_P(b) && *RSTRING_PTR(b) == '\'') {
732
+ if (!check_year_width(b))
733
+ return 0;
734
+ if (!NIL_P(c))
735
+ return 0;
736
+ f++;
737
+ }
738
+ if (!NIL_P(c) && *RSTRING_PTR(c) == '\'') {
739
+ if (!check_year_width(c))
740
+ return 0;
741
+ f++;
742
+ }
743
+ if (f > 1)
744
+ return 0;
745
+ return 1;
746
+ }
747
+ #endif
748
+
749
+ static int
750
+ parse_eu_cb(VALUE m, VALUE hash)
751
+ {
752
+ #ifndef TIGHT_PARSER
753
+ VALUE y, mon, d, b;
754
+
755
+ d = rb_reg_nth_match(1, m);
756
+ mon = rb_reg_nth_match(2, m);
757
+ b = rb_reg_nth_match(3, m);
758
+ y = rb_reg_nth_match(4, m);
759
+
760
+ mon = INT2FIX(mon_num(mon));
761
+
762
+ s3e(hash, y, mon, d, !NIL_P(b) &&
763
+ (*RSTRING_PTR(b) == 'B' ||
764
+ *RSTRING_PTR(b) == 'b'));
765
+ #else
766
+ VALUE y, mon, d;
767
+
768
+ d = rb_reg_nth_match(1, m);
769
+ mon = rb_reg_nth_match(2, m);
770
+ y = rb_reg_nth_match(3, m);
771
+
772
+ if (!check_apost(d, mon, y))
773
+ return 0;
774
+
775
+ mon = INT2FIX(mon_num(mon));
776
+
777
+ s3e(hash, y, mon, d, 0);
778
+ #endif
779
+ return 1;
780
+ }
781
+
782
+ static int
783
+ parse_eu(VALUE str, VALUE hash)
784
+ {
785
+ static const char pat_source[] =
786
+ #ifdef TIGHT_PARSER
787
+ BOS
788
+ FPW_COM FPT_COM
789
+ #endif
790
+ #ifndef TIGHT_PARSER
791
+ "('?\\d+)[^-\\d\\s]*"
792
+ #else
793
+ "(\\d+)(?:(?:st|nd|rd|th)\\b)?"
794
+ #endif
795
+ "\\s*"
796
+ #ifndef TIGHT_PARSER
797
+ "(" ABBR_MONTHS ")[^-\\d\\s']*"
798
+ #else
799
+ "(" VALID_MONTHS ")"
800
+ #endif
801
+ "(?:"
802
+ "\\s*"
803
+ #ifndef TIGHT_PARSER
804
+ "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
805
+ "\\s*"
806
+ "('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)"
807
+ #else
808
+ "(?:" FPA ")?"
809
+ "\\s*"
810
+ "([-']?\\d+)"
811
+ "\\s*"
812
+ "(?:" FPA "|" FPB ")?"
813
+ #endif
814
+ ")?"
815
+ #ifdef TIGHT_PARSER
816
+ COM_FPT COM_FPW
817
+ EOS
818
+ #endif
819
+ ;
820
+ static VALUE pat = Qnil;
821
+
822
+ REGCOMP_I(pat);
823
+ SUBS(str, pat, parse_eu_cb);
824
+ }
825
+
826
+ static int
827
+ parse_us_cb(VALUE m, VALUE hash)
828
+ {
829
+ #ifndef TIGHT_PARSER
830
+ VALUE y, mon, d, b;
831
+
832
+ mon = rb_reg_nth_match(1, m);
833
+ d = rb_reg_nth_match(2, m);
834
+
835
+ b = rb_reg_nth_match(3, m);
836
+ y = rb_reg_nth_match(4, m);
837
+
838
+ mon = INT2FIX(mon_num(mon));
839
+
840
+ s3e(hash, y, mon, d, !NIL_P(b) &&
841
+ (*RSTRING_PTR(b) == 'B' ||
842
+ *RSTRING_PTR(b) == 'b'));
843
+ #else
844
+ VALUE y, mon, d;
845
+
846
+ mon = rb_reg_nth_match(1, m);
847
+ d = rb_reg_nth_match(2, m);
848
+ y = rb_reg_nth_match(3, m);
849
+
850
+ if (!check_apost(mon, d, y))
851
+ return 0;
852
+
853
+ mon = INT2FIX(mon_num(mon));
854
+
855
+ s3e(hash, y, mon, d, 0);
856
+ #endif
857
+ return 1;
858
+ }
859
+
860
+ static int
861
+ parse_us(VALUE str, VALUE hash)
862
+ {
863
+ static const char pat_source[] =
864
+ #ifdef TIGHT_PARSER
865
+ BOS
866
+ FPW_COM FPT_COM
867
+ #endif
868
+ #ifndef TIGHT_PARSER
869
+ "\\b(" ABBR_MONTHS ")[^-\\d\\s']*"
870
+ #else
871
+ "\\b(" VALID_MONTHS ")"
872
+ #endif
873
+ "\\s*"
874
+ #ifndef TIGHT_PARSER
875
+ "('?\\d+)[^-\\d\\s']*"
876
+ #else
877
+ "('?\\d+)(?:(?:st|nd|rd|th)\\b)?"
878
+ COM_FPT
879
+ #endif
880
+ "(?:"
881
+ "\\s*,?"
882
+ "\\s*"
883
+ #ifndef TIGHT_PARSER
884
+ "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
885
+ "\\s*"
886
+ "('?-?\\d+)"
887
+ #else
888
+ "(?:" FPA ")?"
889
+ "\\s*"
890
+ "([-']?\\d+)"
891
+ "\\s*"
892
+ "(?:" FPA "|" FPB ")?"
893
+ #endif
894
+ ")?"
895
+ #ifdef TIGHT_PARSER
896
+ COM_FPT COM_FPW
897
+ EOS
898
+ #endif
899
+ ;
900
+ static VALUE pat = Qnil;
901
+
902
+ REGCOMP_I(pat);
903
+ SUBS(str, pat, parse_us_cb);
904
+ }
905
+
906
+ static int
907
+ parse_iso_cb(VALUE m, VALUE hash)
908
+ {
909
+ VALUE y, mon, d;
910
+
911
+ y = rb_reg_nth_match(1, m);
912
+ mon = rb_reg_nth_match(2, m);
913
+ d = rb_reg_nth_match(3, m);
914
+
915
+ #ifdef TIGHT_PARSER
916
+ if (!check_apost(y, mon, d))
917
+ return 0;
918
+ #endif
919
+
920
+ s3e(hash, y, mon, d, 0);
921
+ return 1;
922
+ }
923
+
924
+ static int
925
+ parse_iso(VALUE str, VALUE hash)
926
+ {
927
+ static const char pat_source[] =
928
+ #ifndef TIGHT_PARSER
929
+ "('?[-+]?\\d+)-(\\d+)-('?-?\\d+)"
930
+ #else
931
+ BOS
932
+ FPW_COM FPT_COM
933
+ "([-+']?\\d+)-(\\d+)-([-']?\\d+)"
934
+ TEE_FPT COM_FPW
935
+ EOS
936
+ #endif
937
+ ;
938
+ static VALUE pat = Qnil;
939
+
940
+ REGCOMP_0(pat);
941
+ SUBS(str, pat, parse_iso_cb);
942
+ }
943
+
944
+ static int
945
+ parse_iso21_cb(VALUE m, VALUE hash)
946
+ {
947
+ VALUE y, w, d;
948
+
949
+ y = rb_reg_nth_match(1, m);
950
+ w = rb_reg_nth_match(2, m);
951
+ d = rb_reg_nth_match(3, m);
952
+
953
+ if (!NIL_P(y))
954
+ set_hash("cwyear", str2num(y));
955
+ set_hash("cweek", str2num(w));
956
+ if (!NIL_P(d))
957
+ set_hash("cwday", str2num(d));
958
+
959
+ return 1;
960
+ }
961
+
962
+ static int
963
+ parse_iso21(VALUE str, VALUE hash)
964
+ {
965
+ static const char pat_source[] =
966
+ #ifndef TIGHT_PARSER
967
+ "\\b(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?\\b"
968
+ #else
969
+ BOS
970
+ FPW_COM FPT_COM
971
+ "(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?"
972
+ TEE_FPT COM_FPW
973
+ EOS
974
+ #endif
975
+ ;
976
+ static VALUE pat = Qnil;
977
+
978
+ REGCOMP_I(pat);
979
+ SUBS(str, pat, parse_iso21_cb);
980
+ }
981
+
982
+ static int
983
+ parse_iso22_cb(VALUE m, VALUE hash)
984
+ {
985
+ VALUE d;
986
+
987
+ d = rb_reg_nth_match(1, m);
988
+ set_hash("cwday", str2num(d));
989
+ return 1;
990
+ }
991
+
992
+ static int
993
+ parse_iso22(VALUE str, VALUE hash)
994
+ {
995
+ static const char pat_source[] =
996
+ #ifndef TIGHT_PARSER
997
+ "-w-(\\d)\\b"
998
+ #else
999
+ BOS
1000
+ FPW_COM FPT_COM
1001
+ "-w-(\\d)"
1002
+ TEE_FPT COM_FPW
1003
+ EOS
1004
+ #endif
1005
+ ;
1006
+ static VALUE pat = Qnil;
1007
+
1008
+ REGCOMP_I(pat);
1009
+ SUBS(str, pat, parse_iso22_cb);
1010
+ }
1011
+
1012
+ static int
1013
+ parse_iso23_cb(VALUE m, VALUE hash)
1014
+ {
1015
+ VALUE mon, d;
1016
+
1017
+ mon = rb_reg_nth_match(1, m);
1018
+ d = rb_reg_nth_match(2, m);
1019
+
1020
+ if (!NIL_P(mon))
1021
+ set_hash("mon", str2num(mon));
1022
+ set_hash("mday", str2num(d));
1023
+
1024
+ return 1;
1025
+ }
1026
+
1027
+ static int
1028
+ parse_iso23(VALUE str, VALUE hash)
1029
+ {
1030
+ static const char pat_source[] =
1031
+ #ifndef TIGHT_PARSER
1032
+ "--(\\d{2})?-(\\d{2})\\b"
1033
+ #else
1034
+ BOS
1035
+ FPW_COM FPT_COM
1036
+ "--(\\d{2})?-(\\d{2})"
1037
+ TEE_FPT COM_FPW
1038
+ EOS
1039
+ #endif
1040
+ ;
1041
+ static VALUE pat = Qnil;
1042
+
1043
+ REGCOMP_0(pat);
1044
+ SUBS(str, pat, parse_iso23_cb);
1045
+ }
1046
+
1047
+ static int
1048
+ parse_iso24_cb(VALUE m, VALUE hash)
1049
+ {
1050
+ VALUE mon, d;
1051
+
1052
+ mon = rb_reg_nth_match(1, m);
1053
+ d = rb_reg_nth_match(2, m);
1054
+
1055
+ set_hash("mon", str2num(mon));
1056
+ if (!NIL_P(d))
1057
+ set_hash("mday", str2num(d));
1058
+
1059
+ return 1;
1060
+ }
1061
+
1062
+ static int
1063
+ parse_iso24(VALUE str, VALUE hash)
1064
+ {
1065
+ static const char pat_source[] =
1066
+ #ifndef TIGHT_PARSER
1067
+ "--(\\d{2})(\\d{2})?\\b"
1068
+ #else
1069
+ BOS
1070
+ FPW_COM FPT_COM
1071
+ "--(\\d{2})(\\d{2})?"
1072
+ TEE_FPT COM_FPW
1073
+ EOS
1074
+ #endif
1075
+ ;
1076
+ static VALUE pat = Qnil;
1077
+
1078
+ REGCOMP_0(pat);
1079
+ SUBS(str, pat, parse_iso24_cb);
1080
+ }
1081
+
1082
+ static int
1083
+ parse_iso25_cb(VALUE m, VALUE hash)
1084
+ {
1085
+ VALUE y, d;
1086
+
1087
+ y = rb_reg_nth_match(1, m);
1088
+ d = rb_reg_nth_match(2, m);
1089
+
1090
+ set_hash("year", str2num(y));
1091
+ set_hash("yday", str2num(d));
1092
+
1093
+ return 1;
1094
+ }
1095
+
1096
+ static int
1097
+ parse_iso25(VALUE str, VALUE hash)
1098
+ {
1099
+ static const char pat0_source[] =
1100
+ #ifndef TIGHT_PARSER
1101
+ "[,.](\\d{2}|\\d{4})-\\d{3}\\b"
1102
+ #else
1103
+ BOS
1104
+ FPW_COM FPT_COM
1105
+ "[,.](\\d{2}|\\d{4})-\\d{3}"
1106
+ TEE_FPT COM_FPW
1107
+ EOS
1108
+ #endif
1109
+ ;
1110
+ static VALUE pat0 = Qnil;
1111
+ static const char pat_source[] =
1112
+ #ifndef TIGHT_PARSER
1113
+ "\\b(\\d{2}|\\d{4})-(\\d{3})\\b"
1114
+ #else
1115
+ BOS
1116
+ FPW_COM FPT_COM
1117
+ "(\\d{2}|\\d{4})-(\\d{3})"
1118
+ TEE_FPT COM_FPW
1119
+ EOS
1120
+ #endif
1121
+ ;
1122
+ static VALUE pat = Qnil;
1123
+
1124
+ REGCOMP_0(pat0);
1125
+ REGCOMP_0(pat);
1126
+
1127
+ if (!NIL_P(f_match(pat0, str)))
1128
+ return 0;
1129
+ SUBS(str, pat, parse_iso25_cb);
1130
+ }
1131
+
1132
+ static int
1133
+ parse_iso26_cb(VALUE m, VALUE hash)
1134
+ {
1135
+ VALUE d;
1136
+
1137
+ d = rb_reg_nth_match(1, m);
1138
+ set_hash("yday", str2num(d));
1139
+
1140
+ return 1;
1141
+ }
1142
+ static int
1143
+ parse_iso26(VALUE str, VALUE hash)
1144
+ {
1145
+ static const char pat0_source[] =
1146
+ #ifndef TIGHT_PARSER
1147
+ "\\d-\\d{3}\\b"
1148
+ #else
1149
+ BOS
1150
+ FPW_COM FPT_COM
1151
+ "\\d-\\d{3}"
1152
+ TEE_FPT COM_FPW
1153
+ EOS
1154
+ #endif
1155
+ ;
1156
+ static VALUE pat0 = Qnil;
1157
+ static const char pat_source[] =
1158
+ #ifndef TIGHT_PARSER
1159
+ "\\b-(\\d{3})\\b"
1160
+ #else
1161
+ BOS
1162
+ FPW_COM FPT_COM
1163
+ "-(\\d{3})"
1164
+ TEE_FPT COM_FPW
1165
+ EOS
1166
+ #endif
1167
+ ;
1168
+ static VALUE pat = Qnil;
1169
+
1170
+ REGCOMP_0(pat0);
1171
+ REGCOMP_0(pat);
1172
+
1173
+ if (!NIL_P(f_match(pat0, str)))
1174
+ return 0;
1175
+ SUBS(str, pat, parse_iso26_cb);
1176
+ }
1177
+
1178
+ static int
1179
+ parse_iso2(VALUE str, VALUE hash)
1180
+ {
1181
+ if (parse_iso21(str, hash))
1182
+ goto ok;
1183
+ if (parse_iso22(str, hash))
1184
+ goto ok;
1185
+ if (parse_iso23(str, hash))
1186
+ goto ok;
1187
+ if (parse_iso24(str, hash))
1188
+ goto ok;
1189
+ if (parse_iso25(str, hash))
1190
+ goto ok;
1191
+ if (parse_iso26(str, hash))
1192
+ goto ok;
1193
+ return 0;
1194
+
1195
+ ok:
1196
+ return 1;
1197
+ }
1198
+
1199
+ static int
1200
+ gengo(int c)
1201
+ {
1202
+ int e;
1203
+
1204
+ switch (c) {
1205
+ case 'M': case 'm': e = 1867; break;
1206
+ case 'T': case 't': e = 1911; break;
1207
+ case 'S': case 's': e = 1925; break;
1208
+ case 'H': case 'h': e = 1988; break;
1209
+ default: e = 0; break;
1210
+ }
1211
+ return e;
1212
+ }
1213
+
1214
+ static int
1215
+ parse_jis_cb(VALUE m, VALUE hash)
1216
+ {
1217
+ VALUE e, y, mon, d;
1218
+ int ep;
1219
+
1220
+ e = rb_reg_nth_match(1, m);
1221
+ y = rb_reg_nth_match(2, m);
1222
+ mon = rb_reg_nth_match(3, m);
1223
+ d = rb_reg_nth_match(4, m);
1224
+
1225
+ ep = gengo(*RSTRING_PTR(e));
1226
+
1227
+ set_hash("year", f_add(str2num(y), INT2FIX(ep)));
1228
+ set_hash("mon", str2num(mon));
1229
+ set_hash("mday", str2num(d));
1230
+
1231
+ return 1;
1232
+ }
1233
+
1234
+ static int
1235
+ parse_jis(VALUE str, VALUE hash)
1236
+ {
1237
+ static const char pat_source[] =
1238
+ #ifndef TIGHT_PARSER
1239
+ "\\b([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)"
1240
+ #else
1241
+ BOS
1242
+ FPW_COM FPT_COM
1243
+ "([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)"
1244
+ TEE_FPT COM_FPW
1245
+ EOS
1246
+ #endif
1247
+ ;
1248
+ static VALUE pat = Qnil;
1249
+
1250
+ REGCOMP_I(pat);
1251
+ SUBS(str, pat, parse_jis_cb);
1252
+ }
1253
+
1254
+ static int
1255
+ parse_vms11_cb(VALUE m, VALUE hash)
1256
+ {
1257
+ VALUE y, mon, d;
1258
+
1259
+ d = rb_reg_nth_match(1, m);
1260
+ mon = rb_reg_nth_match(2, m);
1261
+ y = rb_reg_nth_match(3, m);
1262
+
1263
+ #ifdef TIGHT_PARSER
1264
+ if (!check_apost(d, mon, y))
1265
+ return 0;
1266
+ #endif
1267
+
1268
+ mon = INT2FIX(mon_num(mon));
1269
+
1270
+ s3e(hash, y, mon, d, 0);
1271
+ return 1;
1272
+ }
1273
+
1274
+ static int
1275
+ parse_vms11(VALUE str, VALUE hash)
1276
+ {
1277
+ static const char pat_source[] =
1278
+ #ifndef TIGHT_PARSER
1279
+ "('?-?\\d+)-(" ABBR_MONTHS ")[^-/.]*"
1280
+ "-('?-?\\d+)"
1281
+ #else
1282
+ BOS
1283
+ FPW_COM FPT_COM
1284
+ "([-']?\\d+)-(" DOTLESS_VALID_MONTHS ")"
1285
+ "-([-']?\\d+)"
1286
+ COM_FPT COM_FPW
1287
+ EOS
1288
+ #endif
1289
+ ;
1290
+ static VALUE pat = Qnil;
1291
+
1292
+ REGCOMP_I(pat);
1293
+ SUBS(str, pat, parse_vms11_cb);
1294
+ }
1295
+
1296
+ static int
1297
+ parse_vms12_cb(VALUE m, VALUE hash)
1298
+ {
1299
+ VALUE y, mon, d;
1300
+
1301
+ mon = rb_reg_nth_match(1, m);
1302
+ d = rb_reg_nth_match(2, m);
1303
+ y = rb_reg_nth_match(3, m);
1304
+
1305
+ #ifdef TIGHT_PARSER
1306
+ if (!check_apost(mon, d, y))
1307
+ return 0;
1308
+ #endif
1309
+
1310
+ mon = INT2FIX(mon_num(mon));
1311
+
1312
+ s3e(hash, y, mon, d, 0);
1313
+ return 1;
1314
+ }
1315
+
1316
+ static int
1317
+ parse_vms12(VALUE str, VALUE hash)
1318
+ {
1319
+ static const char pat_source[] =
1320
+ #ifndef TIGHT_PARSER
1321
+ "\\b(" ABBR_MONTHS ")[^-/.]*"
1322
+ "-('?-?\\d+)(?:-('?-?\\d+))?"
1323
+ #else
1324
+ BOS
1325
+ FPW_COM FPT_COM
1326
+ "(" DOTLESS_VALID_MONTHS ")"
1327
+ "-([-']?\\d+)(?:-([-']?\\d+))?"
1328
+ COM_FPT COM_FPW
1329
+ EOS
1330
+ #endif
1331
+ ;
1332
+ static VALUE pat = Qnil;
1333
+
1334
+ REGCOMP_I(pat);
1335
+ SUBS(str, pat, parse_vms12_cb);
1336
+ }
1337
+
1338
+ static int
1339
+ parse_vms(VALUE str, VALUE hash)
1340
+ {
1341
+ if (parse_vms11(str, hash))
1342
+ goto ok;
1343
+ if (parse_vms12(str, hash))
1344
+ goto ok;
1345
+ return 0;
1346
+
1347
+ ok:
1348
+ return 1;
1349
+ }
1350
+
1351
+ static int
1352
+ parse_sla_cb(VALUE m, VALUE hash)
1353
+ {
1354
+ VALUE y, mon, d;
1355
+
1356
+ y = rb_reg_nth_match(1, m);
1357
+ mon = rb_reg_nth_match(2, m);
1358
+ d = rb_reg_nth_match(3, m);
1359
+
1360
+ #ifdef TIGHT_PARSER
1361
+ if (!check_apost(y, mon, d))
1362
+ return 0;
1363
+ #endif
1364
+
1365
+ s3e(hash, y, mon, d, 0);
1366
+ return 1;
1367
+ }
1368
+
1369
+ static int
1370
+ parse_sla(VALUE str, VALUE hash)
1371
+ {
1372
+ static const char pat_source[] =
1373
+ #ifndef TIGHT_PARSER
1374
+ "('?-?\\d+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?"
1375
+ #else
1376
+ BOS
1377
+ FPW_COM FPT_COM
1378
+ "([-']?\\d+)/\\s*('?\\d+)(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
1379
+ COM_FPT COM_FPW
1380
+ EOS
1381
+ #endif
1382
+ ;
1383
+ static VALUE pat = Qnil;
1384
+
1385
+ REGCOMP_I(pat);
1386
+ SUBS(str, pat, parse_sla_cb);
1387
+ }
1388
+
1389
+ #ifdef TIGHT_PARSER
1390
+ static int
1391
+ parse_sla2_cb(VALUE m, VALUE hash)
1392
+ {
1393
+ VALUE y, mon, d;
1394
+
1395
+ d = rb_reg_nth_match(1, m);
1396
+ mon = rb_reg_nth_match(2, m);
1397
+ y = rb_reg_nth_match(3, m);
1398
+
1399
+ if (!check_apost(d, mon, y))
1400
+ return 0;
1401
+
1402
+ mon = INT2FIX(mon_num(mon));
1403
+
1404
+ s3e(hash, y, mon, d, 0);
1405
+ return 1;
1406
+ }
1407
+
1408
+ static int
1409
+ parse_sla2(VALUE str, VALUE hash)
1410
+ {
1411
+ static const char pat_source[] =
1412
+ BOS
1413
+ FPW_COM FPT_COM
1414
+ "([-']?\\d+)/\\s*(" DOTLESS_VALID_MONTHS ")(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
1415
+ COM_FPT COM_FPW
1416
+ EOS
1417
+ ;
1418
+ static VALUE pat = Qnil;
1419
+
1420
+ REGCOMP_I(pat);
1421
+ SUBS(str, pat, parse_sla2_cb);
1422
+ }
1423
+
1424
+ static int
1425
+ parse_sla3_cb(VALUE m, VALUE hash)
1426
+ {
1427
+ VALUE y, mon, d;
1428
+
1429
+ mon = rb_reg_nth_match(1, m);
1430
+ d = rb_reg_nth_match(2, m);
1431
+ y = rb_reg_nth_match(3, m);
1432
+
1433
+ if (!check_apost(mon, d, y))
1434
+ return 0;
1435
+
1436
+ mon = INT2FIX(mon_num(mon));
1437
+
1438
+ s3e(hash, y, mon, d, 0);
1439
+ return 1;
1440
+ }
1441
+
1442
+ static int
1443
+ parse_sla3(VALUE str, VALUE hash)
1444
+ {
1445
+ static const char pat_source[] =
1446
+ BOS
1447
+ FPW_COM FPT_COM
1448
+ "(" DOTLESS_VALID_MONTHS ")/\\s*([-']?\\d+)(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
1449
+ COM_FPT COM_FPW
1450
+ EOS
1451
+ ;
1452
+ static VALUE pat = Qnil;
1453
+
1454
+ REGCOMP_I(pat);
1455
+ SUBS(str, pat, parse_sla3_cb);
1456
+ }
1457
+ #endif
1458
+
1459
+ static int
1460
+ parse_dot_cb(VALUE m, VALUE hash)
1461
+ {
1462
+ VALUE y, mon, d;
1463
+
1464
+ y = rb_reg_nth_match(1, m);
1465
+ mon = rb_reg_nth_match(2, m);
1466
+ d = rb_reg_nth_match(3, m);
1467
+
1468
+ #ifdef TIGHT_PARSER
1469
+ if (!check_apost(y, mon, d))
1470
+ return 0;
1471
+ #endif
1472
+
1473
+ s3e(hash, y, mon, d, 0);
1474
+ return 1;
1475
+ }
1476
+
1477
+ static int
1478
+ parse_dot(VALUE str, VALUE hash)
1479
+ {
1480
+ static const char pat_source[] =
1481
+ #ifndef TIGHT_PARSER
1482
+ "('?-?\\d+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)"
1483
+ #else
1484
+ BOS
1485
+ FPW_COM FPT_COM
1486
+ "([-']?\\d+)\\.\\s*(\\d+)\\.\\s*([-']?\\d+)"
1487
+ COM_FPT COM_FPW
1488
+ EOS
1489
+ #endif
1490
+ ;
1491
+ static VALUE pat = Qnil;
1492
+
1493
+ REGCOMP_I(pat);
1494
+ SUBS(str, pat, parse_dot_cb);
1495
+ }
1496
+
1497
+ #ifdef TIGHT_PARSER
1498
+ static int
1499
+ parse_dot2_cb(VALUE m, VALUE hash)
1500
+ {
1501
+ VALUE y, mon, d;
1502
+
1503
+ d = rb_reg_nth_match(1, m);
1504
+ mon = rb_reg_nth_match(2, m);
1505
+ y = rb_reg_nth_match(3, m);
1506
+
1507
+ if (!check_apost(d, mon, y))
1508
+ return 0;
1509
+
1510
+ mon = INT2FIX(mon_num(mon));
1511
+
1512
+ s3e(hash, y, mon, d, 0);
1513
+ return 1;
1514
+ }
1515
+
1516
+ static int
1517
+ parse_dot2(VALUE str, VALUE hash)
1518
+ {
1519
+ static const char pat_source[] =
1520
+ BOS
1521
+ FPW_COM FPT_COM
1522
+ "([-']?\\d+)\\.\\s*(" DOTLESS_VALID_MONTHS ")(?:(?:[./])\\s*([-']?\\d+))?"
1523
+ COM_FPT COM_FPW
1524
+ EOS
1525
+ ;
1526
+ static VALUE pat = Qnil;
1527
+
1528
+ REGCOMP_I(pat);
1529
+ SUBS(str, pat, parse_dot2_cb);
1530
+ }
1531
+
1532
+ static int
1533
+ parse_dot3_cb(VALUE m, VALUE hash)
1534
+ {
1535
+ VALUE y, mon, d;
1536
+
1537
+ mon = rb_reg_nth_match(1, m);
1538
+ d = rb_reg_nth_match(2, m);
1539
+ y = rb_reg_nth_match(3, m);
1540
+
1541
+ if (!check_apost(mon, d, y))
1542
+ return 0;
1543
+
1544
+ mon = INT2FIX(mon_num(mon));
1545
+
1546
+ s3e(hash, y, mon, d, 0);
1547
+ return 1;
1548
+ }
1549
+
1550
+ static int
1551
+ parse_dot3(VALUE str, VALUE hash)
1552
+ {
1553
+ static const char pat_source[] =
1554
+ BOS
1555
+ FPW_COM FPT_COM
1556
+ "(" DOTLESS_VALID_MONTHS ")\\.\\s*([-']?\\d+)(?:(?:[./])\\s*([-']?\\d+))?"
1557
+ COM_FPT COM_FPW
1558
+ EOS
1559
+ ;
1560
+ static VALUE pat = Qnil;
1561
+
1562
+ REGCOMP_I(pat);
1563
+ SUBS(str, pat, parse_dot3_cb);
1564
+ }
1565
+ #endif
1566
+
1567
+ static int
1568
+ parse_year_cb(VALUE m, VALUE hash)
1569
+ {
1570
+ VALUE y;
1571
+
1572
+ y = rb_reg_nth_match(1, m);
1573
+ set_hash("year", str2num(y));
1574
+ return 1;
1575
+ }
1576
+
1577
+ static int
1578
+ parse_year(VALUE str, VALUE hash)
1579
+ {
1580
+ static const char pat_source[] =
1581
+ #ifndef TIGHT_PARSER
1582
+ "'(\\d+)\\b"
1583
+ #else
1584
+ BOS
1585
+ FPW_COM FPT_COM
1586
+ "'(\\d+)"
1587
+ COM_FPT COM_FPW
1588
+ EOS
1589
+ #endif
1590
+ ;
1591
+ static VALUE pat = Qnil;
1592
+
1593
+ REGCOMP_0(pat);
1594
+ SUBS(str, pat, parse_year_cb);
1595
+ }
1596
+
1597
+ static int
1598
+ parse_mon_cb(VALUE m, VALUE hash)
1599
+ {
1600
+ VALUE mon;
1601
+
1602
+ mon = rb_reg_nth_match(1, m);
1603
+ set_hash("mon", INT2FIX(mon_num(mon)));
1604
+ return 1;
1605
+ }
1606
+
1607
+ static int
1608
+ parse_mon(VALUE str, VALUE hash)
1609
+ {
1610
+ static const char pat_source[] =
1611
+ #ifndef TIGHT_PARSER
1612
+ "\\b(" ABBR_MONTHS ")\\S*"
1613
+ #else
1614
+ BOS
1615
+ FPW_COM FPT_COM
1616
+ "(" VALID_MONTHS ")"
1617
+ COM_FPT COM_FPW
1618
+ EOS
1619
+ #endif
1620
+ ;
1621
+ static VALUE pat = Qnil;
1622
+
1623
+ REGCOMP_I(pat);
1624
+ SUBS(str, pat, parse_mon_cb);
1625
+ }
1626
+
1627
+ static int
1628
+ parse_mday_cb(VALUE m, VALUE hash)
1629
+ {
1630
+ VALUE d;
1631
+
1632
+ d = rb_reg_nth_match(1, m);
1633
+ set_hash("mday", str2num(d));
1634
+ return 1;
1635
+ }
1636
+
1637
+ static int
1638
+ parse_mday(VALUE str, VALUE hash)
1639
+ {
1640
+ static const char pat_source[] =
1641
+ #ifndef TIGHT_PARSER
1642
+ "(\\d+)(st|nd|rd|th)\\b"
1643
+ #else
1644
+ BOS
1645
+ FPW_COM FPT_COM
1646
+ "(\\d+)(st|nd|rd|th)"
1647
+ COM_FPT COM_FPW
1648
+ EOS
1649
+ #endif
1650
+ ;
1651
+ static VALUE pat = Qnil;
1652
+
1653
+ REGCOMP_I(pat);
1654
+ SUBS(str, pat, parse_mday_cb);
1655
+ }
1656
+
1657
+ static int
1658
+ n2i(const char *s, long f, long w)
1659
+ {
1660
+ long e, i;
1661
+ int v;
1662
+
1663
+ e = f + w;
1664
+ v = 0;
1665
+ for (i = f; i < e; i++) {
1666
+ v *= 10;
1667
+ v += s[i] - '0';
1668
+ }
1669
+ return v;
1670
+ }
1671
+
1672
+ static int
1673
+ parse_ddd_cb(VALUE m, VALUE hash)
1674
+ {
1675
+ VALUE s1, s2, s3, s4, s5;
1676
+ const char *cs2, *cs3, *cs5;
1677
+ long l2, l3, l4, l5;
1678
+
1679
+ s1 = rb_reg_nth_match(1, m);
1680
+ s2 = rb_reg_nth_match(2, m);
1681
+ s3 = rb_reg_nth_match(3, m);
1682
+ s4 = rb_reg_nth_match(4, m);
1683
+ s5 = rb_reg_nth_match(5, m);
1684
+
1685
+ cs2 = RSTRING_PTR(s2);
1686
+ l2 = RSTRING_LEN(s2);
1687
+
1688
+ switch (l2) {
1689
+ case 2:
1690
+ if (NIL_P(s3) && !NIL_P(s4))
1691
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1692
+ else
1693
+ set_hash("mday", INT2FIX(n2i(cs2, 0, 2)));
1694
+ break;
1695
+ case 4:
1696
+ if (NIL_P(s3) && !NIL_P(s4)) {
1697
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1698
+ set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1699
+ }
1700
+ else {
1701
+ set_hash("mon", INT2FIX(n2i(cs2, 0, 2)));
1702
+ set_hash("mday", INT2FIX(n2i(cs2, 2, 2)));
1703
+ }
1704
+ break;
1705
+ case 6:
1706
+ if (NIL_P(s3) && !NIL_P(s4)) {
1707
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1708
+ set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1709
+ set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
1710
+ }
1711
+ else {
1712
+ int y = n2i(cs2, 0, 2);
1713
+ if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1714
+ y = -y;
1715
+ set_hash("year", INT2FIX(y));
1716
+ set_hash("mon", INT2FIX(n2i(cs2, 2, 2)));
1717
+ set_hash("mday", INT2FIX(n2i(cs2, 4, 2)));
1718
+ }
1719
+ break;
1720
+ case 8:
1721
+ case 10:
1722
+ case 12:
1723
+ case 14:
1724
+ if (NIL_P(s3) && !NIL_P(s4)) {
1725
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1726
+ set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1727
+ set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
1728
+ set_hash("mday", INT2FIX(n2i(cs2, l2-8, 2)));
1729
+ if (l2 >= 10)
1730
+ set_hash("mon", INT2FIX(n2i(cs2, l2-10, 2)));
1731
+ if (l2 == 12) {
1732
+ int y = n2i(cs2, l2-12, 2);
1733
+ if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1734
+ y = -y;
1735
+ set_hash("year", INT2FIX(y));
1736
+ }
1737
+ if (l2 == 14) {
1738
+ int y = n2i(cs2, l2-14, 4);
1739
+ if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1740
+ y = -y;
1741
+ set_hash("year", INT2FIX(y));
1742
+ set_hash("_comp", Qfalse);
1743
+ }
1744
+ }
1745
+ else {
1746
+ int y = n2i(cs2, 0, 4);
1747
+ if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1748
+ y = -y;
1749
+ set_hash("year", INT2FIX(y));
1750
+ set_hash("mon", INT2FIX(n2i(cs2, 4, 2)));
1751
+ set_hash("mday", INT2FIX(n2i(cs2, 6, 2)));
1752
+ if (l2 >= 10)
1753
+ set_hash("hour", INT2FIX(n2i(cs2, 8, 2)));
1754
+ if (l2 >= 12)
1755
+ set_hash("min", INT2FIX(n2i(cs2, 10, 2)));
1756
+ if (l2 >= 14)
1757
+ set_hash("sec", INT2FIX(n2i(cs2, 12, 2)));
1758
+ set_hash("_comp", Qfalse);
1759
+ }
1760
+ break;
1761
+ case 3:
1762
+ if (NIL_P(s3) && !NIL_P(s4)) {
1763
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1764
+ set_hash("min", INT2FIX(n2i(cs2, l2-3, 1)));
1765
+ }
1766
+ else
1767
+ set_hash("yday", INT2FIX(n2i(cs2, 0, 3)));
1768
+ break;
1769
+ case 5:
1770
+ if (NIL_P(s3) && !NIL_P(s4)) {
1771
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1772
+ set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1773
+ set_hash("hour", INT2FIX(n2i(cs2, l2-5, 1)));
1774
+ }
1775
+ else {
1776
+ int y = n2i(cs2, 0, 2);
1777
+ if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1778
+ y = -y;
1779
+ set_hash("year", INT2FIX(y));
1780
+ set_hash("yday", INT2FIX(n2i(cs2, 2, 3)));
1781
+ }
1782
+ break;
1783
+ case 7:
1784
+ if (NIL_P(s3) && !NIL_P(s4)) {
1785
+ set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1786
+ set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1787
+ set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
1788
+ set_hash("mday", INT2FIX(n2i(cs2, l2-7, 1)));
1789
+ }
1790
+ else {
1791
+ int y = n2i(cs2, 0, 4);
1792
+ if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1793
+ y = -y;
1794
+ set_hash("year", INT2FIX(y));
1795
+ set_hash("yday", INT2FIX(n2i(cs2, 4, 3)));
1796
+ }
1797
+ break;
1798
+ }
1799
+ RB_GC_GUARD(s2);
1800
+ if (!NIL_P(s3)) {
1801
+ cs3 = RSTRING_PTR(s3);
1802
+ l3 = RSTRING_LEN(s3);
1803
+
1804
+ if (!NIL_P(s4)) {
1805
+ switch (l3) {
1806
+ case 2:
1807
+ case 4:
1808
+ case 6:
1809
+ set_hash("sec", INT2FIX(n2i(cs3, l3-2, 2)));
1810
+ if (l3 >= 4)
1811
+ set_hash("min", INT2FIX(n2i(cs3, l3-4, 2)));
1812
+ if (l3 >= 6)
1813
+ set_hash("hour", INT2FIX(n2i(cs3, l3-6, 2)));
1814
+ break;
1815
+ }
1816
+ }
1817
+ else {
1818
+ switch (l3) {
1819
+ case 2:
1820
+ case 4:
1821
+ case 6:
1822
+ set_hash("hour", INT2FIX(n2i(cs3, 0, 2)));
1823
+ if (l3 >= 4)
1824
+ set_hash("min", INT2FIX(n2i(cs3, 2, 2)));
1825
+ if (l3 >= 6)
1826
+ set_hash("sec", INT2FIX(n2i(cs3, 4, 2)));
1827
+ break;
1828
+ }
1829
+ }
1830
+ RB_GC_GUARD(s3);
1831
+ }
1832
+ if (!NIL_P(s4)) {
1833
+ l4 = RSTRING_LEN(s4);
1834
+
1835
+ set_hash("sec_fraction",
1836
+ rb_rational_new2(str2num(s4),
1837
+ f_expt(INT2FIX(10), LONG2NUM(l4))));
1838
+ }
1839
+ if (!NIL_P(s5)) {
1840
+ cs5 = RSTRING_PTR(s5);
1841
+ l5 = RSTRING_LEN(s5);
1842
+
1843
+ set_hash("zone", s5);
1844
+
1845
+ if (*cs5 == '[') {
1846
+ VALUE vbuf = 0;
1847
+ char *buf = ALLOCV_N(char, vbuf, l5 + 1);
1848
+ char *s1, *s2, *s3;
1849
+ VALUE zone;
1850
+
1851
+ memcpy(buf, cs5, l5);
1852
+ buf[l5 - 1] = '\0';
1853
+
1854
+ s1 = buf + 1;
1855
+ s2 = strchr(buf, ':');
1856
+ if (s2) {
1857
+ *s2 = '\0';
1858
+ s2++;
1859
+ }
1860
+ if (s2)
1861
+ s3 = s2;
1862
+ else
1863
+ s3 = s1;
1864
+ zone = rb_str_new2(s3);
1865
+ set_hash("zone", zone);
1866
+ if (isdigit((unsigned char)*s1))
1867
+ *--s1 = '+';
1868
+ set_hash("offset", date_zone_to_diff(rb_str_new2(s1)));
1869
+ ALLOCV_END(vbuf);
1870
+ }
1871
+ RB_GC_GUARD(s5);
1872
+ }
1873
+
1874
+ return 1;
1875
+ }
1876
+
1877
+ static int
1878
+ parse_ddd(VALUE str, VALUE hash)
1879
+ {
1880
+ static const char pat_source[] =
1881
+ #ifdef TIGHT_PARSER
1882
+ BOS
1883
+ #endif
1884
+ "([-+]?)(\\d{2,14})"
1885
+ "(?:"
1886
+ "\\s*"
1887
+ "t?"
1888
+ "\\s*"
1889
+ "(\\d{2,6})?(?:[,.](\\d*))?"
1890
+ ")?"
1891
+ "(?:"
1892
+ "\\s*"
1893
+ "("
1894
+ "z\\b"
1895
+ "|"
1896
+ "[-+]\\d{1,4}\\b"
1897
+ "|"
1898
+ "\\[[-+]?\\d[^\\]]*\\]"
1899
+ ")"
1900
+ ")?"
1901
+ #ifdef TIGHT_PARSER
1902
+ EOS
1903
+ #endif
1904
+ ;
1905
+ static VALUE pat = Qnil;
1906
+
1907
+ REGCOMP_I(pat);
1908
+ SUBS(str, pat, parse_ddd_cb);
1909
+ }
1910
+
1911
+ #ifndef TIGHT_PARSER
1912
+ static int
1913
+ parse_bc_cb(VALUE m, VALUE hash)
1914
+ {
1915
+ set_hash("_bc", Qtrue);
1916
+ return 1;
1917
+ }
1918
+
1919
+ static int
1920
+ parse_bc(VALUE str, VALUE hash)
1921
+ {
1922
+ static const char pat_source[] =
1923
+ "\\b(bc\\b|bce\\b|b\\.c\\.|b\\.c\\.e\\.)";
1924
+ static VALUE pat = Qnil;
1925
+
1926
+ REGCOMP_I(pat);
1927
+ SUBS(str, pat, parse_bc_cb);
1928
+ }
1929
+
1930
+ static int
1931
+ parse_frag_cb(VALUE m, VALUE hash)
1932
+ {
1933
+ VALUE s, n;
1934
+
1935
+ s = rb_reg_nth_match(1, m);
1936
+
1937
+ if (!NIL_P(ref_hash("hour")) && NIL_P(ref_hash("mday"))) {
1938
+ n = str2num(s);
1939
+ if (f_ge_p(n, INT2FIX(1)) &&
1940
+ f_le_p(n, INT2FIX(31)))
1941
+ set_hash("mday", n);
1942
+ }
1943
+ if (!NIL_P(ref_hash("mday")) && NIL_P(ref_hash("hour"))) {
1944
+ n = str2num(s);
1945
+ if (f_ge_p(n, INT2FIX(0)) &&
1946
+ f_le_p(n, INT2FIX(24)))
1947
+ set_hash("hour", n);
1948
+ }
1949
+
1950
+ return 1;
1951
+ }
1952
+
1953
+ static int
1954
+ parse_frag(VALUE str, VALUE hash)
1955
+ {
1956
+ static const char pat_source[] = "\\A\\s*(\\d{1,2})\\s*\\z";
1957
+ static VALUE pat = Qnil;
1958
+
1959
+ REGCOMP_I(pat);
1960
+ SUBS(str, pat, parse_frag_cb);
1961
+ }
1962
+ #endif
1963
+
1964
+ #ifdef TIGHT_PARSER
1965
+ static int
1966
+ parse_dummy_cb(VALUE m, VALUE hash)
1967
+ {
1968
+ return 1;
1969
+ }
1970
+
1971
+ static int
1972
+ parse_wday_only(VALUE str, VALUE hash)
1973
+ {
1974
+ static const char pat_source[] = "\\A\\s*" FPW "\\s*\\z";
1975
+ static VALUE pat = Qnil;
1976
+
1977
+ REGCOMP_0(pat);
1978
+ SUBS(str, pat, parse_dummy_cb);
1979
+ }
1980
+
1981
+ static int
1982
+ parse_time_only(VALUE str, VALUE hash)
1983
+ {
1984
+ static const char pat_source[] = "\\A\\s*" FPT "\\s*\\z";
1985
+ static VALUE pat = Qnil;
1986
+
1987
+ REGCOMP_0(pat);
1988
+ SUBS(str, pat, parse_dummy_cb);
1989
+ }
1990
+
1991
+ static int
1992
+ parse_wday_and_time(VALUE str, VALUE hash)
1993
+ {
1994
+ static const char pat_source[] = "\\A\\s*(" FPW "\\s+" FPT "|" FPT "\\s+" FPW ")\\s*\\z";
1995
+ static VALUE pat = Qnil;
1996
+
1997
+ REGCOMP_0(pat);
1998
+ SUBS(str, pat, parse_dummy_cb);
1999
+ }
2000
+
2001
+ static unsigned
2002
+ have_invalid_char_p(VALUE s)
2003
+ {
2004
+ long i;
2005
+
2006
+ for (i = 0; i < RSTRING_LEN(s); i++)
2007
+ if (iscntrl((unsigned char)RSTRING_PTR(s)[i]) &&
2008
+ !isspace((unsigned char)RSTRING_PTR(s)[i]))
2009
+ return 1;
2010
+ return 0;
2011
+ }
2012
+ #endif
2013
+
2014
+ #define HAVE_ALPHA (1<<0)
2015
+ #define HAVE_DIGIT (1<<1)
2016
+ #define HAVE_DASH (1<<2)
2017
+ #define HAVE_DOT (1<<3)
2018
+ #define HAVE_SLASH (1<<4)
2019
+
2020
+ static unsigned
2021
+ check_class(VALUE s)
2022
+ {
2023
+ unsigned flags;
2024
+ long i;
2025
+
2026
+ flags = 0;
2027
+ for (i = 0; i < RSTRING_LEN(s); i++) {
2028
+ if (isalpha((unsigned char)RSTRING_PTR(s)[i]))
2029
+ flags |= HAVE_ALPHA;
2030
+ if (isdigit((unsigned char)RSTRING_PTR(s)[i]))
2031
+ flags |= HAVE_DIGIT;
2032
+ if (RSTRING_PTR(s)[i] == '-')
2033
+ flags |= HAVE_DASH;
2034
+ if (RSTRING_PTR(s)[i] == '.')
2035
+ flags |= HAVE_DOT;
2036
+ if (RSTRING_PTR(s)[i] == '/')
2037
+ flags |= HAVE_SLASH;
2038
+ }
2039
+ return flags;
2040
+ }
2041
+
2042
+ #define HAVE_ELEM_P(x) ((check_class(str) & (x)) == (x))
2043
+
2044
+ #ifdef TIGHT_PARSER
2045
+ #define PARSER_ERROR return rb_hash_new()
2046
+ #endif
2047
+
2048
+ VALUE
2049
+ date__parse(VALUE str, VALUE comp)
2050
+ {
2051
+ VALUE backref, hash;
2052
+
2053
+ #ifdef TIGHT_PARSER
2054
+ if (have_invalid_char_p(str))
2055
+ PARSER_ERROR;
2056
+ #endif
2057
+
2058
+ backref = rb_backref_get();
2059
+ rb_match_busy(backref);
2060
+
2061
+ {
2062
+ static const char pat_source[] =
2063
+ #ifndef TIGHT_PARSER
2064
+ "[^-+',./:@[:alnum:]\\[\\]]+"
2065
+ #else
2066
+ "[^[:graph:]]+"
2067
+ #endif
2068
+ ;
2069
+ static VALUE pat = Qnil;
2070
+
2071
+ REGCOMP_0(pat);
2072
+ str = rb_str_dup(str);
2073
+ f_gsub_bang(str, pat, asp_string());
2074
+ }
2075
+
2076
+ hash = rb_hash_new();
2077
+ set_hash("_comp", comp);
2078
+
2079
+ if (HAVE_ELEM_P(HAVE_ALPHA))
2080
+ parse_day(str, hash);
2081
+ if (HAVE_ELEM_P(HAVE_DIGIT))
2082
+ parse_time(str, hash);
2083
+
2084
+ #ifdef TIGHT_PARSER
2085
+ if (HAVE_ELEM_P(HAVE_ALPHA))
2086
+ parse_era(str, hash);
2087
+ #endif
2088
+
2089
+ if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT)) {
2090
+ if (parse_eu(str, hash))
2091
+ goto ok;
2092
+ if (parse_us(str, hash))
2093
+ goto ok;
2094
+ }
2095
+ if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DASH))
2096
+ if (parse_iso(str, hash))
2097
+ goto ok;
2098
+ if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT))
2099
+ if (parse_jis(str, hash))
2100
+ goto ok;
2101
+ if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_DASH))
2102
+ if (parse_vms(str, hash))
2103
+ goto ok;
2104
+ if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_SLASH))
2105
+ if (parse_sla(str, hash))
2106
+ goto ok;
2107
+ #ifdef TIGHT_PARSER
2108
+ if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_SLASH)) {
2109
+ if (parse_sla2(str, hash))
2110
+ goto ok;
2111
+ if (parse_sla3(str, hash))
2112
+ goto ok;
2113
+ }
2114
+ #endif
2115
+ if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT))
2116
+ if (parse_dot(str, hash))
2117
+ goto ok;
2118
+ #ifdef TIGHT_PARSER
2119
+ if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_DOT)) {
2120
+ if (parse_dot2(str, hash))
2121
+ goto ok;
2122
+ if (parse_dot3(str, hash))
2123
+ goto ok;
2124
+ }
2125
+ #endif
2126
+ if (HAVE_ELEM_P(HAVE_DIGIT))
2127
+ if (parse_iso2(str, hash))
2128
+ goto ok;
2129
+ if (HAVE_ELEM_P(HAVE_DIGIT))
2130
+ if (parse_year(str, hash))
2131
+ goto ok;
2132
+ if (HAVE_ELEM_P(HAVE_ALPHA))
2133
+ if (parse_mon(str, hash))
2134
+ goto ok;
2135
+ if (HAVE_ELEM_P(HAVE_DIGIT))
2136
+ if (parse_mday(str, hash))
2137
+ goto ok;
2138
+ if (HAVE_ELEM_P(HAVE_DIGIT))
2139
+ if (parse_ddd(str, hash))
2140
+ goto ok;
2141
+
2142
+ #ifdef TIGHT_PARSER
2143
+ if (parse_wday_only(str, hash))
2144
+ goto ok;
2145
+ if (parse_time_only(str, hash))
2146
+ goto ok;
2147
+ if (parse_wday_and_time(str, hash))
2148
+ goto ok;
2149
+
2150
+ PARSER_ERROR; /* not found */
2151
+ #endif
2152
+
2153
+ ok:
2154
+ #ifndef TIGHT_PARSER
2155
+ if (HAVE_ELEM_P(HAVE_ALPHA))
2156
+ parse_bc(str, hash);
2157
+ if (HAVE_ELEM_P(HAVE_DIGIT))
2158
+ parse_frag(str, hash);
2159
+ #endif
2160
+
2161
+ {
2162
+ if (RTEST(ref_hash("_bc"))) {
2163
+ VALUE y;
2164
+
2165
+ y = ref_hash("cwyear");
2166
+ if (!NIL_P(y)) {
2167
+ y = f_add(f_negate(y), INT2FIX(1));
2168
+ set_hash("cwyear", y);
2169
+ }
2170
+ y = ref_hash("year");
2171
+ if (!NIL_P(y)) {
2172
+ y = f_add(f_negate(y), INT2FIX(1));
2173
+ set_hash("year", y);
2174
+ }
2175
+ }
2176
+
2177
+ if (RTEST(ref_hash("_comp"))) {
2178
+ VALUE y;
2179
+
2180
+ y = ref_hash("cwyear");
2181
+ if (!NIL_P(y))
2182
+ if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
2183
+ if (f_ge_p(y, INT2FIX(69)))
2184
+ set_hash("cwyear", f_add(y, INT2FIX(1900)));
2185
+ else
2186
+ set_hash("cwyear", f_add(y, INT2FIX(2000)));
2187
+ }
2188
+ y = ref_hash("year");
2189
+ if (!NIL_P(y))
2190
+ if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
2191
+ if (f_ge_p(y, INT2FIX(69)))
2192
+ set_hash("year", f_add(y, INT2FIX(1900)));
2193
+ else
2194
+ set_hash("year", f_add(y, INT2FIX(2000)));
2195
+ }
2196
+ }
2197
+
2198
+ }
2199
+
2200
+ del_hash("_bc");
2201
+ del_hash("_comp");
2202
+
2203
+ {
2204
+ VALUE zone = ref_hash("zone");
2205
+ if (!NIL_P(zone) && NIL_P(ref_hash("offset")))
2206
+ set_hash("offset", date_zone_to_diff(zone));
2207
+ }
2208
+
2209
+ rb_backref_set(backref);
2210
+
2211
+ return hash;
2212
+ }
2213
+
2214
+ static VALUE
2215
+ comp_year69(VALUE y)
2216
+ {
2217
+ if (f_ge_p(y, INT2FIX(69)))
2218
+ return f_add(y, INT2FIX(1900));
2219
+ return f_add(y, INT2FIX(2000));
2220
+ }
2221
+
2222
+ static VALUE
2223
+ comp_year50(VALUE y)
2224
+ {
2225
+ if (f_ge_p(y, INT2FIX(50)))
2226
+ return f_add(y, INT2FIX(1900));
2227
+ return f_add(y, INT2FIX(2000));
2228
+ }
2229
+
2230
+ static VALUE
2231
+ sec_fraction(VALUE f)
2232
+ {
2233
+ return rb_rational_new2(str2num(f),
2234
+ f_expt(INT2FIX(10),
2235
+ LONG2NUM(RSTRING_LEN(f))));
2236
+ }
2237
+
2238
+ #define SNUM 14
2239
+
2240
+ static int
2241
+ iso8601_ext_datetime_cb(VALUE m, VALUE hash)
2242
+ {
2243
+ VALUE s[SNUM + 1], y;
2244
+
2245
+ {
2246
+ int i;
2247
+ s[0] = Qnil;
2248
+ for (i = 1; i <= SNUM; i++)
2249
+ s[i] = rb_reg_nth_match(i, m);
2250
+ }
2251
+
2252
+ if (!NIL_P(s[3])) {
2253
+ set_hash("mday", str2num(s[3]));
2254
+ if (strcmp(RSTRING_PTR(s[1]), "-") != 0) {
2255
+ y = str2num(s[1]);
2256
+ if (RSTRING_LEN(s[1]) < 4)
2257
+ y = comp_year69(y);
2258
+ set_hash("year", y);
2259
+ }
2260
+ if (NIL_P(s[2])) {
2261
+ if (strcmp(RSTRING_PTR(s[1]), "-") != 0)
2262
+ return 0;
2263
+ }
2264
+ else
2265
+ set_hash("mon", str2num(s[2]));
2266
+ }
2267
+ else if (!NIL_P(s[5])) {
2268
+ set_hash("yday", str2num(s[5]));
2269
+ if (!NIL_P(s[4])) {
2270
+ y = str2num(s[4]);
2271
+ if (RSTRING_LEN(s[4]) < 4)
2272
+ y = comp_year69(y);
2273
+ set_hash("year", y);
2274
+ }
2275
+ }
2276
+ else if (!NIL_P(s[8])) {
2277
+ set_hash("cweek", str2num(s[7]));
2278
+ set_hash("cwday", str2num(s[8]));
2279
+ if (!NIL_P(s[6])) {
2280
+ y = str2num(s[6]);
2281
+ if (RSTRING_LEN(s[6]) < 4)
2282
+ y = comp_year69(y);
2283
+ set_hash("cwyear", y);
2284
+ }
2285
+ }
2286
+ else if (!NIL_P(s[9])) {
2287
+ set_hash("cwday", str2num(s[9]));
2288
+ }
2289
+ if (!NIL_P(s[10])) {
2290
+ set_hash("hour", str2num(s[10]));
2291
+ set_hash("min", str2num(s[11]));
2292
+ if (!NIL_P(s[12]))
2293
+ set_hash("sec", str2num(s[12]));
2294
+ }
2295
+ if (!NIL_P(s[13])) {
2296
+ set_hash("sec_fraction", sec_fraction(s[13]));
2297
+ }
2298
+ if (!NIL_P(s[14])) {
2299
+ set_hash("zone", s[14]);
2300
+ set_hash("offset", date_zone_to_diff(s[14]));
2301
+ }
2302
+
2303
+ return 1;
2304
+ }
2305
+
2306
+ static int
2307
+ iso8601_ext_datetime(VALUE str, VALUE hash)
2308
+ {
2309
+ static const char pat_source[] =
2310
+ "\\A\\s*(?:([-+]?\\d{2,}|-)-(\\d{2})?-(\\d{2})|"
2311
+ "([-+]?\\d{2,})?-(\\d{3})|"
2312
+ "(\\d{4}|\\d{2})?-w(\\d{2})-(\\d)|"
2313
+ "-w-(\\d))"
2314
+ "(?:t"
2315
+ "(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?"
2316
+ "(z|[-+]\\d{2}(?::?\\d{2})?)?)?\\s*\\z";
2317
+ static VALUE pat = Qnil;
2318
+
2319
+ REGCOMP_I(pat);
2320
+ MATCH(str, pat, iso8601_ext_datetime_cb);
2321
+ }
2322
+
2323
+ #undef SNUM
2324
+ #define SNUM 17
2325
+
2326
+ static int
2327
+ iso8601_bas_datetime_cb(VALUE m, VALUE hash)
2328
+ {
2329
+ VALUE s[SNUM + 1], y;
2330
+
2331
+ {
2332
+ int i;
2333
+ s[0] = Qnil;
2334
+ for (i = 1; i <= SNUM; i++)
2335
+ s[i] = rb_reg_nth_match(i, m);
2336
+ }
2337
+
2338
+ if (!NIL_P(s[3])) {
2339
+ set_hash("mday", str2num(s[3]));
2340
+ if (strcmp(RSTRING_PTR(s[1]), "--") != 0) {
2341
+ y = str2num(s[1]);
2342
+ if (RSTRING_LEN(s[1]) < 4)
2343
+ y = comp_year69(y);
2344
+ set_hash("year", y);
2345
+ }
2346
+ if (*RSTRING_PTR(s[2]) == '-') {
2347
+ if (strcmp(RSTRING_PTR(s[1]), "--") != 0)
2348
+ return 0;
2349
+ }
2350
+ else
2351
+ set_hash("mon", str2num(s[2]));
2352
+ }
2353
+ else if (!NIL_P(s[5])) {
2354
+ set_hash("yday", str2num(s[5]));
2355
+ y = str2num(s[4]);
2356
+ if (RSTRING_LEN(s[4]) < 4)
2357
+ y = comp_year69(y);
2358
+ set_hash("year", y);
2359
+ }
2360
+ else if (!NIL_P(s[6])) {
2361
+ set_hash("yday", str2num(s[6]));
2362
+ }
2363
+ else if (!NIL_P(s[9])) {
2364
+ set_hash("cweek", str2num(s[8]));
2365
+ set_hash("cwday", str2num(s[9]));
2366
+ y = str2num(s[7]);
2367
+ if (RSTRING_LEN(s[7]) < 4)
2368
+ y = comp_year69(y);
2369
+ set_hash("cwyear", y);
2370
+ }
2371
+ else if (!NIL_P(s[11])) {
2372
+ set_hash("cweek", str2num(s[10]));
2373
+ set_hash("cwday", str2num(s[11]));
2374
+ }
2375
+ else if (!NIL_P(s[12])) {
2376
+ set_hash("cwday", str2num(s[12]));
2377
+ }
2378
+ if (!NIL_P(s[13])) {
2379
+ set_hash("hour", str2num(s[13]));
2380
+ set_hash("min", str2num(s[14]));
2381
+ if (!NIL_P(s[15]))
2382
+ set_hash("sec", str2num(s[15]));
2383
+ }
2384
+ if (!NIL_P(s[16])) {
2385
+ set_hash("sec_fraction", sec_fraction(s[16]));
2386
+ }
2387
+ if (!NIL_P(s[17])) {
2388
+ set_hash("zone", s[17]);
2389
+ set_hash("offset", date_zone_to_diff(s[17]));
2390
+ }
2391
+
2392
+ return 1;
2393
+ }
2394
+
2395
+ static int
2396
+ iso8601_bas_datetime(VALUE str, VALUE hash)
2397
+ {
2398
+ static const char pat_source[] =
2399
+ "\\A\\s*(?:([-+]?(?:\\d{4}|\\d{2})|--)(\\d{2}|-)(\\d{2})|"
2400
+ "([-+]?(?:\\d{4}|\\d{2}))(\\d{3})|"
2401
+ "-(\\d{3})|"
2402
+ "(\\d{4}|\\d{2})w(\\d{2})(\\d)|"
2403
+ "-w(\\d{2})(\\d)|"
2404
+ "-w-(\\d))"
2405
+ "(?:t?"
2406
+ "(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?"
2407
+ "(z|[-+]\\d{2}(?:\\d{2})?)?)?\\s*\\z";
2408
+ static VALUE pat = Qnil;
2409
+
2410
+ REGCOMP_I(pat);
2411
+ MATCH(str, pat, iso8601_bas_datetime_cb);
2412
+ }
2413
+
2414
+ #undef SNUM
2415
+ #define SNUM 5
2416
+
2417
+ static int
2418
+ iso8601_ext_time_cb(VALUE m, VALUE hash)
2419
+ {
2420
+ VALUE s[SNUM + 1];
2421
+
2422
+ {
2423
+ int i;
2424
+ s[0] = Qnil;
2425
+ for (i = 1; i <= SNUM; i++)
2426
+ s[i] = rb_reg_nth_match(i, m);
2427
+ }
2428
+
2429
+ set_hash("hour", str2num(s[1]));
2430
+ set_hash("min", str2num(s[2]));
2431
+ if (!NIL_P(s[3]))
2432
+ set_hash("sec", str2num(s[3]));
2433
+ if (!NIL_P(s[4]))
2434
+ set_hash("sec_fraction", sec_fraction(s[4]));
2435
+ if (!NIL_P(s[5])) {
2436
+ set_hash("zone", s[5]);
2437
+ set_hash("offset", date_zone_to_diff(s[5]));
2438
+ }
2439
+
2440
+ return 1;
2441
+ }
2442
+
2443
+ #define iso8601_bas_time_cb iso8601_ext_time_cb
2444
+
2445
+ static int
2446
+ iso8601_ext_time(VALUE str, VALUE hash)
2447
+ {
2448
+ static const char pat_source[] =
2449
+ "\\A\\s*(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?"
2450
+ "(z|[-+]\\d{2}(:?\\d{2})?)?)?\\s*\\z";
2451
+ static VALUE pat = Qnil;
2452
+
2453
+ REGCOMP_I(pat);
2454
+ MATCH(str, pat, iso8601_ext_time_cb);
2455
+ }
2456
+
2457
+ static int
2458
+ iso8601_bas_time(VALUE str, VALUE hash)
2459
+ {
2460
+ static const char pat_source[] =
2461
+ "\\A\\s*(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?"
2462
+ "(z|[-+]\\d{2}(\\d{2})?)?)?\\s*\\z";
2463
+ static VALUE pat = Qnil;
2464
+
2465
+ REGCOMP_I(pat);
2466
+ MATCH(str, pat, iso8601_bas_time_cb);
2467
+ }
2468
+
2469
+ VALUE
2470
+ date__iso8601(VALUE str)
2471
+ {
2472
+ VALUE backref, hash;
2473
+
2474
+ backref = rb_backref_get();
2475
+ rb_match_busy(backref);
2476
+
2477
+ hash = rb_hash_new();
2478
+
2479
+ if (iso8601_ext_datetime(str, hash))
2480
+ goto ok;
2481
+ if (iso8601_bas_datetime(str, hash))
2482
+ goto ok;
2483
+ if (iso8601_ext_time(str, hash))
2484
+ goto ok;
2485
+ if (iso8601_bas_time(str, hash))
2486
+ goto ok;
2487
+
2488
+ ok:
2489
+ rb_backref_set(backref);
2490
+
2491
+ return hash;
2492
+ }
2493
+
2494
+ #undef SNUM
2495
+ #define SNUM 8
2496
+
2497
+ static int
2498
+ rfc3339_cb(VALUE m, VALUE hash)
2499
+ {
2500
+ VALUE s[SNUM + 1];
2501
+
2502
+ {
2503
+ int i;
2504
+ s[0] = Qnil;
2505
+ for (i = 1; i <= SNUM; i++)
2506
+ s[i] = rb_reg_nth_match(i, m);
2507
+ }
2508
+
2509
+ set_hash("year", str2num(s[1]));
2510
+ set_hash("mon", str2num(s[2]));
2511
+ set_hash("mday", str2num(s[3]));
2512
+ set_hash("hour", str2num(s[4]));
2513
+ set_hash("min", str2num(s[5]));
2514
+ set_hash("sec", str2num(s[6]));
2515
+ set_hash("zone", s[8]);
2516
+ set_hash("offset", date_zone_to_diff(s[8]));
2517
+ if (!NIL_P(s[7]))
2518
+ set_hash("sec_fraction", sec_fraction(s[7]));
2519
+
2520
+ return 1;
2521
+ }
2522
+
2523
+ static int
2524
+ rfc3339(VALUE str, VALUE hash)
2525
+ {
2526
+ static const char pat_source[] =
2527
+ "\\A\\s*(-?\\d{4})-(\\d{2})-(\\d{2})"
2528
+ "(?:t|\\s)"
2529
+ "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
2530
+ "(z|[-+]\\d{2}:\\d{2})\\s*\\z";
2531
+ static VALUE pat = Qnil;
2532
+
2533
+ REGCOMP_I(pat);
2534
+ MATCH(str, pat, rfc3339_cb);
2535
+ }
2536
+
2537
+ VALUE
2538
+ date__rfc3339(VALUE str)
2539
+ {
2540
+ VALUE backref, hash;
2541
+
2542
+ backref = rb_backref_get();
2543
+ rb_match_busy(backref);
2544
+
2545
+ hash = rb_hash_new();
2546
+ rfc3339(str, hash);
2547
+ rb_backref_set(backref);
2548
+ return hash;
2549
+ }
2550
+
2551
+ #undef SNUM
2552
+ #define SNUM 8
2553
+
2554
+ static int
2555
+ xmlschema_datetime_cb(VALUE m, VALUE hash)
2556
+ {
2557
+ VALUE s[SNUM + 1];
2558
+
2559
+ {
2560
+ int i;
2561
+ s[0] = Qnil;
2562
+ for (i = 1; i <= SNUM; i++)
2563
+ s[i] = rb_reg_nth_match(i, m);
2564
+ }
2565
+
2566
+ set_hash("year", str2num(s[1]));
2567
+ if (!NIL_P(s[2]))
2568
+ set_hash("mon", str2num(s[2]));
2569
+ if (!NIL_P(s[3]))
2570
+ set_hash("mday", str2num(s[3]));
2571
+ if (!NIL_P(s[4]))
2572
+ set_hash("hour", str2num(s[4]));
2573
+ if (!NIL_P(s[5]))
2574
+ set_hash("min", str2num(s[5]));
2575
+ if (!NIL_P(s[6]))
2576
+ set_hash("sec", str2num(s[6]));
2577
+ if (!NIL_P(s[7]))
2578
+ set_hash("sec_fraction", sec_fraction(s[7]));
2579
+ if (!NIL_P(s[8])) {
2580
+ set_hash("zone", s[8]);
2581
+ set_hash("offset", date_zone_to_diff(s[8]));
2582
+ }
2583
+
2584
+ return 1;
2585
+ }
2586
+
2587
+ static int
2588
+ xmlschema_datetime(VALUE str, VALUE hash)
2589
+ {
2590
+ static const char pat_source[] =
2591
+ "\\A\\s*(-?\\d{4,})(?:-(\\d{2})(?:-(\\d{2}))?)?"
2592
+ "(?:t"
2593
+ "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?"
2594
+ "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
2595
+ static VALUE pat = Qnil;
2596
+
2597
+ REGCOMP_I(pat);
2598
+ MATCH(str, pat, xmlschema_datetime_cb);
2599
+ }
2600
+
2601
+ #undef SNUM
2602
+ #define SNUM 5
2603
+
2604
+ static int
2605
+ xmlschema_time_cb(VALUE m, VALUE hash)
2606
+ {
2607
+ VALUE s[SNUM + 1];
2608
+
2609
+ {
2610
+ int i;
2611
+ s[0] = Qnil;
2612
+ for (i = 1; i <= SNUM; i++)
2613
+ s[i] = rb_reg_nth_match(i, m);
2614
+ }
2615
+
2616
+ set_hash("hour", str2num(s[1]));
2617
+ set_hash("min", str2num(s[2]));
2618
+ if (!NIL_P(s[3]))
2619
+ set_hash("sec", str2num(s[3]));
2620
+ if (!NIL_P(s[4]))
2621
+ set_hash("sec_fraction", sec_fraction(s[4]));
2622
+ if (!NIL_P(s[5])) {
2623
+ set_hash("zone", s[5]);
2624
+ set_hash("offset", date_zone_to_diff(s[5]));
2625
+ }
2626
+
2627
+ return 1;
2628
+ }
2629
+
2630
+ static int
2631
+ xmlschema_time(VALUE str, VALUE hash)
2632
+ {
2633
+ static const char pat_source[] =
2634
+ "\\A\\s*(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
2635
+ "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
2636
+ static VALUE pat = Qnil;
2637
+
2638
+ REGCOMP_I(pat);
2639
+ MATCH(str, pat, xmlschema_time_cb);
2640
+ }
2641
+
2642
+ #undef SNUM
2643
+ #define SNUM 4
2644
+
2645
+ static int
2646
+ xmlschema_trunc_cb(VALUE m, VALUE hash)
2647
+ {
2648
+ VALUE s[SNUM + 1];
2649
+
2650
+ {
2651
+ int i;
2652
+ s[0] = Qnil;
2653
+ for (i = 1; i <= SNUM; i++)
2654
+ s[i] = rb_reg_nth_match(i, m);
2655
+ }
2656
+
2657
+ if (!NIL_P(s[1]))
2658
+ set_hash("mon", str2num(s[1]));
2659
+ if (!NIL_P(s[2]))
2660
+ set_hash("mday", str2num(s[2]));
2661
+ if (!NIL_P(s[3]))
2662
+ set_hash("mday", str2num(s[3]));
2663
+ if (!NIL_P(s[4])) {
2664
+ set_hash("zone", s[4]);
2665
+ set_hash("offset", date_zone_to_diff(s[4]));
2666
+ }
2667
+
2668
+ return 1;
2669
+ }
2670
+
2671
+ static int
2672
+ xmlschema_trunc(VALUE str, VALUE hash)
2673
+ {
2674
+ static const char pat_source[] =
2675
+ "\\A\\s*(?:--(\\d{2})(?:-(\\d{2}))?|---(\\d{2}))"
2676
+ "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
2677
+ static VALUE pat = Qnil;
2678
+
2679
+ REGCOMP_I(pat);
2680
+ MATCH(str, pat, xmlschema_trunc_cb);
2681
+ }
2682
+
2683
+ VALUE
2684
+ date__xmlschema(VALUE str)
2685
+ {
2686
+ VALUE backref, hash;
2687
+
2688
+ backref = rb_backref_get();
2689
+ rb_match_busy(backref);
2690
+
2691
+ hash = rb_hash_new();
2692
+
2693
+ if (xmlschema_datetime(str, hash))
2694
+ goto ok;
2695
+ if (xmlschema_time(str, hash))
2696
+ goto ok;
2697
+ if (xmlschema_trunc(str, hash))
2698
+ goto ok;
2699
+
2700
+ ok:
2701
+ rb_backref_set(backref);
2702
+
2703
+ return hash;
2704
+ }
2705
+
2706
+ #undef SNUM
2707
+ #define SNUM 8
2708
+
2709
+ static int
2710
+ rfc2822_cb(VALUE m, VALUE hash)
2711
+ {
2712
+ VALUE s[SNUM + 1], y;
2713
+
2714
+ {
2715
+ int i;
2716
+ s[0] = Qnil;
2717
+ for (i = 1; i <= SNUM; i++)
2718
+ s[i] = rb_reg_nth_match(i, m);
2719
+ }
2720
+
2721
+ if (!NIL_P(s[1])) {
2722
+ set_hash("wday", INT2FIX(day_num(s[1])));
2723
+ }
2724
+ set_hash("mday", str2num(s[2]));
2725
+ set_hash("mon", INT2FIX(mon_num(s[3])));
2726
+ y = str2num(s[4]);
2727
+ if (RSTRING_LEN(s[4]) < 4)
2728
+ y = comp_year50(y);
2729
+ set_hash("year", y);
2730
+ set_hash("hour", str2num(s[5]));
2731
+ set_hash("min", str2num(s[6]));
2732
+ if (!NIL_P(s[7]))
2733
+ set_hash("sec", str2num(s[7]));
2734
+ set_hash("zone", s[8]);
2735
+ set_hash("offset", date_zone_to_diff(s[8]));
2736
+
2737
+ return 1;
2738
+ }
2739
+
2740
+ static int
2741
+ rfc2822(VALUE str, VALUE hash)
2742
+ {
2743
+ static const char pat_source[] =
2744
+ "\\A\\s*(?:(" ABBR_DAYS ")\\s*,\\s+)?"
2745
+ "(\\d{1,2})\\s+"
2746
+ "(" ABBR_MONTHS ")\\s+"
2747
+ "(-?\\d{2,})\\s+"
2748
+ "(\\d{2}):(\\d{2})(?::(\\d{2}))?\\s*"
2749
+ "([-+]\\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\\s*\\z";
2750
+ static VALUE pat = Qnil;
2751
+
2752
+ REGCOMP_I(pat);
2753
+ MATCH(str, pat, rfc2822_cb);
2754
+ }
2755
+
2756
+ VALUE
2757
+ date__rfc2822(VALUE str)
2758
+ {
2759
+ VALUE backref, hash;
2760
+
2761
+ backref = rb_backref_get();
2762
+ rb_match_busy(backref);
2763
+
2764
+ hash = rb_hash_new();
2765
+ rfc2822(str, hash);
2766
+ rb_backref_set(backref);
2767
+ return hash;
2768
+ }
2769
+
2770
+ #undef SNUM
2771
+ #define SNUM 8
2772
+
2773
+ static int
2774
+ httpdate_type1_cb(VALUE m, VALUE hash)
2775
+ {
2776
+ VALUE s[SNUM + 1];
2777
+
2778
+ {
2779
+ int i;
2780
+ s[0] = Qnil;
2781
+ for (i = 1; i <= SNUM; i++)
2782
+ s[i] = rb_reg_nth_match(i, m);
2783
+ }
2784
+
2785
+ set_hash("wday", INT2FIX(day_num(s[1])));
2786
+ set_hash("mday", str2num(s[2]));
2787
+ set_hash("mon", INT2FIX(mon_num(s[3])));
2788
+ set_hash("year", str2num(s[4]));
2789
+ set_hash("hour", str2num(s[5]));
2790
+ set_hash("min", str2num(s[6]));
2791
+ set_hash("sec", str2num(s[7]));
2792
+ set_hash("zone", s[8]);
2793
+ set_hash("offset", INT2FIX(0));
2794
+
2795
+ return 1;
2796
+ }
2797
+
2798
+ static int
2799
+ httpdate_type1(VALUE str, VALUE hash)
2800
+ {
2801
+ static const char pat_source[] =
2802
+ "\\A\\s*(" ABBR_DAYS ")\\s*,\\s+"
2803
+ "(\\d{2})\\s+"
2804
+ "(" ABBR_MONTHS ")\\s+"
2805
+ "(-?\\d{4})\\s+"
2806
+ "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
2807
+ "(gmt)\\s*\\z";
2808
+ static VALUE pat = Qnil;
2809
+
2810
+ REGCOMP_I(pat);
2811
+ MATCH(str, pat, httpdate_type1_cb);
2812
+ }
2813
+
2814
+ #undef SNUM
2815
+ #define SNUM 8
2816
+
2817
+ static int
2818
+ httpdate_type2_cb(VALUE m, VALUE hash)
2819
+ {
2820
+ VALUE s[SNUM + 1], y;
2821
+
2822
+ {
2823
+ int i;
2824
+ s[0] = Qnil;
2825
+ for (i = 1; i <= SNUM; i++)
2826
+ s[i] = rb_reg_nth_match(i, m);
2827
+ }
2828
+
2829
+ set_hash("wday", INT2FIX(day_num(s[1])));
2830
+ set_hash("mday", str2num(s[2]));
2831
+ set_hash("mon", INT2FIX(mon_num(s[3])));
2832
+ y = str2num(s[4]);
2833
+ if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99)))
2834
+ y = comp_year69(y);
2835
+ set_hash("year", y);
2836
+ set_hash("hour", str2num(s[5]));
2837
+ set_hash("min", str2num(s[6]));
2838
+ set_hash("sec", str2num(s[7]));
2839
+ set_hash("zone", s[8]);
2840
+ set_hash("offset", INT2FIX(0));
2841
+
2842
+ return 1;
2843
+ }
2844
+
2845
+ static int
2846
+ httpdate_type2(VALUE str, VALUE hash)
2847
+ {
2848
+ static const char pat_source[] =
2849
+ "\\A\\s*(" DAYS ")\\s*,\\s+"
2850
+ "(\\d{2})\\s*-\\s*"
2851
+ "(" ABBR_MONTHS ")\\s*-\\s*"
2852
+ "(\\d{2})\\s+"
2853
+ "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
2854
+ "(gmt)\\s*\\z";
2855
+ static VALUE pat = Qnil;
2856
+
2857
+ REGCOMP_I(pat);
2858
+ MATCH(str, pat, httpdate_type2_cb);
2859
+ }
2860
+
2861
+ #undef SNUM
2862
+ #define SNUM 7
2863
+
2864
+ static int
2865
+ httpdate_type3_cb(VALUE m, VALUE hash)
2866
+ {
2867
+ VALUE s[SNUM + 1];
2868
+
2869
+ {
2870
+ int i;
2871
+ s[0] = Qnil;
2872
+ for (i = 1; i <= SNUM; i++)
2873
+ s[i] = rb_reg_nth_match(i, m);
2874
+ }
2875
+
2876
+ set_hash("wday", INT2FIX(day_num(s[1])));
2877
+ set_hash("mon", INT2FIX(mon_num(s[2])));
2878
+ set_hash("mday", str2num(s[3]));
2879
+ set_hash("hour", str2num(s[4]));
2880
+ set_hash("min", str2num(s[5]));
2881
+ set_hash("sec", str2num(s[6]));
2882
+ set_hash("year", str2num(s[7]));
2883
+
2884
+ return 1;
2885
+ }
2886
+
2887
+ static int
2888
+ httpdate_type3(VALUE str, VALUE hash)
2889
+ {
2890
+ static const char pat_source[] =
2891
+ "\\A\\s*(" ABBR_DAYS ")\\s+"
2892
+ "(" ABBR_MONTHS ")\\s+"
2893
+ "(\\d{1,2})\\s+"
2894
+ "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
2895
+ "(\\d{4})\\s*\\z";
2896
+ static VALUE pat = Qnil;
2897
+
2898
+ REGCOMP_I(pat);
2899
+ MATCH(str, pat, httpdate_type3_cb);
2900
+ }
2901
+
2902
+ VALUE
2903
+ date__httpdate(VALUE str)
2904
+ {
2905
+ VALUE backref, hash;
2906
+
2907
+ backref = rb_backref_get();
2908
+ rb_match_busy(backref);
2909
+
2910
+ hash = rb_hash_new();
2911
+
2912
+ if (httpdate_type1(str, hash))
2913
+ goto ok;
2914
+ if (httpdate_type2(str, hash))
2915
+ goto ok;
2916
+ if (httpdate_type3(str, hash))
2917
+ goto ok;
2918
+
2919
+ ok:
2920
+ rb_backref_set(backref);
2921
+
2922
+ return hash;
2923
+ }
2924
+
2925
+ #undef SNUM
2926
+ #define SNUM 9
2927
+
2928
+ static int
2929
+ jisx0301_cb(VALUE m, VALUE hash)
2930
+ {
2931
+ VALUE s[SNUM + 1];
2932
+ int ep;
2933
+
2934
+ {
2935
+ int i;
2936
+ s[0] = Qnil;
2937
+ for (i = 1; i <= SNUM; i++)
2938
+ s[i] = rb_reg_nth_match(i, m);
2939
+ }
2940
+
2941
+ ep = gengo(NIL_P(s[1]) ? 'h' : *RSTRING_PTR(s[1]));
2942
+ set_hash("year", f_add(str2num(s[2]), INT2FIX(ep)));
2943
+ set_hash("mon", str2num(s[3]));
2944
+ set_hash("mday", str2num(s[4]));
2945
+ if (!NIL_P(s[5])) {
2946
+ set_hash("hour", str2num(s[5]));
2947
+ if (!NIL_P(s[6]))
2948
+ set_hash("min", str2num(s[6]));
2949
+ if (!NIL_P(s[7]))
2950
+ set_hash("sec", str2num(s[7]));
2951
+ }
2952
+ if (!NIL_P(s[8]))
2953
+ set_hash("sec_fraction", sec_fraction(s[8]));
2954
+ if (!NIL_P(s[9])) {
2955
+ set_hash("zone", s[9]);
2956
+ set_hash("offset", date_zone_to_diff(s[9]));
2957
+ }
2958
+
2959
+ return 1;
2960
+ }
2961
+
2962
+ static int
2963
+ jisx0301(VALUE str, VALUE hash)
2964
+ {
2965
+ static const char pat_source[] =
2966
+ "\\A\\s*([mtsh])?(\\d{2})\\.(\\d{2})\\.(\\d{2})"
2967
+ "(?:t"
2968
+ "(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?"
2969
+ "(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z";
2970
+ static VALUE pat = Qnil;
2971
+
2972
+ REGCOMP_I(pat);
2973
+ MATCH(str, pat, jisx0301_cb);
2974
+ }
2975
+
2976
+ VALUE
2977
+ date__jisx0301(VALUE str)
2978
+ {
2979
+ VALUE backref, hash;
2980
+
2981
+ backref = rb_backref_get();
2982
+ rb_match_busy(backref);
2983
+
2984
+ hash = rb_hash_new();
2985
+ if (jisx0301(str, hash))
2986
+ goto ok;
2987
+ hash = date__iso8601(str);
2988
+
2989
+ ok:
2990
+ rb_backref_set(backref);
2991
+ return hash;
2992
+ }
2993
+
2994
+ /*
2995
+ Local variables:
2996
+ c-file-style: "ruby"
2997
+ End:
2998
+ */