strptime 0.1.9-x64-mingw32 → 0.2.1-x64-mingw32

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 87b7e4d6f0044905e518c093138d21e538af7f23
4
- data.tar.gz: 772e0fbc7837a84fbee99fd598ace9b64b31e622
3
+ metadata.gz: da9b5b737ae895af93e98cc6a5d267e134e36cef
4
+ data.tar.gz: ff65ec6bdc06e6f0b202bb8a91594e50f83d6483
5
5
  SHA512:
6
- metadata.gz: 152d8f0198b22f65929cc6fd3503bde2898758ea5eb21d932d9fc8d8a183b3f9520222a30ce055dc7eab68ac93703c963d76c22eed5b701d31c84c1feb769f6f
7
- data.tar.gz: 306be2bad64761df3f8d4345b319d20cbb129c1d454ac8a6fee04f38809fa20f95b4f250457d1fbf83f4b1224ba562967708edebe39996cbd8b4440911924a68
6
+ metadata.gz: 9a16feb8a8146c3d0ae99880f6b9be74fad1049de1413446faa81072bba597d61c9dd15afdf73625f792f49cadbd2a57b9a52515d2c03a2984429477eb7484d5
7
+ data.tar.gz: 149c4fdc38c93bf6389d2cb4733c4745eb422b70a46dcc0b767bb61cf7ff14ab0f2018abbe916d4e572f08d26ed497841e4c024cea61cacd2aac6f8b98d215ed
@@ -2,5 +2,6 @@ require "mkmf"
2
2
 
3
3
  have_func('rb_timespec_now')
4
4
  have_func('rb_time_timespec_new')
5
+ have_func('rb_time_utc_offset')
5
6
 
6
7
  create_makefile("strptime/strptime")
@@ -147,7 +147,7 @@ rb_localtime_r(const time_t *t, struct tm *result)
147
147
  }
148
148
  #define LOCALTIME(tm, result) (tzset(),rb_localtime_r((tm), &(result)))
149
149
 
150
- static struct tm *
150
+ struct tm *
151
151
  rb_gmtime_r(const time_t *t, struct tm *result)
