kernaux 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of kernaux might be problematic. Click here for more details.
- 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/io.c +27 -0
- data/ext/default/main.c +38 -0
- data/ext/default/main.h +32 -0
- data/ext/default/ntoa.c +254 -0
- data/ext/default/printf.c +210 -0
- data/ext/default/version.c +59 -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/io.rb +22 -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 +21 -0
- metadata +232 -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,59 @@
|
|
1
|
+
#include "main.h"
|
2
|
+
|
3
|
+
static VALUE rb_KernAux_Version_with_cmdlineQN(VALUE self);
|
4
|
+
static VALUE rb_KernAux_Version_with_ioQN(VALUE self);
|
5
|
+
static VALUE rb_KernAux_Version_with_ntoaQN(VALUE self);
|
6
|
+
static VALUE rb_KernAux_Version_with_printfQN(VALUE self);
|
7
|
+
|
8
|
+
static VALUE rb_KernAux_Version = Qnil;
|
9
|
+
|
10
|
+
void init_version()
|
11
|
+
{
|
12
|
+
rb_gc_register_mark_object(rb_KernAux_Version =
|
13
|
+
rb_define_module_under(rb_KernAux, "Version"));
|
14
|
+
|
15
|
+
rb_define_singleton_method(rb_KernAux_Version, "with_cmdline?",
|
16
|
+
rb_KernAux_Version_with_cmdlineQN, 0);
|
17
|
+
rb_define_singleton_method(rb_KernAux_Version, "with_io?",
|
18
|
+
rb_KernAux_Version_with_ioQN, 0);
|
19
|
+
rb_define_singleton_method(rb_KernAux_Version, "with_ntoa?",
|
20
|
+
rb_KernAux_Version_with_ntoaQN, 0);
|
21
|
+
rb_define_singleton_method(rb_KernAux_Version, "with_printf?",
|
22
|
+
rb_KernAux_Version_with_printfQN, 0);
|
23
|
+
}
|
24
|
+
|
25
|
+
VALUE rb_KernAux_Version_with_cmdlineQN(VALUE self)
|
26
|
+
{
|
27
|
+
#ifdef KERNAUX_VERSION_WITH_CMDLINE
|
28
|
+
return Qtrue;
|
29
|
+
#else
|
30
|
+
return Qfalse;
|
31
|
+
#endif
|
32
|
+
}
|
33
|
+
|
34
|
+
VALUE rb_KernAux_Version_with_ioQN(VALUE self)
|
35
|
+
{
|
36
|
+
#ifdef KERNAUX_VERSION_WITH_IO
|
37
|
+
return Qtrue;
|
38
|
+
#else
|
39
|
+
return Qfalse;
|
40
|
+
#endif
|
41
|
+
}
|
42
|
+
|
43
|
+
VALUE rb_KernAux_Version_with_ntoaQN(VALUE self)
|
44
|
+
{
|
45
|
+
#ifdef KERNAUX_VERSION_WITH_NTOA
|
46
|
+
return Qtrue;
|
47
|
+
#else
|
48
|
+
return Qfalse;
|
49
|
+
#endif
|
50
|
+
}
|
51
|
+
|
52
|
+
VALUE rb_KernAux_Version_with_printfQN(VALUE self)
|
53
|
+
{
|
54
|
+
#ifdef KERNAUX_VERSION_WITH_PRINTF
|
55
|
+
return Qtrue;
|
56
|
+
#else
|
57
|
+
return Qfalse;
|
58
|
+
#endif
|
59
|
+
}
|
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
|