strptime 0.1.9-x86-mingw32 → 0.2.1-x86-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 +4 -4
- data/ext/strptime/extconf.rb +1 -0
- data/ext/strptime/ruby_time.c +1 -1
- data/ext/strptime/strftime.c +495 -0
- data/ext/strptime/strptime.c +7 -3
- data/ext/strptime/strptime.h +13 -0
- data/lib/strptime/version.rb +1 -1
- data/strptime.gemspec +2 -2
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7fd559dc8db67f9c34e112b507f486bd177ea62
|
4
|
+
data.tar.gz: 31929c76c58428dcd1095a84259ef21ddbaf72d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 645b9336951b994033fc3643f3311f021eff07c5b59033e7b45992510ca05f234441bed609d0af5193601700e7d44a932642b53d30571885fca1555f4e678a95
|
7
|
+
data.tar.gz: 70c3a936869271dc744293e004d40426cb9fa00420fc1255499ea929ee11676fb1ca217664b6c70552bc2e5fe3e504f3de2d39720fdd6e6ef289e79596a7364f
|
data/ext/strptime/extconf.rb
CHANGED
data/ext/strptime/ruby_time.c
CHANGED
@@ -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
|
-
|
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
|
+
}
|
data/ext/strptime/strptime.c
CHANGED
@@ -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:
|
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
|
}
|
data/ext/strptime/strptime.h
CHANGED
@@ -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 */
|
data/lib/strptime/version.rb
CHANGED
data/strptime.gemspec
CHANGED
@@ -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
|
4
|
+
version: 0.2.1
|
5
5
|
platform: x86-mingw32
|
6
6
|
authors:
|
7
7
|
- NARUSE, Yui
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
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: []
|