kernaux 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +44 -0
- data/.rubocop.yml +79 -0
- data/.simplecov +9 -0
- data/.yardopts +4 -0
- data/Gemfile +8 -0
- data/README.md +29 -0
- data/Rakefile +80 -0
- data/bin/console +8 -0
- data/bin/setup +7 -0
- data/ext/default/assert.c +55 -0
- data/ext/default/cmdline.c +83 -0
- data/ext/default/dynarg.c +45 -0
- data/ext/default/dynarg.h +35 -0
- data/ext/default/extconf.rb +14 -0
- data/ext/default/main.c +34 -0
- data/ext/default/main.h +28 -0
- data/ext/default/ntoa.c +254 -0
- data/ext/default/printf.c +210 -0
- data/ext/default/version.c +47 -0
- data/kernaux.gemspec +59 -0
- data/lib/kernaux/assert.rb +58 -0
- data/lib/kernaux/cmdline.rb +20 -0
- data/lib/kernaux/errors.rb +39 -0
- data/lib/kernaux/ntoa.rb +136 -0
- data/lib/kernaux/printf.rb +70 -0
- data/lib/kernaux/version.rb +13 -0
- data/lib/kernaux.rb +20 -0
- metadata +230 -0
data/ext/default/ntoa.c
ADDED
@@ -0,0 +1,254 @@
|
|
1
|
+
#include "main.h"
|
2
|
+
|
3
|
+
#ifdef KERNAUX_VERSION_WITH_NTOA
|
4
|
+
|
5
|
+
static VALUE rb_KernAux_utoa(int argc, const VALUE *argv, VALUE self);
|
6
|
+
static VALUE rb_KernAux_itoa(int argc, const VALUE *argv, VALUE self);
|
7
|
+
static VALUE rb_KernAux_utoa2(VALUE self, VALUE number);
|
8
|
+
static VALUE rb_KernAux_itoa2(VALUE self, VALUE number);
|
9
|
+
static VALUE rb_KernAux_utoa8(VALUE self, VALUE number);
|
10
|
+
static VALUE rb_KernAux_itoa8(VALUE self, VALUE number);
|
11
|
+
static VALUE rb_KernAux_utoa10(VALUE self, VALUE number);
|
12
|
+
static VALUE rb_KernAux_itoa10(VALUE self, VALUE number);
|
13
|
+
static VALUE rb_KernAux_utoa16(VALUE self, VALUE number);
|
14
|
+
static VALUE rb_KernAux_itoa16(VALUE self, VALUE number);
|
15
|
+
|
16
|
+
static ID rb_intern_b = Qnil;
|
17
|
+
static ID rb_intern_B = Qnil;
|
18
|
+
static ID rb_intern_h = Qnil;
|
19
|
+
static ID rb_intern_H = Qnil;
|
20
|
+
static ID rb_intern_o = Qnil;
|
21
|
+
static ID rb_intern_O = Qnil;
|
22
|
+
static ID rb_intern_d = Qnil;
|
23
|
+
static ID rb_intern_D = Qnil;
|
24
|
+
static ID rb_intern_x = Qnil;
|
25
|
+
static ID rb_intern_X = Qnil;
|
26
|
+
|
27
|
+
static VALUE rb_KernAux_InvalidNtoaBaseError = Qnil;
|
28
|
+
static VALUE rb_KernAux_TooLongNtoaPrefixError = Qnil;
|
29
|
+
|
30
|
+
static int convert_base(VALUE base);
|
31
|
+
|
32
|
+
void init_ntoa()
|
33
|
+
{
|
34
|
+
rb_gc_register_mark_object(ID2SYM(rb_intern_b = rb_intern("b")));
|
35
|
+
rb_gc_register_mark_object(ID2SYM(rb_intern_B = rb_intern("B")));
|
36
|
+
rb_gc_register_mark_object(ID2SYM(rb_intern_h = rb_intern("h")));
|
37
|
+
rb_gc_register_mark_object(ID2SYM(rb_intern_H = rb_intern("H")));
|
38
|
+
rb_gc_register_mark_object(ID2SYM(rb_intern_o = rb_intern("o")));
|
39
|
+
rb_gc_register_mark_object(ID2SYM(rb_intern_O = rb_intern("O")));
|
40
|
+
rb_gc_register_mark_object(ID2SYM(rb_intern_d = rb_intern("d")));
|
41
|
+
rb_gc_register_mark_object(ID2SYM(rb_intern_D = rb_intern("D")));
|
42
|
+
rb_gc_register_mark_object(ID2SYM(rb_intern_x = rb_intern("x")));
|
43
|
+
rb_gc_register_mark_object(ID2SYM(rb_intern_X = rb_intern("X")));
|
44
|
+
|
45
|
+
rb_gc_register_mark_object(rb_KernAux_InvalidNtoaBaseError =
|
46
|
+
rb_define_class_under(rb_KernAux, "InvalidNtoaBaseError",
|
47
|
+
rb_KernAux_Error));
|
48
|
+
rb_gc_register_mark_object(rb_KernAux_TooLongNtoaPrefixError =
|
49
|
+
rb_define_class_under(rb_KernAux, "TooLongNtoaPrefixError",
|
50
|
+
rb_KernAux_Error));
|
51
|
+
|
52
|
+
rb_define_singleton_method(rb_KernAux, "utoa", rb_KernAux_utoa, -1);
|
53
|
+
rb_define_singleton_method(rb_KernAux, "itoa", rb_KernAux_itoa, -1);
|
54
|
+
rb_define_singleton_method(rb_KernAux, "utoa2", rb_KernAux_utoa2, 1);
|
55
|
+
rb_define_singleton_method(rb_KernAux, "itoa2", rb_KernAux_itoa2, 1);
|
56
|
+
rb_define_singleton_method(rb_KernAux, "utoa8", rb_KernAux_utoa8, 1);
|
57
|
+
rb_define_singleton_method(rb_KernAux, "itoa8", rb_KernAux_itoa8, 1);
|
58
|
+
rb_define_singleton_method(rb_KernAux, "utoa10", rb_KernAux_utoa10, 1);
|
59
|
+
rb_define_singleton_method(rb_KernAux, "itoa10", rb_KernAux_itoa10, 1);
|
60
|
+
rb_define_singleton_method(rb_KernAux, "utoa16", rb_KernAux_utoa16, 1);
|
61
|
+
rb_define_singleton_method(rb_KernAux, "itoa16", rb_KernAux_itoa16, 1);
|
62
|
+
}
|
63
|
+
|
64
|
+
VALUE rb_KernAux_utoa(const int argc, const VALUE *argv, const VALUE self)
|
65
|
+
{
|
66
|
+
if (argc < 2 || argc > 3) {
|
67
|
+
rb_raise(
|
68
|
+
rb_eArgError,
|
69
|
+
"wrong number of arguments (given %d, expected 2..3)",
|
70
|
+
argc
|
71
|
+
);
|
72
|
+
}
|
73
|
+
|
74
|
+
VALUE number_rb = argv[0];
|
75
|
+
VALUE base_rb = argv[1];
|
76
|
+
VALUE prefix_rb = argc == 3 ? argv[2] : Qnil;
|
77
|
+
|
78
|
+
const uint64_t number = NUM2ULL(number_rb);
|
79
|
+
|
80
|
+
if (rb_funcall(number_rb, rb_intern_LESS, 1, INT2FIX(0))) {
|
81
|
+
rb_raise(rb_eRangeError, "can't convert negative number to uint64_t");
|
82
|
+
}
|
83
|
+
|
84
|
+
const char *prefix = NULL;
|
85
|
+
long prefix_len = 0;
|
86
|
+
if (!NIL_P(prefix_rb)) {
|
87
|
+
prefix = StringValueCStr(prefix_rb);
|
88
|
+
prefix_len = RSTRING_LEN(prefix_rb);
|
89
|
+
|
90
|
+
if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN || prefix_len < 0) {
|
91
|
+
rb_raise(
|
92
|
+
rb_KernAux_TooLongNtoaPrefixError,
|
93
|
+
"prefix length %ld is too long",
|
94
|
+
prefix_len
|
95
|
+
);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
char buffer[KERNAUX_UTOA_MIN_BUFFER_SIZE + prefix_len];
|
100
|
+
kernaux_utoa(number, buffer, convert_base(base_rb), prefix);
|
101
|
+
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
|
102
|
+
}
|
103
|
+
|
104
|
+
VALUE rb_KernAux_itoa(const int argc, const VALUE *argv, const VALUE self)
|
105
|
+
{
|
106
|
+
if (argc < 2 || argc > 3) {
|
107
|
+
rb_raise(
|
108
|
+
rb_eArgError,
|
109
|
+
"wrong number of arguments (given %d, expected 2..3)",
|
110
|
+
argc
|
111
|
+
);
|
112
|
+
}
|
113
|
+
|
114
|
+
VALUE number_rb = argv[0];
|
115
|
+
VALUE base_rb = argv[1];
|
116
|
+
VALUE prefix_rb = argc == 3 ? argv[2] : Qnil;
|
117
|
+
|
118
|
+
const int64_t number = NUM2LL(number_rb);
|
119
|
+
|
120
|
+
const char *prefix = NULL;
|
121
|
+
long prefix_len = 0;
|
122
|
+
if (!NIL_P(prefix_rb)) {
|
123
|
+
prefix = StringValueCStr(prefix_rb);
|
124
|
+
prefix_len = RSTRING_LEN(prefix_rb);
|
125
|
+
|
126
|
+
if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN || prefix_len < 0) {
|
127
|
+
rb_raise(
|
128
|
+
rb_KernAux_TooLongNtoaPrefixError,
|
129
|
+
"prefix length %ld is too long",
|
130
|
+
prefix_len
|
131
|
+
);
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
char buffer[KERNAUX_ITOA_MIN_BUFFER_SIZE + prefix_len];
|
136
|
+
kernaux_itoa(number, buffer, convert_base(base_rb), prefix);
|
137
|
+
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
|
138
|
+
}
|
139
|
+
|
140
|
+
VALUE rb_KernAux_utoa2(
|
141
|
+
const VALUE self_rb __attribute__((unused)),
|
142
|
+
const VALUE number_rb
|
143
|
+
) {
|
144
|
+
const uint64_t number = NUM2ULL(number_rb);
|
145
|
+
if (rb_funcall(number_rb, rb_intern_LESS, 1, INT2FIX(0))) {
|
146
|
+
rb_raise(rb_eRangeError, "can't convert negative number to uint64_t");
|
147
|
+
}
|
148
|
+
char buffer[KERNAUX_UTOA2_BUFFER_SIZE];
|
149
|
+
kernaux_utoa2(number, buffer);
|
150
|
+
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
|
151
|
+
}
|
152
|
+
|
153
|
+
VALUE rb_KernAux_itoa2(
|
154
|
+
const VALUE self_rb __attribute__((unused)),
|
155
|
+
const VALUE number_rb
|
156
|
+
) {
|
157
|
+
const int64_t number = NUM2LL(number_rb);
|
158
|
+
char buffer[KERNAUX_ITOA2_BUFFER_SIZE];
|
159
|
+
kernaux_itoa2(number, buffer);
|
160
|
+
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
|
161
|
+
}
|
162
|
+
|
163
|
+
VALUE rb_KernAux_utoa8(
|
164
|
+
const VALUE self_rb __attribute__((unused)),
|
165
|
+
const VALUE number_rb
|
166
|
+
) {
|
167
|
+
const uint64_t number = NUM2ULL(number_rb);
|
168
|
+
if (rb_funcall(number_rb, rb_intern_LESS, 1, INT2FIX(0))) {
|
169
|
+
rb_raise(rb_eRangeError, "can't convert negative number to uint64_t");
|
170
|
+
}
|
171
|
+
char buffer[KERNAUX_UTOA8_BUFFER_SIZE];
|
172
|
+
kernaux_utoa8(number, buffer);
|
173
|
+
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
|
174
|
+
}
|
175
|
+
|
176
|
+
VALUE rb_KernAux_itoa8(
|
177
|
+
const VALUE self_rb __attribute__((unused)),
|
178
|
+
const VALUE number_rb
|
179
|
+
) {
|
180
|
+
const int64_t number = NUM2LL(number_rb);
|
181
|
+
char buffer[KERNAUX_ITOA8_BUFFER_SIZE];
|
182
|
+
kernaux_itoa8(number, buffer);
|
183
|
+
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
|
184
|
+
}
|
185
|
+
|
186
|
+
VALUE rb_KernAux_utoa10(
|
187
|
+
const VALUE self_rb __attribute__((unused)),
|
188
|
+
const VALUE number_rb
|
189
|
+
) {
|
190
|
+
const uint64_t number = NUM2ULL(number_rb);
|
191
|
+
if (rb_funcall(number_rb, rb_intern_LESS, 1, INT2FIX(0))) {
|
192
|
+
rb_raise(rb_eRangeError, "can't convert negative number to uint64_t");
|
193
|
+
}
|
194
|
+
char buffer[KERNAUX_UTOA10_BUFFER_SIZE];
|
195
|
+
kernaux_utoa10(number, buffer);
|
196
|
+
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
|
197
|
+
}
|
198
|
+
|
199
|
+
VALUE rb_KernAux_itoa10(
|
200
|
+
const VALUE self_rb __attribute__((unused)),
|
201
|
+
const VALUE number_rb
|
202
|
+
) {
|
203
|
+
const int64_t number = NUM2LL(number_rb);
|
204
|
+
char buffer[KERNAUX_ITOA10_BUFFER_SIZE];
|
205
|
+
kernaux_itoa10(number, buffer);
|
206
|
+
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
|
207
|
+
}
|
208
|
+
|
209
|
+
VALUE rb_KernAux_utoa16(
|
210
|
+
const VALUE self_rb __attribute__((unused)),
|
211
|
+
const VALUE number_rb
|
212
|
+
) {
|
213
|
+
const uint64_t number = NUM2ULL(number_rb);
|
214
|
+
if (rb_funcall(number_rb, rb_intern_LESS, 1, INT2FIX(0))) {
|
215
|
+
rb_raise(rb_eRangeError, "can't convert negative number to uint64_t");
|
216
|
+
}
|
217
|
+
char buffer[KERNAUX_UTOA16_BUFFER_SIZE];
|
218
|
+
kernaux_utoa16(number, buffer);
|
219
|
+
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
|
220
|
+
}
|
221
|
+
|
222
|
+
VALUE rb_KernAux_itoa16(
|
223
|
+
const VALUE self_rb __attribute__((unused)),
|
224
|
+
const VALUE number_rb
|
225
|
+
) {
|
226
|
+
const int64_t number = NUM2LL(number_rb);
|
227
|
+
char buffer[KERNAUX_ITOA16_BUFFER_SIZE];
|
228
|
+
kernaux_itoa16(number, buffer);
|
229
|
+
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
|
230
|
+
}
|
231
|
+
|
232
|
+
int convert_base(const VALUE base_rb)
|
233
|
+
{
|
234
|
+
if (TYPE(base_rb) == T_SYMBOL) {
|
235
|
+
const ID base_id = SYM2ID(base_rb);
|
236
|
+
if (base_id == rb_intern_b) return 'b';
|
237
|
+
else if (base_id == rb_intern_B) return 'B';
|
238
|
+
else if (base_id == rb_intern_h) return 'h';
|
239
|
+
else if (base_id == rb_intern_H) return 'H';
|
240
|
+
else if (base_id == rb_intern_o) return 'o';
|
241
|
+
else if (base_id == rb_intern_O) return 'O';
|
242
|
+
else if (base_id == rb_intern_d) return 'd';
|
243
|
+
else if (base_id == rb_intern_D) return 'D';
|
244
|
+
else if (base_id == rb_intern_x) return 'x';
|
245
|
+
else if (base_id == rb_intern_X) return 'X';
|
246
|
+
else {
|
247
|
+
rb_raise(rb_KernAux_InvalidNtoaBaseError, "invalid base");
|
248
|
+
}
|
249
|
+
} else {
|
250
|
+
return NUM2INT(base_rb);
|
251
|
+
}
|
252
|
+
}
|
253
|
+
|
254
|
+
#endif // KERNAUX_VERSION_WITH_NTOA
|
@@ -0,0 +1,210 @@
|
|
1
|
+
#include "main.h"
|
2
|
+
|
3
|
+
#include "dynarg.h"
|
4
|
+
|
5
|
+
#include <stddef.h>
|
6
|
+
#include <stdlib.h>
|
7
|
+
|
8
|
+
#ifdef KERNAUX_VERSION_WITH_PRINTF
|
9
|
+
|
10
|
+
/*************
|
11
|
+
* ::KernAux *
|
12
|
+
*************/
|
13
|
+
|
14
|
+
static VALUE rb_KernAux_snprintf1(int argc, const VALUE *argv, VALUE self);
|
15
|
+
|
16
|
+
static VALUE rb_KernAux_snprintf1_PROTECT(VALUE userdata);
|
17
|
+
|
18
|
+
/************************
|
19
|
+
* ::KernAux::Snprintf1 *
|
20
|
+
************************/
|
21
|
+
|
22
|
+
static VALUE rb_KernAux_Snprintf1 = Qnil;
|
23
|
+
|
24
|
+
static size_t rb_KernAux_Snprintf1_DSIZE(const void *ptr);
|
25
|
+
|
26
|
+
const rb_data_type_t rb_KernAux_Snprintf1_DTYPE = {
|
27
|
+
.wrap_struct_name = "KernAux::Snprintf1",
|
28
|
+
.parent = NULL,
|
29
|
+
.data = NULL,
|
30
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
31
|
+
.function = {
|
32
|
+
.dfree = RUBY_DEFAULT_FREE,
|
33
|
+
.dsize = rb_KernAux_Snprintf1_DSIZE,
|
34
|
+
.dmark = NULL,
|
35
|
+
.dcompact = NULL,
|
36
|
+
.reserved = { 0 },
|
37
|
+
},
|
38
|
+
};
|
39
|
+
|
40
|
+
struct rb_KernAux_Snprintf1_DATA {
|
41
|
+
const struct KernAux_PrintfFmt_Spec *spec;
|
42
|
+
const struct DynArg *dynarg;
|
43
|
+
int size;
|
44
|
+
const char *format;
|
45
|
+
char *str;
|
46
|
+
};
|
47
|
+
|
48
|
+
/********
|
49
|
+
* Main *
|
50
|
+
********/
|
51
|
+
|
52
|
+
void init_printf()
|
53
|
+
{
|
54
|
+
rb_gc_register_mark_object(
|
55
|
+
rb_KernAux_Snprintf1 =
|
56
|
+
// @api private
|
57
|
+
rb_define_class_under(rb_KernAux, "Snprintf1", rb_cObject));
|
58
|
+
rb_funcall(rb_KernAux, rb_intern("private_constant"), 1, ID2SYM(rb_intern("Snprintf1")));
|
59
|
+
|
60
|
+
rb_define_singleton_method(rb_KernAux, "snprintf1",
|
61
|
+
rb_KernAux_snprintf1, -1);
|
62
|
+
}
|
63
|
+
|
64
|
+
/*************
|
65
|
+
* ::KernAux *
|
66
|
+
*************/
|
67
|
+
|
68
|
+
VALUE rb_KernAux_snprintf1(
|
69
|
+
const int argc,
|
70
|
+
const VALUE *const argv_rb,
|
71
|
+
const VALUE self __attribute__((unused))
|
72
|
+
) {
|
73
|
+
if (argc < 2 || argc > 5) rb_raise(rb_eArgError, "expected 2, 3, 4 or 5 args");
|
74
|
+
|
75
|
+
const VALUE size_rb = argv_rb[0];
|
76
|
+
VALUE format_rb = argv_rb[1];
|
77
|
+
|
78
|
+
const int size = NUM2INT(size_rb);
|
79
|
+
const char *const format = StringValueCStr(format_rb);
|
80
|
+
|
81
|
+
if (size < 0) rb_raise(rb_eRangeError, "expected non-negative size");
|
82
|
+
|
83
|
+
const char *fmt = format;
|
84
|
+
|
85
|
+
while (*fmt && *fmt != '%') ++fmt;
|
86
|
+
if (*(fmt++) != '%') rb_raise(rb_eArgError, "invalid format");
|
87
|
+
|
88
|
+
struct KernAux_PrintfFmt_Spec spec = KernAux_PrintfFmt_Spec_create();
|
89
|
+
|
90
|
+
fmt = KernAux_PrintfFmt_Spec_parse(&spec, fmt);
|
91
|
+
|
92
|
+
while (*fmt) {
|
93
|
+
if (*(fmt++) == '%') rb_raise(rb_eArgError, "invalid format");
|
94
|
+
}
|
95
|
+
|
96
|
+
int arg_index = 2;
|
97
|
+
if (spec.set_width && argc > arg_index) {
|
98
|
+
KernAux_PrintfFmt_Spec_set_width(&spec, NUM2INT(argv_rb[arg_index++]));
|
99
|
+
}
|
100
|
+
if (spec.set_precision && argc > arg_index) {
|
101
|
+
KernAux_PrintfFmt_Spec_set_precision(&spec, NUM2INT(argv_rb[arg_index++]));
|
102
|
+
}
|
103
|
+
|
104
|
+
struct DynArg dynarg = DynArg_create();
|
105
|
+
if (argc > arg_index) {
|
106
|
+
VALUE arg_rb = argv_rb[arg_index];
|
107
|
+
|
108
|
+
if (spec.type == KERNAUX_PRINTF_FMT_TYPE_INT) {
|
109
|
+
DynArg_use_long_long(&dynarg, NUM2LL(arg_rb));
|
110
|
+
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_UINT) {
|
111
|
+
DynArg_use_unsigned_long_long(&dynarg, NUM2ULL(arg_rb));
|
112
|
+
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_FLOAT ||
|
113
|
+
spec.type == KERNAUX_PRINTF_FMT_TYPE_EXP)
|
114
|
+
{
|
115
|
+
DynArg_use_double(&dynarg, NUM2DBL(arg_rb));
|
116
|
+
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_CHAR) {
|
117
|
+
Check_Type(arg_rb, T_STRING);
|
118
|
+
DynArg_use_char(&dynarg, *StringValuePtr(arg_rb));
|
119
|
+
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_STR) {
|
120
|
+
Check_Type(arg_rb, T_STRING);
|
121
|
+
DynArg_use_str(&dynarg, StringValueCStr(arg_rb));
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
char *const str = malloc(size);
|
126
|
+
if (!str) rb_raise(rb_eNoMemError, "snprintf1 buffer malloc");
|
127
|
+
|
128
|
+
struct rb_KernAux_Snprintf1_DATA *userdata;
|
129
|
+
VALUE userdata_rb = TypedData_Make_Struct(
|
130
|
+
rb_KernAux_Snprintf1,
|
131
|
+
struct rb_KernAux_Snprintf1_DATA,
|
132
|
+
&rb_KernAux_Snprintf1_DTYPE,
|
133
|
+
userdata
|
134
|
+
);
|
135
|
+
if (NIL_P(userdata_rb) || userdata == NULL) {
|
136
|
+
free(str);
|
137
|
+
rb_raise(rb_eNoMemError, "snprintf1 userdata alloc");
|
138
|
+
}
|
139
|
+
|
140
|
+
userdata->spec = &spec;
|
141
|
+
userdata->dynarg = &dynarg;
|
142
|
+
userdata->size = size;
|
143
|
+
userdata->format = format;
|
144
|
+
userdata->str = str;
|
145
|
+
|
146
|
+
int state = 0;
|
147
|
+
VALUE result =
|
148
|
+
rb_protect(rb_KernAux_snprintf1_PROTECT, userdata_rb, &state);
|
149
|
+
|
150
|
+
free(str);
|
151
|
+
|
152
|
+
if (state == 0) {
|
153
|
+
return result;
|
154
|
+
} else {
|
155
|
+
rb_jump_tag(state);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
VALUE rb_KernAux_snprintf1_PROTECT(VALUE userdata_rb)
|
160
|
+
{
|
161
|
+
const struct rb_KernAux_Snprintf1_DATA *userdata = NULL;
|
162
|
+
TypedData_Get_Struct(
|
163
|
+
userdata_rb,
|
164
|
+
struct rb_KernAux_Snprintf1_DATA,
|
165
|
+
&rb_KernAux_Snprintf1_DTYPE,
|
166
|
+
userdata
|
167
|
+
);
|
168
|
+
|
169
|
+
int slen;
|
170
|
+
if (userdata->spec->set_width) {
|
171
|
+
if (userdata->spec->set_precision) {
|
172
|
+
slen = userdata->dynarg->use_dbl
|
173
|
+
? kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->width, userdata->spec->precision, userdata->dynarg->dbl)
|
174
|
+
: kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->width, userdata->spec->precision, userdata->dynarg->arg);
|
175
|
+
} else {
|
176
|
+
slen = userdata->dynarg->use_dbl
|
177
|
+
? kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->width, userdata->dynarg->dbl)
|
178
|
+
: kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->width, userdata->dynarg->arg);
|
179
|
+
}
|
180
|
+
} else {
|
181
|
+
if (userdata->spec->set_precision) {
|
182
|
+
slen = userdata->dynarg->use_dbl
|
183
|
+
? kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->precision, userdata->dynarg->dbl)
|
184
|
+
: kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->precision, userdata->dynarg->arg);
|
185
|
+
} else {
|
186
|
+
slen = userdata->dynarg->use_dbl
|
187
|
+
? kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->dynarg->dbl)
|
188
|
+
: kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->dynarg->arg);
|
189
|
+
}
|
190
|
+
}
|
191
|
+
|
192
|
+
const VALUE output_rb =
|
193
|
+
rb_funcall(rb_str_new2(userdata->str), rb_intern_freeze, 0);
|
194
|
+
|
195
|
+
const VALUE result_rb = rb_ary_new2(2);
|
196
|
+
rb_ary_push(result_rb, output_rb);
|
197
|
+
rb_ary_push(result_rb, INT2NUM(slen));
|
198
|
+
return rb_funcall(result_rb, rb_intern_freeze, 0);
|
199
|
+
}
|
200
|
+
|
201
|
+
/************************
|
202
|
+
* ::KernAux::Snprintf1 *
|
203
|
+
************************/
|
204
|
+
|
205
|
+
size_t rb_KernAux_Snprintf1_DSIZE(const void *const ptr)
|
206
|
+
{
|
207
|
+
return sizeof(struct rb_KernAux_Snprintf1_DATA);
|
208
|
+
}
|
209
|
+
|
210
|
+
#endif // KERNAUX_VERSION_WITH_PRINTF
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#include "main.h"
|
2
|
+
|
3
|
+
static VALUE rb_KernAux_Version_with_cmdlineQN(VALUE self);
|
4
|
+
static VALUE rb_KernAux_Version_with_ntoaQN(VALUE self);
|
5
|
+
static VALUE rb_KernAux_Version_with_printfQN(VALUE self);
|
6
|
+
|
7
|
+
static VALUE rb_KernAux_Version = Qnil;
|
8
|
+
|
9
|
+
void init_version()
|
10
|
+
{
|
11
|
+
rb_gc_register_mark_object(rb_KernAux_Version =
|
12
|
+
rb_define_module_under(rb_KernAux, "Version"));
|
13
|
+
|
14
|
+
rb_define_singleton_method(rb_KernAux_Version, "with_cmdline?",
|
15
|
+
rb_KernAux_Version_with_cmdlineQN, 0);
|
16
|
+
rb_define_singleton_method(rb_KernAux_Version, "with_ntoa?",
|
17
|
+
rb_KernAux_Version_with_ntoaQN, 0);
|
18
|
+
rb_define_singleton_method(rb_KernAux_Version, "with_printf?",
|
19
|
+
rb_KernAux_Version_with_printfQN, 0);
|
20
|
+
}
|
21
|
+
|
22
|
+
VALUE rb_KernAux_Version_with_cmdlineQN(VALUE self)
|
23
|
+
{
|
24
|
+
#ifdef KERNAUX_VERSION_WITH_CMDLINE
|
25
|
+
return Qtrue;
|
26
|
+
#else
|
27
|
+
return Qfalse;
|
28
|
+
#endif
|
29
|
+
}
|
30
|
+
|
31
|
+
VALUE rb_KernAux_Version_with_ntoaQN(VALUE self)
|
32
|
+
{
|
33
|
+
#ifdef KERNAUX_VERSION_WITH_NTOA
|
34
|
+
return Qtrue;
|
35
|
+
#else
|
36
|
+
return Qfalse;
|
37
|
+
#endif
|
38
|
+
}
|
39
|
+
|
40
|
+
VALUE rb_KernAux_Version_with_printfQN(VALUE self)
|
41
|
+
{
|
42
|
+
#ifdef KERNAUX_VERSION_WITH_PRINTF
|
43
|
+
return Qtrue;
|
44
|
+
#else
|
45
|
+
return Qfalse;
|
46
|
+
#endif
|
47
|
+
}
|
data/kernaux.gemspec
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/kernaux/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
repo = 'https://github.com/tailix/libkernaux'
|
7
|
+
home = "#{repo}/tree/master/bindings/ruby"
|
8
|
+
bugs = "#{repo}/issues"
|
9
|
+
docs = "https://www.rubydoc.info/gems/kernaux/#{KernAux::VERSION}"
|
10
|
+
|
11
|
+
spec.name = 'kernaux'
|
12
|
+
spec.version = KernAux::VERSION
|
13
|
+
spec.license = 'MIT'
|
14
|
+
spec.homepage = home
|
15
|
+
spec.platform = Gem::Platform::RUBY
|
16
|
+
|
17
|
+
spec.required_ruby_version = '~> 3.0'
|
18
|
+
|
19
|
+
spec.authors = ['Alex Kotov']
|
20
|
+
spec.email = %w[kotovalexarian@gmail.com]
|
21
|
+
|
22
|
+
spec.summary =
|
23
|
+
'Binding to libkernaux - auxiliary library for kernel development'
|
24
|
+
|
25
|
+
spec.description = <<~DESCRIPTION.split("\n").map(&:strip).join ' '
|
26
|
+
Binding to libkernaux - auxiliary library for kernel development.
|
27
|
+
DESCRIPTION
|
28
|
+
|
29
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
30
|
+
spec.metadata['homepage_uri'] = home
|
31
|
+
spec.metadata['source_code_uri'] = home
|
32
|
+
spec.metadata['bug_tracker_uri'] = bugs
|
33
|
+
spec.metadata['documentation_uri'] = docs
|
34
|
+
|
35
|
+
spec.bindir = 'exe'
|
36
|
+
spec.require_paths = ['lib']
|
37
|
+
|
38
|
+
spec.files = Dir.chdir File.expand_path __dir__ do
|
39
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
40
|
+
f.match %r{\A(?:test|spec|features)/}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename f }
|
45
|
+
|
46
|
+
spec.extensions << 'ext/default/extconf.rb'
|
47
|
+
|
48
|
+
spec.add_development_dependency 'bundler', '~> 2.2'
|
49
|
+
spec.add_development_dependency 'pry', '~> 0.14'
|
50
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
51
|
+
spec.add_development_dependency 'rake-compiler', '~> 1.1'
|
52
|
+
spec.add_development_dependency 'rspec', '~> 3.10'
|
53
|
+
spec.add_development_dependency 'rubocop', '~> 1.25'
|
54
|
+
spec.add_development_dependency 'rubocop-performance', '~> 1.13'
|
55
|
+
spec.add_development_dependency 'rubocop-rake', '~> 0.6'
|
56
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.7'
|
57
|
+
spec.add_development_dependency 'simplecov', '~> 0.21'
|
58
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
59
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Style/Documentation
|
4
|
+
begin; end
|
5
|
+
|
6
|
+
module KernAux
|
7
|
+
# Default callback for assertions.
|
8
|
+
# @see .assert_cb
|
9
|
+
DEFAULT_ASSERT_CB = @assert_cb = lambda { |file, line, msg|
|
10
|
+
raise AssertError, "#{file}:#{line}:#{msg}"
|
11
|
+
}
|
12
|
+
|
13
|
+
# @!scope class
|
14
|
+
|
15
|
+
##
|
16
|
+
# @!attribute [rw] assert_cb
|
17
|
+
# Panic callback.
|
18
|
+
#
|
19
|
+
# @return [Proc]
|
20
|
+
#
|
21
|
+
# @api unsafe
|
22
|
+
#
|
23
|
+
# @see .panic
|
24
|
+
# @see .assert_do
|
25
|
+
##
|
26
|
+
|
27
|
+
##
|
28
|
+
# Raise assertion with implicit file and line, retrieved from `caller`, and
|
29
|
+
# explicit message.
|
30
|
+
#
|
31
|
+
# @param msg [String] any message
|
32
|
+
# @return [nil]
|
33
|
+
#
|
34
|
+
# @raise [AssertError] if {.assert_cb} have not been changed
|
35
|
+
#
|
36
|
+
# @see .assert_do Explicit file and line.
|
37
|
+
#
|
38
|
+
def self.panic(msg)
|
39
|
+
file, line = caller(1..1).first.split(':')[0..1]
|
40
|
+
assert_do file, Integer(line), msg
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# @!method assert_do(file, line, msg)
|
45
|
+
# Raise assertion with explicit file, line and message.
|
46
|
+
#
|
47
|
+
# @param file [String] file name, usually from `__FILE__`
|
48
|
+
# @param line [Integer] line number, usually from `__LINE__`
|
49
|
+
# @param msg [String] any message
|
50
|
+
# @return [nil]
|
51
|
+
#
|
52
|
+
# @raise [AssertError] if {.assert_cb} have not been changed
|
53
|
+
#
|
54
|
+
# @see .panic Implicit file and line
|
55
|
+
##
|
56
|
+
end
|
57
|
+
|
58
|
+
# rubocop:enable Style/Documentation
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Style/Documentation
|
4
|
+
begin; end
|
5
|
+
|
6
|
+
module KernAux
|
7
|
+
# @!scope class
|
8
|
+
|
9
|
+
##
|
10
|
+
# @!method cmdline(str)
|
11
|
+
# Parse command line.
|
12
|
+
#
|
13
|
+
# @param str [String] command line string
|
14
|
+
# @return [Array<String>] command line arguments
|
15
|
+
#
|
16
|
+
# @raise [CmdlineError] syntax is invalid
|
17
|
+
##
|
18
|
+
end
|
19
|
+
|
20
|
+
# rubocop:enable Style/Documentation
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KernAux
|
4
|
+
##
|
5
|
+
# Our base class for runtime errors.
|
6
|
+
#
|
7
|
+
class Error < RuntimeError; end
|
8
|
+
|
9
|
+
##
|
10
|
+
# Raised when assertion has failed or panic has been called.
|
11
|
+
#
|
12
|
+
# @see .panic
|
13
|
+
# @see .assert_do
|
14
|
+
#
|
15
|
+
class AssertError < Error; end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Raised when command line parsing goes wrong.
|
19
|
+
#
|
20
|
+
# @see .cmdline
|
21
|
+
#
|
22
|
+
class CmdlineError < Error; end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Raised when integer base is invalid.
|
26
|
+
#
|
27
|
+
# @see .utoa
|
28
|
+
# @see .itoa
|
29
|
+
#
|
30
|
+
class InvalidNtoaBaseError < Error; end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Raised when prefix is too long.
|
34
|
+
#
|
35
|
+
# @see .utoa
|
36
|
+
# @see .itoa
|
37
|
+
#
|
38
|
+
class TooLongNtoaPrefixError < Error; end
|
39
|
+
end
|