date 3.3.1 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,31 +7,21 @@
7
7
  #include "ruby/re.h"
8
8
  #include <ctype.h>
9
9
 
10
+ #undef strncasecmp
11
+ #define strncasecmp STRNCASECMP
12
+
10
13
  static const char *day_names[] = {
11
14
  "Sunday", "Monday", "Tuesday", "Wednesday",
12
15
  "Thursday", "Friday", "Saturday",
13
- "Sun", "Mon", "Tue", "Wed",
14
- "Thu", "Fri", "Sat"
15
16
  };
17
+ static const int ABBREVIATED_DAY_NAME_LENGTH = 3;
16
18
 
17
19
  static const char *month_names[] = {
18
20
  "January", "February", "March", "April",
19
21
  "May", "June", "July", "August", "September",
20
22
  "October", "November", "December",
21
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
22
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
23
- };
24
-
25
- static const char *merid_names[] = {
26
- "am", "pm",
27
- "a.m.", "p.m."
28
- };
29
-
30
- static const char *extz_pats[] = {
31
- ":z",
32
- "::z",
33
- ":::z"
34
23
  };
24
+ static const int ABBREVIATED_MONTH_NAME_LENGTH = 3;
35
25
 
36
26
  #define sizeof_array(o) (sizeof o / sizeof o[0])
37
27
 
@@ -75,7 +65,7 @@ num_pattern_p(const char *s)
75
65
  #define NUM_PATTERN_P() num_pattern_p(&fmt[fi + 1])
76
66
 
77
67
  static long