152
152
  {
153
153
  #ifdef HAVE_GMTIME_R
@@ -0,0 +1,495 @@
1
+ #include "../strptime/strptime.h"
2
+ #include "ruby/encoding.h"
3
+ #include <time.h>
4
+
5
+ VALUE rb_cStrftime;
6
+ #ifndef HAVE_RB_TIME_UTC_OFFSET
7
+ static ID id_gmtoff;
8
+ #endif
9
+
10
+ #define GetStrftimeval(obj, tobj) ((tobj) = get_strftimeval(obj))
11
+ #define GetNewStrftimeval(obj, tobj) ((tobj) = get_new_strftimeval(obj))
12
+ #define StrfTIME_INIT_P(tobj) ((tobj)->isns)
13
+
14
+ #define LIKELY(x) (__builtin_expect((x), 1))
15
+ #define UNLIKELY(x) (__builtin_expect((x), 0))
16
+
17
+ #define REG_PC (pc)
18
+ #define GET_PC() REG_PC
19
+ #define SET_PC(x) (REG_PC = (x))
20
+ #define GET_CURRENT_INSN() (*GET_PC())
21
+ #define GET_OPERAND(n) (GET_PC()[(n)])
22
+ #define ADD_PC(n) (SET_PC(REG_PC + (n)))
23
+
24
+ #define JUMP(dst) (REG_PC += (dst))
25
+
26
+ #define LABEL(x) INSN_LABEL_##x
27
+ #define ELABEL(x) INSN_ELABEL_##x
28
+ #define LABEL_PTR(x) &&LABEL(x)
29
+
30
+ #define INSN_ENTRY(insn) LABEL(insn) :
31
+
32
+ #define TC_DISPATCH(insn) \
33
+ goto *(void const *)GET_CURRENT_INSN(); \
34
+ ;
35
+ #define END_INSN(insn) TC_DISPATCH(insn);
36
+
37
+ #define INSN_DISPATCH() \
38
+ TC_DISPATCH(__START__) \
39
+ {
40
+
41
+ #define END_INSNS_DISPATCH() \
42
+ rb_bug("strptime: unknown insn: %p", GET_CURRENT_INSN()); \
43
+ } /* end of while loop */
44
+
45
+ #define NEXT_INSN() TC_DISPATCH(__NEXT_INSN__)
46
+
47
+
48
+
49
+ static VALUE
50
+ strftime_exec0(void **pc, VALUE fmt, struct timespec *tsp, int gmtoff, size_t result_length)
51
+ {
52
+ VALUE result;
53
+ struct tm tm;
54
+ char *p;
55
+ if (UNLIKELY(tsp == NULL)) {
56
+ static const void *const insns_address_table[] = {
57
+ NULL, NULL, NULL, NULL,
58
+ NULL, NULL, NULL, LABEL_PTR(H),
59
+ NULL, NULL, NULL, LABEL_PTR(L),
60
+ LABEL_PTR(M), LABEL_PTR(N), NULL, NULL,
61
+ NULL, NULL, LABEL_PTR(S), NULL,
62
+ NULL, NULL, NULL, NULL,
63
+ LABEL_PTR(Y), NULL, NULL, NULL,
64
+ NULL, NULL, LABEL_PTR(_5f), LABEL_PTR(_60),
65
+ NULL, NULL, NULL, LABEL_PTR(d),
66
+ LABEL_PTR(d), NULL, NULL, NULL,
67
+ NULL, NULL, NULL, NULL,
68
+ LABEL_PTR(m), NULL, NULL, NULL,
69
+ NULL, NULL, NULL, NULL,
70
+ NULL, NULL, NULL, NULL,
71
+ LABEL_PTR(y), LABEL_PTR(z),
72
+ };
73
+ *pc = (void *)insns_address_table;
74
+ return Qnil;
75
+ }
76
+
77
+ result = rb_str_new(NULL, result_length);
78
+ p = RSTRING_PTR(result);
79
+
80
+ tsp->tv_sec += gmtoff;
81
+ rb_gmtime_r(&tsp->tv_sec, &tm);
82
+
83
+ INSN_DISPATCH();
84
+ INSN_ENTRY(H)
85
+ {
86
+ *p++ = '0' + (tm.tm_hour / 10);
87
+ *p++ = '0' + (tm.tm_hour % 10);
88
+ ADD_PC(1);
89
+ END_INSN(H)
90
+ }
91
+ INSN_ENTRY(L)
92
+ {
93
+ int msec = tsp->tv_nsec / 1000000;
94
+ p[2] = '0' + (msec % 10);
95
+ msec /= 10;
96
+ p[1] = '0' + (msec % 10);
97
+ p[0] = '0' + (msec / 10);
98
+ p += 3;
99
+ ADD_PC(1);
100
+ END_INSN(L)
101
+ }
102
+ INSN_ENTRY(M)
103
+ {
104
+ *p++ = '0' + (tm.tm_min / 10);
105
+ *p++ = '0' + (tm.tm_min % 10);
106
+ ADD_PC(1);
107
+ END_INSN(M)
108
+ }
109
+ INSN_ENTRY(N)
110
+ {
111
+ int len = 9;
112
+ int i;
113
+ int base = 1;
114
+ int subsec = tsp->tv_nsec;
115
+ for (i=0; i < 9-len; i++) {
116
+ base *= 10;
117
+ }
118
+ subsec /= base;
119
+ for (i=0; i < len; i++) {
120
+ p[len-i-1] = '0' + subsec % 10;
121
+ subsec /= 10;
122
+ }
123
+ p += len;
124
+ ADD_PC(1);
125
+ END_INSN(N)
126
+ }
127
+ INSN_ENTRY(S)
128
+ {
129
+ *p++ = '0' + (tm.tm_sec / 10);
130
+ *p++ = '0' + (tm.tm_sec % 10);
131
+ ADD_PC(1);
132
+ END_INSN(S)
133
+ }
134
+ INSN_ENTRY(Y)
135
+ {
136
+ // TODO: Y10K
137
+ int i, y = tm.tm_year;
138
+ y += y < 69 ? 2000 : 1900;
139
+ for (i = 0; i < 4; i++) {
140
+ p[3-i] = '0' + y % 10;
141
+ y /= 10;
142
+ }
143
+ p += 4;
144
+ ADD_PC(1);
145
+ END_INSN(Y)
146
+ }
147
+ INSN_ENTRY(d)
148
+ {
149
+ *p++ = '0' + (tm.tm_mday / 10);
150
+ *p++ = '0' + (tm.tm_mday % 10);
151
+ ADD_PC(1);
152
+ END_INSN(d)
153
+ }
154
+ INSN_ENTRY(m)
155
+ {
156
+ int mon = tm.tm_mon + 1;
157
+ *p++ = '0' + (mon / 10);
158
+ *p++ = '0' + (mon % 10);
159
+ ADD_PC(1);
160
+ END_INSN(m)
161
+ }
162
+ INSN_ENTRY(y)
163
+ {
164
+ int y = tm.tm_year % 100;
165
+ *p++ = '0' + (y / 10);
166
+ *p++ = '0' + (y % 10);
167
+ ADD_PC(1);
168
+ END_INSN(y)
169
+ }
170
+ INSN_ENTRY(z)
171
+ {
172
+ int h, m, tmp=gmtoff;
173
+ if (gmtoff >= 0) {
174
+ *p++ = '+';
175
+ } else {
176
+ *p++ = '-';
177
+ tmp = -tmp;
178
+ }
179
+ tmp /= 60;
180
+ h = (tmp / 60)&15; /* ignore too large offset */
181
+ m = tmp % 60;
182
+ *p++ = '0' + (h / 10);
183
+ *p++ = '0' + (h % 10);
184
+ *p++ = '0' + (m / 10);
185
+ *p++ = '0' + (m % 10);
186
+ ADD_PC(1);
187
+ END_INSN(y)
188
+ }
189
+ INSN_ENTRY(_60)
190
+ {
191
+ size_t v = (size_t)GET_OPERAND(1);
192
+ size_t off = v & 0xFFFF;
193
+ size_t len = v >> 16;
194
+ memcpy(p, RSTRING_PTR(fmt) + off, len);
195
+ p += len;
196
+ pc += 2;
197
+ END_INSN(_60)
198
+ }
199
+ INSN_ENTRY(_5f)
200
+ {
201
+ return result;
202
+ END_INSN(_5f)
203
+ }
204
+ END_INSNS_DISPATCH();
205
+
206
+ /* unreachable */
207
+ rb_bug("strftime_exec0: unreachable");
208
+ UNREACHABLE;
209
+ }
210
+
211
+ static void **
212
+ strftime_compile(const char *fmt, size_t flen, size_t *rlenp)
213
+ {
214
+ size_t fi = 0, rlen = 0;
215
+ char c;
216
+ void **isns0, **isns;
217
+ void **insns_address_table;
218
+ void *tmp;
219
+ strftime_exec0((void **)&insns_address_table, Qnil, NULL, 0, 0);
220
+
221
+ if (flen > 65535) {
222
+ rb_raise(rb_eArgError, "too long format string (>65335)");
223
+ }
224
+ isns0 = ALLOC_N(void *, flen + 2);
225
+ isns = isns0;
226
+
227
+ while (fi < flen) {
228
+ switch (fmt[fi]) {
229
+ case '%':
230
+ fi++;
231
+ c = fmt[fi];
232
+ switch (c) {
233
+ case 'H':
234
+ rlen += 2;
235
+ goto accept_format;
236
+ case 'L':
237
+ rlen += 3;
238
+ goto accept_format;
239
+ case 'M':
240
+ rlen += 2;
241
+ goto accept_format;
242
+ case 'N':
243
+ rlen += 9;
244
+ goto accept_format;
245
+ case 'S':
246
+ rlen += 2;
247
+ goto accept_format;
248
+ case 'Y':
249
+ rlen += 4;
250
+ goto accept_format;
251
+ case 'd':
252
+ rlen += 2;
253
+ goto accept_format;
254
+ case 'm':
255
+ rlen += 2;
256
+ goto accept_format;
257
+ case 'y':
258
+ rlen += 2;
259
+ goto accept_format;
260
+ case 'z':
261
+ rlen += 5;
262
+ goto accept_format;
263
+ accept_format:
264
+ tmp = insns_address_table[c - 'A'];
265
+ if (tmp) {
266
+ *isns++ = tmp;
267
+ fi++;
268
+ continue;
269
+ }
270
+ default:
271
+ xfree(isns0);
272
+ rb_raise(rb_eArgError, "invalid format");
273
+ break;
274
+ }
275
+ default: {
276
+ const char *p0 = fmt + fi, *p = p0, *pe = fmt + flen;
277
+ size_t v = fi;
278
+ while (p < pe && *p != '%')
279
+ p++;
280
+ v += (p - p0) << 16;
281
+ fi += p - p0;
282
+ rlen += p - p0;
283
+ *isns++ = insns_address_table['`' - 'A'];
284
+ *isns++ = (void *)v;
285
+ } break;
286
+ }
287
+ }
288
+ *isns++ = insns_address_table['_' - 'A'];
289
+ REALLOC_N(isns0, void *, isns - isns0);
290
+ *rlenp = rlen;
291
+ return isns0;
292
+ }
293
+
294
+ struct strftime_object {
295
+ void **isns;
296
+ size_t result_length;
297
+ VALUE fmt;
298
+ };
299
+
300
+ static void
301
+ strftime_mark(void *ptr)
302
+ {
303
+ struct strftime_object *tobj = ptr;
304
+ rb_gc_mark(tobj->fmt);
305
+ }
306
+
307
+ static void
308
+ strftime_free(void *ptr)
309
+ {
310
+ struct strftime_object *tobj = ptr;
311
+ if (tobj->isns) ruby_xfree(tobj->isns);
312
+ }
313
+
314
+ static size_t
315
+ strftime_memsize(const void *tobj)
316
+ {
317
+ return sizeof(struct strftime_object);
318
+ }
319
+
320
+ static const rb_data_type_t strftime_data_type = {
321
+ "strftime",
322
+ {
323
+ strftime_mark, strftime_free, strftime_memsize,
324
+ },
325
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
326
+ 0,
327
+ 0,
328
+ RUBY_TYPED_FREE_IMMEDIATELY
329
+ #endif
330
+ };
331
+
332
+ static VALUE
333
+ strftime_s_alloc(VALUE klass)
334
+ {
335
+ VALUE obj;
336
+ struct strftime_object *tobj;
337
+
338
+ obj = TypedData_Make_Struct(klass, struct strftime_object,
339
+ &strftime_data_type, tobj);
340
+
341
+ return obj;
342
+ }
343
+
344
+ static struct strftime_object *
345
+ get_strftimeval(VALUE obj)
346
+ {
347
+ struct strftime_object *tobj;
348
+ TypedData_Get_Struct(obj, struct strftime_object, &strftime_data_type,
349
+ tobj);
350
+ if (!StrfTIME_INIT_P(tobj)) {
351
+ rb_raise(rb_eTypeError, "uninitialized %" PRIsVALUE, rb_obj_class(obj));
352
+ }
353
+ return tobj;
354
+ }
355
+
356
+ static struct strftime_object *
357
+ get_new_strftimeval(VALUE obj)
358
+ {
359
+ struct strftime_object *tobj;
360
+ TypedData_Get_Struct(obj, struct strftime_object, &strftime_data_type,
361
+ tobj);
362
+ if (StrfTIME_INIT_P(tobj)) {
363
+ rb_raise(rb_eTypeError, "already initialized %" PRIsVALUE,
364
+ rb_obj_class(obj));
365
+ }
366
+ return tobj;
367
+ }
368
+
369
+ /*
370
+ * @overload new(format)
371
+ * @param format [String] strftime(3) style format string.
372
+ *
373
+ * returns generator object
374
+ */
375
+ static VALUE
376
+ strftime_init(VALUE self, VALUE fmt)
377
+ {
378
+ struct strftime_object *tobj;
379
+ void **isns;
380
+ size_t rlen;
381
+ StringValueCStr(fmt);
382
+ TypedData_Get_Struct(self, struct strftime_object, &strftime_data_type,
383
+ tobj);
384
+ isns = strftime_compile(RSTRING_PTR(fmt), RSTRING_LEN(fmt), &rlen);
385
+ tobj->isns = isns;
386
+ tobj->fmt = rb_str_new_frozen(fmt);
387
+ tobj->result_length = rlen;
388
+ return self;
389
+ }
390
+
391
+ /* @api private
392
+ * For Ruby VM internal.
393
+ */
394
+ static VALUE
395
+ strftime_init_copy(VALUE copy, VALUE self)
396
+ {
397
+ struct strftime_object *tobj, *tcopy;
398
+
399
+ if (!OBJ_INIT_COPY(copy, self)) return copy;
400
+ GetStrftimeval(self, tobj);
401
+ GetNewStrftimeval(copy, tcopy);
402
+ MEMCPY(tcopy, tobj, struct strftime_object, 1);
403
+
404
+ return copy;
405
+ }
406
+
407
+ /*
408
+ * @overload exec(str)
409
+ * @param str [String] string to parse
410
+ * @return [Time] the time object given string means
411
+ *
412
+ * Return a formatted datetime string
413
+ *
414
+ */
415
+ static VALUE
416
+ strftime_exec(VALUE self, VALUE time)
417
+ {
418
+ struct strftime_object *sobj;
419
+ struct timespec ts = rb_time_timespec(time);
420
+ #ifdef HAVE_RB_TIME_UTC_OFFSET
421
+ int gmtoff = FIX2INT(rb_time_utc_offset(time));
422
+ #else
423
+ int gmtoff = NUM2INT(rb_funcall(time, id_gmtoff, 0));
424
+ #endif
425
+ GetStrftimeval(self, sobj);
426
+
427
+ return strftime_exec0(sobj->isns, sobj->fmt, &ts, gmtoff, sobj->result_length);
428
+ }
429
+
430
+ /*
431
+ * @overload execi(epoch)
432
+ * @param epoch [Integer] Unix epoch
433
+ * @return [String] the formatted datetime string
434
+ *
435
+ * Return a formatted datetime string
436
+ *
437
+ */
438
+ static VALUE
439
+ strftime_execi(VALUE self, VALUE epoch)
440
+ {
441
+ struct strftime_object *tobj;
442
+ struct timespec ts;
443
+ GetStrftimeval(self, tobj);
444
+
445
+ if (RB_INTEGER_TYPE_P(epoch)) {
446
+ ts.tv_sec = NUM2TIMET(epoch);
447
+ ts.tv_nsec = 0;
448
+ } else if (RB_FLOAT_TYPE_P(epoch)) {
449
+ double d = NUM2DBL(epoch);
450
+ ts.tv_sec = (time_t)d;
451
+ ts.tv_nsec = (int)((int64_t)(d * 1000000000) % 1000000000);
452
+ } else if (RB_TYPE_P(epoch, T_RATIONAL)) {
453
+ ts.tv_sec = NUM2TIMET(epoch);
454
+ ts.tv_nsec = NUM2INT(rb_funcall(rb_funcall(epoch, '*', 1, INT2FIX(1000000000)), '%', 1, INT2FIX(1000000000)));
455
+ }
456
+
457
+ return strftime_exec0(tobj->isns, tobj->fmt, &ts, 0, tobj->result_length);
458
+ }
459
+
460
+ /*
461
+ * @overload source
462
+ * @return [String] source format string
463
+ */
464
+ static VALUE
465
+ strftime_source(VALUE self)
466
+ {
467
+ struct strftime_object *tobj;
468
+ GetStrftimeval(self, tobj);
469
+
470
+ return tobj->fmt;
471
+ }
472
+
473
+
474
+ /*
475
+ * Document-class: Strftime
476
+ *
477
+ * Strftime is a faster way to format time string like strftime(3).
478
+ *
479
+ * @example
480
+ * generator = Strftime.new('%Y-%m-%dT%H:%M:%S%z')
481
+ * generator.source #=> "%Y-%m-%dT%H:%M:%S%z"
482
+ * generator.exec(Time.now) #=> 2017-12-25T12:34:56+09:00
483
+ */
484
+ void
485
+ Init_strftime(void)
486
+ {
487
+ rb_cStrftime = rb_define_class("Strftime", rb_cObject);
488
+ rb_define_alloc_func(rb_cStrftime, strftime_s_alloc);
489
+ rb_define_method(rb_cStrftime, "initialize", strftime_init, 1);
490
+ rb_define_method(rb_cStrftime, "initialize_copy", strftime_init_copy, 1);
491
+ rb_define_method(rb_cStrftime, "exec", strftime_exec, 1);
492
+ rb_define_method(rb_cStrftime, "execi", strftime_execi, 1);
493
+ rb_define_method(rb_cStrftime, "source", strftime_source, 0);
494
+ id_gmtoff = rb_intern("gmtoff");
495
+ }
@@ -481,7 +481,7 @@ strptime_exec0(void **pc, const char *fmt, const char *str, size_t slen,
481
481
  UNREACHABLE;
482
482
  }
483
483
 
484
- void **
484
+ static void **
485
485
  strptime_compile(const char *fmt, size_t flen)
486
486
  {
487
487
  size_t fi = 0;
@@ -518,7 +518,10 @@ strptime_compile(const char *fmt, size_t flen)
518
518
  fi++;
519
519
  continue;
520
520
  }
521
- default: rb_raise(rb_eArgError, "invalid format"); break;
521
+ default:
522
+ xfree(isns0);
523
+ rb_raise(rb_eArgError, "invalid format");
524
+ break;
522
525
  }
