date 1.0.0 → 3.1.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.

@@ -40,9 +40,9 @@ RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int bas
40
40
  #define f_sub_bang(s,r,x) rb_funcall(s, rb_intern("sub!"), 2, r, x)
41
41
  #define f_gsub_bang(s,r,x) rb_funcall(s, rb_intern("gsub!"), 2, r, x)
42
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)))
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
46
 
47
47
  #define cstr2num(s) rb_cstr_to_inum(s, 10, 0)
48
48
  #define str2num(s) rb_str_to_inum(s, 10, 0)
@@ -66,7 +66,13 @@ static const char abbr_months[][4] = {
66
66
  #define asubt_string() rb_str_new("\024", 1)
67
67
  #endif
68
68
 
69
- #define DECDIGIT "0123456789"
69
+ static size_t
70
+ digit_span(const char *s, const char *e)
71
+ {
72
+ size_t i = 0;
73
+ while (s + i < e && isdigit((unsigned char)s[i])) i++;
74
+ return i;
75
+ }
70
76
 
71
77
  static void
72
78
  s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
@@ -92,7 +98,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
92
98
  y = d;
93
99
  d = Qnil;
94
100
  }
95
- if (!NIL_P(d) && *RSTRING_PTR(d) == '\'') {
101
+ if (!NIL_P(d) && RSTRING_LEN(d) > 0 && *RSTRING_PTR(d) == '\'') {
96
102
  y = d;
97
103
  d = Qnil;
98
104
  }
@@ -103,17 +109,20 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
103
109
  size_t l;
104
110
 
105
111
  s = RSTRING_PTR(y);
106
- while (!issign((unsigned char)*s) && !isdigit((unsigned char)*s))
112
+ ep = RSTRING_END(y);
113
+ while (s < ep && !issign(*s) && !isdigit((unsigned char)*s))
107
114
  s++;
115
+ if (s >= ep) goto no_date;
108
116
  bp = s;
109
117
  if (issign((unsigned char)*s))
110
118
  s++;
111
- l = strspn(s, DECDIGIT);
119
+ l = digit_span(s, ep);
112
120
  ep = s + l;
113
121
  if (*ep) {
114
122
  y = d;
115
123
  d = rb_str_new(bp, ep - bp);
116
124
  }
125
+ no_date:;
117
126
  }
118
127
 
119
128
  if (!NIL_P(m)) {
@@ -152,8 +161,10 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
152
161
  VALUE iy;
153
162
 
154
163
  s = RSTRING_PTR(y);
155
- while (!issign((unsigned char)*s) && !isdigit((unsigned char)*s))
164
+ ep = RSTRING_END(y);
165
+ while (s < ep && !issign(*s) && !isdigit((unsigned char)*s))
156
166
  s++;
167
+ if (s >= ep) goto no_year;
157
168
  bp = s;
158
169
  if (issign(*s)) {
159
170
  s++;
@@ -161,7 +172,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
161
172
  }
162
173
  if (sign)
163
174
  c = Qfalse;
164
- l = strspn(s, DECDIGIT);
175
+ l = digit_span(s, ep);
165
176
  ep = s + l;
166
177
  if (l > 2)
167
178
  c = Qfalse;
@@ -175,6 +186,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
175
186
  ALLOCV_END(vbuf);
176
187
  }
177
188
  set_hash("year", iy);
189
+ no_year:;
178
190
  }
179
191
 
180
192
  if (bc)
@@ -186,10 +198,12 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
186
198
  VALUE im;
187
199
 
188
200
  s = RSTRING_PTR(m);
189
- while (!isdigit((unsigned char)*s))
201
+ ep = RSTRING_END(m);
202
+ while (s < ep && !isdigit((unsigned char)*s))
190
203
  s++;
204
+ if (s >= ep) goto no_month;
191
205
  bp = s;
192
- l = strspn(s, DECDIGIT);
206
+ l = digit_span(s, ep);
193
207
  ep = s + l;