78
- read_digits(const char *s, VALUE *n, size_t width)
68
+ read_digits(const char *s, size_t slen, VALUE *n, size_t width)
79
69
  {
80
70
  size_t l;
81
71
 
@@ -83,7 +73,7 @@ read_digits(const char *s, VALUE *n, size_t width)
83
73
  return 0;
84
74
 
85
75
  l = 0;
86
- while (ISDIGIT(s[l])) {
76
+ while (l < slen && ISDIGIT(s[l])) {
87
77
  if (++l == width) break;
88
78
  }
89
79
 
@@ -131,7 +121,7 @@ do { \
131
121
  #define READ_DIGITS(n,w) \
132
122
  do { \
133
123
  size_t l; \
134
- l = read_digits(&str[si], &n, w); \
124
+ l = read_digits(&str[si], slen - si, &n, w); \
135
125
  if (l == 0) \
136
126
  fail(); \
137
127
  si += l; \
@@ -161,6 +151,12 @@ do { \
161
151
 
162
152
  VALUE date_zone_to_diff(VALUE);
163
153
 
154
+ static inline int
155
+ head_match_p(size_t len, const char *name, const char *str, size_t slen, size_t si)
156
+ {
157
+ return slen - si >= len && strncasecmp(name, &str[si], len) == 0;
158
+ }
159
+
164
160
  static size_t
165
161
  date__strptime_internal(const char *str, size_t slen,
166
162
  const char *fmt, size_t flen, VALUE hash)
@@ -168,9 +164,18 @@ date__strptime_internal(const char *str, size_t slen,
168
164
  size_t si, fi;
169
165
  int c;
170
166
 
167
+ #define HEAD_MATCH_P(len, name) head_match_p(len, name, str, slen, si)
171
168
  si = fi = 0;
172
169
 
173
170
  while (fi < flen) {
171
+ if (isspace((unsigned char)fmt[fi])) {
172
+ while (si < slen && isspace((unsigned char)str[si]))
173
+ si++;
174
+ while (++fi < flen && isspace((unsigned char)fmt[fi]));
175
+ continue;
176
+ }
177
+
178
+ if (si >= slen) fail();
174
179
 
175
180
  switch (fmt[fi]) {
176
181
  case '%':
@@ -194,12 +199,11 @@ date__strptime_internal(const char *str, size_t slen,
194
199
  {
195
200
  int i;
196
201
 
197
- for (i = 0; i < (int)sizeof_array(extz_pats); i++)
198
- if (strncmp(extz_pats[i], &fmt[fi],
199
- strlen(extz_pats[i])) == 0) {
200
- fi += i;
201
- goto again;
202
- }
202
+ for (i = 1; i < 3 && fi + i < flen && fmt[fi+i] == ':'; ++i);
203
+ if (fmt[fi+i] == 'z') {
204
+ fi += i - 1;
205
+ goto again;
206
+ }
203
207
  fail();
204
208
  }
205
209
 
@@ -209,10 +213,12 @@ date__strptime_internal(const char *str, size_t slen,
209
213
  int i;
210
214
 
211
215
  for (i = 0; i < (int)sizeof_array(day_names); i++) {
212
- size_t l = strlen(day_names[i]);
213
- if (strncasecmp(day_names[i], &str[si], l) == 0) {
216
+ const char *day_name = day_names[i];
217
+ size_t l = strlen(day_name);
218
+ if (HEAD_MATCH_P(l, day_name) ||
219
+ HEAD_MATCH_P(l = ABBREVIATED_DAY_NAME_LENGTH, day_name)) {
214
220
  si += l;
215
- set_hash("wday", INT2FIX(i % 7));
221
+ set_hash("wday", INT2FIX(i));
216
222
  goto matched;
217
223
  }
218
224
  }
@@ -225,10 +231,12 @@ date__strptime_internal(const char *str, size_t slen,
225
231
  int i;
226
232
 
227
233
  for (i = 0; i < (int)sizeof_array(month_names); i++) {
228
- size_t l = strlen(month_names[i]);
229
- if (strncasecmp(month_names[i], &str[si], l) == 0) {
234
+ const char *month_name = month_names[i];
235
+ size_t l = strlen(month_name);
236
+ if (HEAD_MATCH_P(l, month_name) ||
237
+ HEAD_MATCH_P(l = ABBREVIATED_MONTH_NAME_LENGTH, month_name)) {
230
238
  si += l;
231
- set_hash("mon", INT2FIX((i % 12) + 1));
239
+ set_hash("mon", INT2FIX(i + 1));
232
240
  goto matched;
233
241
  }
234
242
  }
@@ -402,18 +410,19 @@ date__strptime_internal(const char *str, size_t slen,
402
410
 
403
411
  case 'P':
404
412
  case 'p':
413
+ if (slen - si < 2) fail();
405
414
  {
406
- int i;
407
-
408
- for (i = 0; i < 4; i++) {
409
- size_t l = strlen(merid_names[i]);
410
- if (strncasecmp(merid_names[i], &str[si], l) == 0) {
411
- si += l;
412
- set_hash("_merid", INT2FIX((i % 2) == 0 ? 0 : 12));
413
- goto matched;
414
- }
415
+ char c = str[si];
416
+ const int hour = (c == 'P' || c == 'p') ? 12 : 0;
417
+ if (!hour && !(c == 'A' || c == 'a')) fail();
418
+ if ((c = str[si+1]) == '.') {
419
+ if (slen - si < 4 || str[si+3] != '.') fail();
420
+ c = str[si += 2];
415
421
  }
416
- fail();
422
+ if (!(c == 'M' || c == 'm')) fail();
423
+ si += 2;
424
+ set_hash("_merid", INT2FIX(hour));
425
+ goto matched;
417
426
  }
418
427
 
419
428
  case 'Q':
@@ -587,7 +596,7 @@ date__strptime_internal(const char *str, size_t slen,
587
596
 
588
597
  b = rb_backref_get();
589
598
  rb_match_busy(b);
590
- m = f_match(pat, rb_usascii_str_new2(&str[si]));
599
+ m = f_match(pat, rb_usascii_str_new(&str[si], slen - si));
591
600
 
592
601
  if (!NIL_P(m)) {
593
602
  VALUE s, l, o;
@@ -619,22 +628,13 @@ date__strptime_internal(const char *str, size_t slen,
619
628
  if (str[si] != '%')
620
629
  fail();
621
630
  si++;
622
- if (fi < flen)
623
- if (str[si] != fmt[fi])
631
+ if (fi < flen) {
632
+ if (si >= slen || str[si] != fmt[fi])
624
633
  fail();
625
- si++;
634
+ si++;
635
+ }
626
636
  goto matched;
627
637
  }
628
- case ' ':
629
- case '\t':
630
- case '\n':
631
- case '\v':
632
- case '\f':
633
- case '\r':
634
- while (isspace((unsigned char)str[si]))
635
- si++;
636
- fi++;
637
- break;
638
638
  default:
639
639
  ordinal:
640
640
  if (str[si] != fmt[fi])
data/ext/date/extconf.rb CHANGED
@@ -3,6 +3,7 @@ require 'mkmf'
3
3
 
4
4
  config_string("strict_warnflags") {|w| $warnflags += " #{w}"}
5
5
 
6
+ append_cflags("-Wno-compound-token-split-by-macro") if RUBY_VERSION < "2.7."
6
7
  have_func("rb_category_warn")
7
8
  with_werror("", {:werror => true}) do |opt, |
8
9
  have_var("timezone", "time.h", opt)
data/ext/date/prereq.mk CHANGED
@@ -1,7 +1,7 @@
1
1
  .SUFFIXES: .list
2
2
 
3
3
  .list.h:
4
- gperf --ignore-case -C -c -P -p -j1 -i 1 -g -o -t -N $(*F) $< \
4
+ gperf --ignore-case -L ANSI-C -C -c -P -p -j1 -i 1 -g -o -t -N $(*F) $< \
5
5
  | sed -f $(top_srcdir)/tool/gperf.sed \
6
6
  > $(@F)
7
7