523
526
  case ' ':
524
527
  case '\t':
@@ -562,7 +565,7 @@ static void
562
565
  strptime_free(void *ptr)
563
566
  {
564
567
  struct strptime_object *tobj = ptr;
565
- ruby_xfree(tobj->isns);
568
+ if (tobj->isns) ruby_xfree(tobj->isns);
566
569
  }
567
570
 
568
571
  static size_t
@@ -735,4 +738,5 @@ Init_strptime(void)
735
738
  rb_define_method(rb_cStrptime, "exec", strptime_exec, 1);
736
739
  rb_define_method(rb_cStrptime, "execi", strptime_execi, 1);
737
740
  rb_define_method(rb_cStrptime, "source", strptime_source, 0);
741
+ Init_strftime();
738
742
  }
@@ -12,5 +12,18 @@ void rb_timespec_now(struct timespec *ts);
12
12
  time_t timegm_noleapsecond(struct tm *tm);
13
13
  const char *find_time_t(struct tm *tptr, int utc_p, time_t *tp);
14
14
  void tm_add_offset(struct tm *tm, long diff);
15
+ struct tm *rb_gmtime_r(const time_t *t, struct tm *result);
16
+ void Init_strftime(void);
17
+
18
+ #ifndef RB_INTEGER_TYPE_P
19
+ #define RB_INTEGER_TYPE_P(obj) rb_integer_type_p(obj)
20
+ static inline int
21
+ rb_integer_type_p(VALUE obj)
22
+ {
23
+ return (FIXNUM_P(obj) ||
24
+ (!SPECIAL_CONST_P(obj) &&
25
+ BUILTIN_TYPE(obj) == RUBY_T_BIGNUM));
26
+ }
27
+ #endif
15
28
 
