kernaux 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/Rakefile +14 -2
- data/ext/default/main.h +6 -0
- data/ext/default/printf.c +95 -166
- data/lib/kernaux/version.rb +1 -1
- data/lib/kernaux.rb +0 -1
- metadata +3 -4
- data/lib/kernaux/printf.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 575d6442a1d63f0c17a1679006ebcc61aa65174d1ff9a9feecd873fb0ed23077
|
4
|
+
data.tar.gz: 0dd0cb5e521520974de0eca0e7f3cf536d5557d6386094faf885575c0453f392
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e4c2dffb8776d91a701e3a2d10135a6dbaa459ec9208d921067e13fefee8a4ac368319c3e62003731f7dcfb6367c48d785ce1d0d2341dda7fdbaba5aaa99a31
|
7
|
+
data.tar.gz: 5ba213e81e45bca750c2a07062cf5db89650b5a49b4106909b285977c965ae90748c57527d5d851276c8f3e8ae21a6128f55c62adfd7300feb71caeecc6d8955
|
data/README.md
CHANGED
@@ -15,7 +15,7 @@ Install
|
|
15
15
|
Add the following to your `Gemfile`:
|
16
16
|
|
17
17
|
```ruby
|
18
|
-
gem 'kernaux', '~> 0.
|
18
|
+
gem 'kernaux', '~> 0.7.0'
|
19
19
|
```
|
20
20
|
|
21
21
|
Or add the following to your `*.gemspec`:
|
@@ -23,7 +23,7 @@ Or add the following to your `*.gemspec`:
|
|
23
23
|
```ruby
|
24
24
|
Gem::Specification.new do |spec|
|
25
25
|
# ...
|
26
|
-
spec.add_runtime_dependency 'kernaux', '~> 0.
|
26
|
+
spec.add_runtime_dependency 'kernaux', '~> 0.7.0'
|
27
27
|
# ...
|
28
28
|
end
|
29
29
|
```
|
data/Rakefile
CHANGED
@@ -20,13 +20,13 @@ CLEAN << 'doc'
|
|
20
20
|
CLEAN << 'spec/examples.txt'
|
21
21
|
|
22
22
|
desc 'Run default checks'
|
23
|
-
task default: %i[test lint
|
23
|
+
task default: %i[test lint]
|
24
24
|
|
25
25
|
desc 'Run tests'
|
26
26
|
task test: :spec
|
27
27
|
|
28
28
|
desc 'Run code analysis tools'
|
29
|
-
task lint: :
|
29
|
+
task lint: %i[rubocop cppcheck yard:cov]
|
30
30
|
|
31
31
|
desc 'Fix code style (rubocop --auto-correct)'
|
32
32
|
task fix: 'rubocop:auto_correct'
|
@@ -66,6 +66,18 @@ task :console do
|
|
66
66
|
sh 'bundle', 'exec', File.expand_path(File.join('bin', 'console'), __dir__)
|
67
67
|
end
|
68
68
|
|
69
|
+
desc 'Run cppcheck'
|
70
|
+
task :cppcheck do
|
71
|
+
sh(
|
72
|
+
'cppcheck',
|
73
|
+
'--quiet',
|
74
|
+
'--error-exitcode=1',
|
75
|
+
'--std=c99',
|
76
|
+
'--enable=warning,style,performance,portability',
|
77
|
+
__dir__,
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
69
81
|
namespace :yard do
|
70
82
|
desc 'Measure documentation coverage'
|
71
83
|
task :cov do
|
data/ext/default/main.h
CHANGED
data/ext/default/printf.c
CHANGED
@@ -1,208 +1,137 @@
|
|
1
1
|
#include "main.h"
|
2
|
-
|
3
2
|
#include "dynarg.h"
|
4
3
|
|
5
|
-
#
|
6
|
-
#include <stdlib.h>
|
4
|
+
#define BUFFER_SIZE 4096
|
7
5
|
|
8
6
|
#ifdef KERNAUX_VERSION_WITH_PRINTF
|
9
7
|
|
10
|
-
|
11
|
-
*
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
********/
|
8
|
+
/**
|
9
|
+
* Typical `printf`.
|
10
|
+
*
|
11
|
+
* @param format [String] format string
|
12
|
+
* @return [String] formatted output
|
13
|
+
*
|
14
|
+
* @example
|
15
|
+
* KernAux.sprintf 'foo%*scar%d', 5, 'bar', 123
|
16
|
+
* #=> "foo barcar123"
|
17
|
+
*/
|
18
|
+
static VALUE rb_KernAux_sprintf(int argc, VALUE *argv, VALUE self);
|
51
19
|
|
52
20
|
void init_printf()
|
53
21
|
{
|
54
|
-
|
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);
|
22
|
+
rb_define_singleton_method(rb_KernAux, "sprintf", rb_KernAux_sprintf, -1);
|
62
23
|
}
|
63
24
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
VALUE rb_KernAux_snprintf1(
|
69
|
-
const int argc,
|
70
|
-
const VALUE *const argv_rb,
|
71
|
-
const VALUE self KERNAUX_UNUSED
|
72
|
-
) {
|
73
|
-
if (argc < 2 || argc > 5) rb_raise(rb_eArgError, "expected 2, 3, 4 or 5 args");
|
25
|
+
#define TAKE_ARG \
|
26
|
+
if (arg_index >= argc) rb_raise(rb_eArgError, "too few arguments"); \
|
27
|
+
VALUE arg_rb = argv[arg_index++]; \
|
28
|
+
do {} while (0)
|
74
29
|
|
75
|
-
|
76
|
-
|
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");
|
30
|
+
VALUE rb_KernAux_sprintf(const int argc, VALUE *const argv, VALUE self)
|
31
|
+
{
|
32
|
+
if (argc == 0) rb_raise(rb_eArgError, "too few arguments");
|
82
33
|
|
83
|
-
const char *
|
34
|
+
const char *format = StringValueCStr(argv[0]);
|
35
|
+
int arg_index = 1;
|
36
|
+
VALUE result = rb_str_new_literal("");
|
84
37
|
|
85
|
-
while (*
|
86
|
-
|
38
|
+
while (*format) {
|
39
|
+
if (*format != '%') {
|
40
|
+
rb_str_cat(result, format, 1);
|
41
|
+
++format;
|
42
|
+
continue;
|
43
|
+
}
|
87
44
|
|
88
|
-
|
45
|
+
++format;
|
46
|
+
struct KernAux_PrintfFmt_Spec spec =
|
47
|
+
KernAux_PrintfFmt_Spec_create_out(&format);
|
89
48
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
if (spec.set_precision && argc > arg_index) {
|
99
|
-
KernAux_PrintfFmt_Spec_set_precision(&spec, NUM2INT(argv_rb[arg_index++]));
|
100
|
-
}
|
49
|
+
if (spec.set_width) {
|
50
|
+
TAKE_ARG;
|
51
|
+
KernAux_PrintfFmt_Spec_set_width(&spec, NUM2INT(arg_rb));
|
52
|
+
}
|
53
|
+
if (spec.set_precision) {
|
54
|
+
TAKE_ARG;
|
55
|
+
KernAux_PrintfFmt_Spec_set_precision(&spec, NUM2INT(arg_rb));
|
56
|
+
}
|
101
57
|
|
102
|
-
|
103
|
-
if (argc > arg_index) {
|
104
|
-
VALUE arg_rb = argv_rb[arg_index];
|
58
|
+
struct DynArg dynarg = DynArg_create();
|
105
59
|
|
106
60
|
if (spec.type == KERNAUX_PRINTF_FMT_TYPE_INT) {
|
61
|
+
TAKE_ARG;
|
107
62
|
DynArg_use_long_long(&dynarg, NUM2LL(arg_rb));
|
108
63
|
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_UINT) {
|
64
|
+
TAKE_ARG;
|
109
65
|
DynArg_use_unsigned_long_long(&dynarg, NUM2ULL(arg_rb));
|
110
66
|
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_FLOAT ||
|
111
67
|
spec.type == KERNAUX_PRINTF_FMT_TYPE_EXP)
|
112
68
|
{
|
69
|
+
TAKE_ARG;
|
113
70
|
DynArg_use_double(&dynarg, NUM2DBL(arg_rb));
|
114
71
|
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_CHAR) {
|
72
|
+
TAKE_ARG;
|
115
73
|
Check_Type(arg_rb, T_STRING);
|
116
74
|
DynArg_use_char(&dynarg, *StringValuePtr(arg_rb));
|
117
75
|
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_STR) {
|
76
|
+
TAKE_ARG;
|
118
77
|
Check_Type(arg_rb, T_STRING);
|
119
78
|
DynArg_use_str(&dynarg, StringValueCStr(arg_rb));
|
120
79
|
}
|
121
|
-
}
|
122
|
-
|
123
|
-
char *const str = malloc(size);
|
124
|
-
if (!str) rb_raise(rb_eNoMemError, "snprintf1 buffer malloc");
|
125
|
-
|
126
|
-
struct rb_KernAux_Snprintf1_DATA *userdata;
|
127
|
-
VALUE userdata_rb = TypedData_Make_Struct(
|
128
|
-
rb_KernAux_Snprintf1,
|
129
|
-
struct rb_KernAux_Snprintf1_DATA,
|
130
|
-
&rb_KernAux_Snprintf1_DTYPE,
|
131
|
-
userdata
|
132
|
-
);
|
133
|
-
if (NIL_P(userdata_rb) || userdata == NULL) {
|
134
|
-
free(str);
|
135
|
-
rb_raise(rb_eNoMemError, "snprintf1 userdata alloc");
|
136
|
-
}
|
137
|
-
|
138
|
-
userdata->spec = &spec;
|
139
|
-
userdata->dynarg = &dynarg;
|
140
|
-
userdata->size = size;
|
141
|
-
userdata->format = format;
|
142
|
-
userdata->str = str;
|
143
|
-
|
144
|
-
int state = 0;
|
145
|
-
VALUE result =
|
146
|
-
rb_protect(rb_KernAux_snprintf1_PROTECT, userdata_rb, &state);
|
147
|
-
|
148
|
-
free(str);
|
149
|
-
|
150
|
-
if (state == 0) {
|
151
|
-
return result;
|
152
|
-
} else {
|
153
|
-
rb_jump_tag(state);
|
154
|
-
}
|
155
|
-
}
|
156
80
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
81
|
+
// 1 additional byte for the '%' character.
|
82
|
+
// 1 additional byte for the terminating '\0' character.
|
83
|
+
char old_format[2 + spec.format_limit - spec.format_start];
|
84
|
+
memset(old_format, '\0', sizeof(old_format));
|
85
|
+
old_format[0] = '%';
|
86
|
+
strncpy(&old_format[1], spec.format_start, sizeof(old_format) - 2);
|
87
|
+
|
88
|
+
char buffer[BUFFER_SIZE];
|
89
|
+
int slen;
|
90
|
+
|
91
|
+
if (spec.set_width) {
|
92
|
+
if (spec.set_precision) {
|
93
|
+
if (dynarg.use_dbl) {
|
94
|
+
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
|
95
|
+
spec.width, spec.precision,
|
96
|
+
dynarg.dbl);
|
97
|
+
} else {
|
98
|
+
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
|
99
|
+
spec.width, spec.precision,
|
100
|
+
dynarg.arg);
|
101
|
+
}
|
102
|
+
} else {
|
103
|
+
if (dynarg.use_dbl) {
|
104
|
+
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
|
105
|
+
spec.width, dynarg.dbl);
|
106
|
+
} else {
|
107
|
+
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
|
108
|
+
spec.width, dynarg.arg);
|
109
|
+
}
|
110
|
+
}
|
173
111
|
} else {
|
174
|
-
|
175
|
-
|
176
|
-
|
112
|
+
if (spec.set_precision) {
|
113
|
+
if (dynarg.use_dbl) {
|
114
|
+
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
|
115
|
+
spec.precision, dynarg.dbl);
|
116
|
+
} else {
|
117
|
+
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
|
118
|
+
spec.precision, dynarg.arg);
|
119
|
+
}
|
120
|
+
} else {
|
121
|
+
if (dynarg.use_dbl) {
|
122
|
+
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format, dynarg.dbl);
|
123
|
+
} else {
|
124
|
+
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format, dynarg.arg);
|
125
|
+
}
|
126
|
+
}
|
177
127
|
}
|
178
|
-
} else {
|
179
|
-
if (userdata->spec->set_precision) {
|
180
|
-
slen = userdata->dynarg->use_dbl
|
181
|
-
? kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->precision, userdata->dynarg->dbl)
|
182
|
-
: kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->precision, userdata->dynarg->arg);
|
183
|
-
} else {
|
184
|
-
slen = userdata->dynarg->use_dbl
|
185
|
-
? kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->dynarg->dbl)
|
186
|
-
: kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->dynarg->arg);
|
187
|
-
}
|
188
|
-
}
|
189
128
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
const VALUE result_rb = rb_ary_new2(2);
|
194
|
-
rb_ary_push(result_rb, output_rb);
|
195
|
-
rb_ary_push(result_rb, INT2NUM(slen));
|
196
|
-
return rb_funcall(result_rb, rb_intern_freeze, 0);
|
197
|
-
}
|
129
|
+
rb_str_cat(result, buffer, slen);
|
130
|
+
}
|
198
131
|
|
199
|
-
|
200
|
-
* ::KernAux::Snprintf1 *
|
201
|
-
************************/
|
132
|
+
if (arg_index < argc) rb_raise(rb_eArgError, "too many arguments");
|
202
133
|
|
203
|
-
|
204
|
-
{
|
205
|
-
return sizeof(struct rb_KernAux_Snprintf1_DATA);
|
134
|
+
return rb_funcall(result, rb_intern_freeze, 0);
|
206
135
|
}
|
207
136
|
|
208
137
|
#endif // KERNAUX_VERSION_WITH_PRINTF
|
data/lib/kernaux/version.rb
CHANGED
data/lib/kernaux.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kernaux
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Kotov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-12-
|
11
|
+
date: 2022-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -197,7 +197,6 @@ files:
|
|
197
197
|
- lib/kernaux/cmdline.rb
|
198
198
|
- lib/kernaux/errors.rb
|
199
199
|
- lib/kernaux/ntoa.rb
|
200
|
-
- lib/kernaux/printf.rb
|
201
200
|
- lib/kernaux/version.rb
|
202
201
|
homepage: https://github.com/tailix/libkernaux/tree/master/bindings/ruby
|
203
202
|
licenses:
|
@@ -207,7 +206,7 @@ metadata:
|
|
207
206
|
homepage_uri: https://github.com/tailix/libkernaux/tree/master/bindings/ruby
|
208
207
|
source_code_uri: https://github.com/tailix/libkernaux/tree/master/bindings/ruby
|
209
208
|
bug_tracker_uri: https://github.com/tailix/libkernaux/issues
|
210
|
-
documentation_uri: https://www.rubydoc.info/gems/kernaux/0.
|
209
|
+
documentation_uri: https://www.rubydoc.info/gems/kernaux/0.7.0
|
211
210
|
post_install_message:
|
212
211
|
rdoc_options: []
|
213
212
|
require_paths:
|
data/lib/kernaux/printf.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# rubocop:disable Style/Documentation
|
4
|
-
begin; end
|
5
|
-
|
6
|
-
module KernAux
|
7
|
-
# Buffer size for {.sprintf1}.
|
8
|
-
# @todo Make it dynamic.
|
9
|
-
SPRINTF1_BUFFER_SIZE = 10_000
|
10
|
-
|
11
|
-
# @!scope class
|
12
|
-
|
13
|
-
# @!parse [ruby]
|
14
|
-
|
15
|
-
if Version.with_printf?
|
16
|
-
##
|
17
|
-
# Typical `printf`.
|
18
|
-
#
|
19
|
-
# @param args [Array<String,
|
20
|
-
# Array<(String, Object)>,
|
21
|
-
# Array<(String, Integer, Object)>>]
|
22
|
-
# @return [String] formatted output
|
23
|
-
#
|
24
|
-
# @example
|
25
|
-
# KernAux.sprintf 'foo', ['%*s', 5, 'bar'], 'car', ['%d', 123]
|
26
|
-
# #=> "foo barcar123"
|
27
|
-
#
|
28
|
-
def self.sprintf(*args)
|
29
|
-
args.map do |arg|
|
30
|
-
if arg.is_a? Array
|
31
|
-
sprintf1(*arg)
|
32
|
-
else
|
33
|
-
arg
|
34
|
-
end
|
35
|
-
end.join.freeze
|
36
|
-
end
|
37
|
-
|
38
|
-
##
|
39
|
-
# `printf` for single formatting parameter.
|
40
|
-
#
|
41
|
-
# @param format [String] formatting string
|
42
|
-
# @return [String] formatted output
|
43
|
-
#
|
44
|
-
# @see .sprintf Multiple formatting parameters
|
45
|
-
#
|
46
|
-
# @example
|
47
|
-
# KernAux.sprintf1 '%%' #=> "%"
|
48
|
-
# KernAux.sprintf1 '%s', 'foo' #=> "foo"
|
49
|
-
# KernAux.sprintf1 '%5s', 'foo' #=> " foo"
|
50
|
-
# KernAux.sprintf1 '%*s', 5, 'foo' #=> " foo"
|
51
|
-
#
|
52
|
-
def self.sprintf1(format, *args)
|
53
|
-
snprintf1(SPRINTF1_BUFFER_SIZE, format, *args).first
|
54
|
-
end
|
55
|
-
|
56
|
-
##
|
57
|
-
# @!method snprintf1(buffer_size, format, ...)
|
58
|
-
# `printf` for single formatting parameter with manual buffer size.
|
59
|
-
#
|
60
|
-
# @param buffer_size [Integer] buffer size (including terminating null
|
61
|
-
# character)
|
62
|
-
# @param format [String] formatting string
|
63
|
-
# @return [Array<(String, Integer)>] formatted output and it's size
|
64
|
-
#
|
65
|
-
# @see .sprintf1 Automatic buffer size
|
66
|
-
##
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# rubocop:enable Style/Documentation
|