194
208
  {
195
209
  char *buf;
@@ -201,6 +215,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
201
215
  ALLOCV_END(vbuf);
202
216
  }
203
217
  set_hash("mon", im);
218
+ no_month:;
204
219
  }
205
220
 
206
221
  if (!NIL_P(d)) {
@@ -209,10 +224,12 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
209
224
  VALUE id;
210
225
 
211
226
  s = RSTRING_PTR(d);
212
- while (!isdigit((unsigned char)*s))
227
+ ep = RSTRING_END(d);
228
+ while (s < ep && !isdigit((unsigned char)*s))
213
229
  s++;
230
+ if (s >= ep) goto no_mday;
214
231
  bp = s;
215
- l = strspn(s, DECDIGIT);
232
+ l = digit_span(s, ep);
216
233
  ep = s + l;
217
234
  {
218
235
  char *buf;
@@ -224,6 +241,7 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
224
241
  ALLOCV_END(vbuf);
225
242
  }
226
243
  set_hash("mday", id);
244
+ no_mday:;
227
245
  }
228
246
 
229
247
  if (!NIL_P(c))
@@ -258,23 +276,24 @@ regcomp(const char *source, long len, int opt)
258
276
  VALUE pat;
259
277
 
260
278
  pat = rb_reg_new(source, len, opt);
279
+ rb_obj_freeze(pat);
261
280
  rb_gc_register_mark_object(pat);
262
281
  return pat;
263
282
  }
264
283
 
265
284
  #define REGCOMP(pat,opt) \