16
29
  #endif /* STRPTIME_H */
@@ -1,3 +1,3 @@
1
1
  class Strptime
2
- VERSION = "0.1.9"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["NARUSE, Yui"]
10
10
  spec.email = ["naruse@airemix.jp"]
11
11
 
12
- spec.summary = %q{a fast strptime engine.}
13
- spec.description = %q{a fast strptime engine which uses VM.}
12
+ spec.summary = %q{a fast strptime/strftime engine.}
13
+ spec.description = %q{a fast strptime/strftime engine which uses VM.}
14
14
  spec.homepage = "https://github.com/nurse/strptime"
15
15
  spec.license = "BSD-2-Clause"
16
16
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strptime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.2.1
5
5
  platform: x64-mingw32
6
6
  authors:
7
7
  - NARUSE, Yui
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-01-11 00:00:00.000000000 Z
11
+ date: 2017-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,7 +94,7 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- description: a fast strptime engine which uses VM.
97
+ description: a fast strptime/strftime engine which uses VM.
98
98
  email:
99
99
  - naruse@airemix.jp
100
100
  executables: []
@@ -114,6 +114,7 @@ files:
114
114
  - bin/setup
115
115
  - ext/strptime/extconf.rb
116
116
  - ext/strptime/ruby_time.c
117
+ - ext/strptime/strftime.c
117
118
  - ext/strptime/strptime.c
118
119
  - ext/strptime/strptime.h
119
120
  - lib/strptime.rb
@@ -150,5 +151,5 @@ rubyforge_project:
150
151
  rubygems_version: 2.6.8
151
152
  signing_key:
152
153
  specification_version: 4
153
- summary: a fast strptime engine.
154
+ summary: a fast strptime/strftime engine.
154
155
  test_files: []