266
- { \
285
+ do { \
267
286
  if (NIL_P(pat)) \
268
287
  pat = regcomp(pat##_source, sizeof pat##_source - 1, opt); \
269
- }
288
+ } while (0)
270
289
 
271
290
  #define REGCOMP_0(pat) REGCOMP(pat, 0)
272
291
  #define REGCOMP_I(pat) REGCOMP(pat, ONIG_OPTION_IGNORECASE)
273
292
 
274
293
  #define MATCH(s,p,c) \
275
- { \
294
+ do { \
276
295
  return match(s, p, hash, c); \
277
- }
296
+ } while (0)
278
297
 
279
298
  static int
280
299
  match(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
@@ -314,95 +333,119 @@ subx(VALUE str, VALUE rep, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
314
333
  }
315
334
 
316
335
  #define SUBS(s,p,c) \
317
- { \
336
+ do { \
318
337
  return subx(s, asp_string(), p, hash, c); \
319
- }
338
+ } while (0)
320
339
 
321
340
  #ifdef TIGHT_PARSER
322
341
  #define SUBA(s,p,c) \
323
- { \
342
+ do { \
324
343
  return subx(s, asuba_string(), p, hash, c); \
325
- }
344
+ } while (0)
326
345
 
327
346
  #define SUBB(s,p,c) \
328
- { \
347
+ do { \
329
348
  return subx(s, asubb_string(), p, hash, c); \
330
- }
349
+ } while (0)
331
350
 
332
351
  #define SUBW(s,p,c) \
333
- { \
352
+ do { \
334
353
  return subx(s, asubw_string(), p, hash, c); \
335
- }
354
+ } while (0)
336
355
 
337
356
  #define SUBT(s,p,c) \
338
- { \
357
+ do { \
339
358
  return subx(s, asubt_string(), p, hash, c); \
340
- }
359
+ } while (0)
341
360
  #endif
342
361
 
343
362
  #include "zonetab.h"
344
363
 
345
364
  static int
346
- str_end_with(const char *s, long l, const char *w)
365
+ str_end_with_word(const char *s, long l, const char *w)
347
366
  {
348
367
  int n = (int)strlen(w);
349
- return (l >= n && strncmp(s - n, w, n) == 0);
368
+ if (l <= n || !isspace((unsigned char)s[l - n - 1])) return 0;
369
+ if (strncasecmp(&s[l - n], w, n)) return 0;
370
+ do ++n; while (l > n && isspace((unsigned char)s[l - n - 1]));
371
+ return n;
350
372
  }
351
373
 
352
- VALUE
353
- date_zone_to_diff(VALUE str)
374
+ static long
375
+ shrunk_size(const char *s, long l)
354
376
  {
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;
377
+ long i, ni;
378
+ int sp = 0;
379
+ for (i = ni = 0; i < l; ++i) {
380
+ if (!isspace((unsigned char)s[i])) {
381
+ if (sp) ni++;
382
+ sp = 0;
383
+ ni++;
372
384
  }
373
385
  else {
374
- if (isalpha((unsigned char)s[i]))
375
- *d++ = tolower((unsigned char)s[i]);
376
- else
377
- *d++ = s[i];
378
- sp = 0;
386
+ sp = 1;
379
387
  }
380
388
  }
381
- if (d > dest) {
382
- if (*(d - 1) == ' ')
383
- --d;
384
- *d = '\0';
389
+ return ni < l ? ni : 0;
390
+ }
391
+
392
+ static long
393
+ shrink_space(char *d, const char *s, long l)
394
+ {
395
+ long i, ni;
396
+ int sp = 0;
397
+ for (i = ni = 0; i < l; ++i) {
398
+ if (!isspace((unsigned char)s[i])) {
399
+ if (sp) d[ni++] = ' ';
400
+ sp = 0;
401
+ d[ni++] = s[i];
402
+ }
403
+ else {
404
+ sp = 1;
405
+ }
385
406
  }
386
- l = d - dest;
387
- s = dest;
407
+ return ni;
408
+ }
409
+
410
+ VALUE
411
+ date_zone_to_diff(VALUE str)
412
+ {
413
+ VALUE offset = Qnil;
414
+ VALUE vbuf = 0;
415
+ long l = RSTRING_LEN(str);
416
+ const char *s = RSTRING_PTR(str);
417
+
388
418
  {
389
- static const char STD[] = " standard time";
390
- static const char DST1[] = " daylight time";
391
- static const char DST2[] = " dst";
392
419
  int dst = 0;
420
+ int w;
393
421
 
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;
422
+ if ((w = str_end_with_word(s, l, "time")) > 0) {
423
+ int wtime = w;
424
+ l -= w;
425
+ if ((w = str_end_with_word(s, l, "standard")) > 0) {
426
+ l -= w;
427
+ }
428
+ else if ((w = str_end_with_word(s, l, "daylight")) > 0) {
429
+ l -= w;
430
+ dst = 1;
431
+ }
432
+ else {
433
+ l += wtime;
434
+ }
400
435
  }
401
- else if (str_end_with(d, l, DST2)) {
402
- l -= sizeof(DST2) - 1;
436
+ else if ((w = str_end_with_word(s, l, "dst")) > 0) {
437
+ l -= w;
403
438
  dst = 1;
404
439
  }
405
440
  {
441
+ long sl = shrunk_size(s, l);
442
+ if (sl > 0 && sl <= MAX_WORD_LENGTH) {
443
+ char *d = ALLOCV_N(char, vbuf, sl);
444
+ l = shrink_space(d, s, l);
445
+ s = d;
446
+ }
447
+ }
448
+ if (l > 0 && l <= MAX_WORD_LENGTH) {
406
449
  const struct zone *z = zonetab(s, (unsigned int)l);
407
450
  if (z) {
408
451
  int d = z->offset;
@@ -418,8 +461,8 @@ date_zone_to_diff(VALUE str)
418
461
  long hour = 0, min = 0, sec = 0;
419
462
 
420
463
  if (l > 3 &&
421
- (strncmp(s, "gmt", 3) == 0 ||
422
- strncmp(s, "utc", 3) == 0)) {
464
+ (strncasecmp(s, "gmt", 3) == 0 ||
465
+ strncasecmp(s, "utc", 3) == 0)) {
423
466
  s += 3;
424
467
  l -= 3;
425
468
  }
@@ -706,16 +749,14 @@ parse_era(VALUE str, VALUE hash)
706
749
  static int
707
750
  check_year_width(VALUE y)
708
751
  {
709
- char *s;
710
- size_t l;
752
+ const char *s;
753
+ long l;
711
754
 
755
+ l = RSTRING_LEN(y);
756
+ if (l < 2) return 0;
712
757
  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;
758
+ if (!isdigit((unsigned char)s[1])) return 0;
759
+ return (l == 2 || !isdigit((unsigned char)s[2]));
719
760
  }
720
761
 
721
762
  static int
@@ -1196,6 +1237,9 @@ parse_iso2(VALUE str, VALUE hash)
1196
1237
  return 1;
1197
1238
  }
1198
1239
 
1240
+ #define JISX0301_ERA_INITIALS "mtshr"
1241
+ #define JISX0301_DEFAULT_ERA 'H' /* obsolete */
1242
+
1199
1243
  static int
1200
1244
  gengo(int c)
1201
1245
  {
@@ -1206,6 +1250,7 @@ gengo(int c)
1206
1250
  case 'T': case 't': e = 1911; break;
1207
1251
  case 'S': case 's': e = 1925; break;
1208
1252
  case 'H': case 'h': e = 1988; break;
1253
+ case 'R': case 'r': e = 2018; break;
1209
1254
  default: e = 0; break;
1210
1255
  }
1211
1256
  return e;
@@ -1236,11 +1281,11 @@ parse_jis(VALUE str, VALUE hash)
1236
1281
  {
1237
1282
  static const char pat_source[] =
1238
1283
  #ifndef TIGHT_PARSER
1239
- "\\b([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)"
1284
+ "\\b([" JISX0301_ERA_INITIALS "])(\\d+)\\.(\\d+)\\.(\\d+)"
1240
1285
  #else
1241
1286
  BOS
1242
1287
  FPW_COM FPT_COM
1243
- "([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)"
1288
+ "([" JISX0301_ERA_INITIALS "])(\\d+)\\.(\\d+)\\.(\\d+)"
1244
1289
  TEE_FPT COM_FPW
1245
1290
  EOS
1246
1291
  #endif
@@ -1843,30 +1888,26 @@ parse_ddd_cb(VALUE m, VALUE hash)
1843
1888
  set_hash("zone", s5);
1844
1889
 
1845
1890
  if (*cs5 == '[') {
1846
- VALUE vbuf = 0;
1847
- char *buf = ALLOCV_N(char, vbuf, l5 + 1);
1848
- char *s1, *s2, *s3;
1891
+ const char *s1, *s2;
1849
1892
  VALUE zone;
1850
1893
 
1851
- memcpy(buf, cs5, l5);
1852
- buf[l5 - 1] = '\0';
1853
-
1854
- s1 = buf + 1;
1855
- s2 = strchr(buf, ':');
1894
+ l5 -= 2;
1895
+ s1 = cs5 + 1;
1896
+ s2 = memchr(s1, ':', l5);
1856
1897
  if (s2) {
1857
- *s2 = '\0';
1858
1898
  s2++;
1899
+ zone = rb_str_subseq(s5, s2 - cs5, l5 - (s2 - s1));
1900
+ s5 = rb_str_subseq(s5, 1, s2 - s1);
1859
1901
  }
1860
- if (s2)
1861
- s3 = s2;
1862
- else
1863
- s3 = s1;
1864
- zone = rb_str_new2(s3);
1902
+ else {
1903
+ zone = rb_str_subseq(s5, 1, l5);
1904
+ if (isdigit((unsigned char)*s1))
1905
+ s5 = rb_str_append(rb_str_new_cstr("+"), zone);
1906
+ else
1907
+ s5 = zone;
1908
+ }
1865
1909
  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);
1910
+ set_hash("offset", date_zone_to_diff(s5));
1870
1911
  }
1871
1912
  RB_GC_GUARD(s5);
1872
1913
  }
@@ -2159,7 +2200,7 @@ date__parse(VALUE str, VALUE comp)
2159
2200
  #endif
2160
2201
 
2161
2202
  {
2162
- if (RTEST(ref_hash("_bc"))) {
2203
+ if (RTEST(del_hash("_bc"))) {
2163
2204
  VALUE y;
2164
2205
 
2165
2206
  y = ref_hash("cwyear");
@@ -2174,7 +2215,7 @@ date__parse(VALUE str, VALUE comp)
2174
2215
  }
2175
2216
  }
2176
2217
 
2177
- if (RTEST(ref_hash("_comp"))) {
2218
+ if (RTEST(del_hash("_comp"))) {
2178
2219
  VALUE y;
2179
2220
 
2180
2221
  y = ref_hash("cwyear");
@@ -2197,9 +2238,6 @@ date__parse(VALUE str, VALUE comp)
2197
2238
 
2198
2239
  }
2199
2240
 
2200
- del_hash("_bc");
2201
- del_hash("_comp");
2202
-
2203
2241
  {
2204
2242
  VALUE zone = ref_hash("zone");
2205
2243
  if (!NIL_P(zone) && NIL_P(ref_hash("offset")))
@@ -2249,8 +2287,8 @@ iso8601_ext_datetime_cb(VALUE m, VALUE hash)
2249
2287
  s[i] = rb_reg_nth_match(i, m);
2250
2288
  }
2251
2289
 
2252
- if (!NIL_P(s[3])) {
2253
- set_hash("mday", str2num(s[3]));
2290
+ if (!NIL_P(s[1])) {
2291
+ if (!NIL_P(s[3])) set_hash("mday", str2num(s[3]));
2254
2292
  if (strcmp(RSTRING_PTR(s[1]), "-") != 0) {
2255
2293
  y = str2num(s[1]);
2256
2294
  if (RSTRING_LEN(s[1]) < 4)
@@ -2307,7 +2345,7 @@ static int
2307
2345
  iso8601_ext_datetime(VALUE str, VALUE hash)
2308
2346
  {
2309
2347
  static const char pat_source[] =
2310
- "\\A\\s*(?:([-+]?\\d{2,}|-)-(\\d{2})?-(\\d{2})|"
2348
+ "\\A\\s*(?:([-+]?\\d{2,}|-)-(\\d{2})?(?:-(\\d{2}))?|"
2311
2349
  "([-+]?\\d{2,})?-(\\d{3})|"
2312
2350
  "(\\d{4}|\\d{2})?-w(\\d{2})-(\\d)|"
2313
2351
  "-w-(\\d))"
@@ -2938,7 +2976,7 @@ jisx0301_cb(VALUE m, VALUE hash)
2938
2976
  s[i] = rb_reg_nth_match(i, m);
2939
2977
  }
2940
2978
 
2941
- ep = gengo(NIL_P(s[1]) ? 'h' : *RSTRING_PTR(s[1]));
2979
+ ep = gengo(NIL_P(s[1]) ? JISX0301_DEFAULT_ERA : *RSTRING_PTR(s[1]));
2942
2980
  set_hash("year", f_add(str2num(s[2]), INT2FIX(ep)));
2943
2981
  set_hash("mon", str2num(s[3]));
2944
2982
  set_hash("mday", str2num(s[4]));
@@ -2963,7 +3001,7 @@ static int
2963
3001
  jisx0301(VALUE str, VALUE hash)
2964
3002
  {
2965
3003
  static const char pat_source[] =
2966
- "\\A\\s*([mtsh])?(\\d{2})\\.(\\d{2})\\.(\\d{2})"
3004
+ "\\A\\s*([" JISX0301_ERA_INITIALS "])?(\\d{2})\\.(\\d{2})\\.(\\d{2})"
2967
3005
  "(?:t"
2968
3006
  "(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?"
2969
3007
  "(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z";