kernaux 0.6.1 → 0.7.0

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
  SHA256:
3
- metadata.gz: d133e744a0189eaf3251ac677994455f409cec24f67a665fcea9ee28759a3204
4
- data.tar.gz: dc132268794f4aa577bb5c3b89837f7cd6fb821ce05d217d4891956096e7d1e3
3
+ metadata.gz: 575d6442a1d63f0c17a1679006ebcc61aa65174d1ff9a9feecd873fb0ed23077
4
+ data.tar.gz: 0dd0cb5e521520974de0eca0e7f3cf536d5557d6386094faf885575c0453f392
5
5
  SHA512:
6
- metadata.gz: 19e7444add8923f062ad2be547c4f832497df83938c71782edd43b489c0920a26d07dc7adeb4a8a05a235ff202d180bd8d30758c55a1e98f55eec67dea3f215e
7
- data.tar.gz: c0fbe8b5854630b0de6d44735f21efef5ff0733a8cfe8234a027d680b5369330c8e449f5d424a6211e1e716f59bc02e5fb9321dd20e62b7c0cd197513951b696
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.6.1'
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.6.1'
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 yard:cov]
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: :rubocop
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
@@ -4,6 +4,12 @@
4
4
  #include <kernaux.h>
5
5
  #include <ruby.h>
6
6
 
7
+ #include <stdbool.h>
8
+ #include <stddef.h>
9
+ #include <stdint.h>
10
+ #include <stdlib.h>
11
+ #include <string.h>
12
+
7
13
  extern ID rb_intern_call;
8
14
  extern ID rb_intern_freeze;
9
15
  extern ID rb_intern_LESS;
data/ext/default/printf.c CHANGED
@@ -1,208 +1,137 @@
1
1
  #include "main.h"
2
-
3
2
  #include "dynarg.h"
4
3
 
5
- #include <stddef.h>
6
- #include <stdlib.h>
4
+ #define BUFFER_SIZE 4096
7
5
 
8
6
  #ifdef KERNAUX_VERSION_WITH_PRINTF
9
7
 
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
- ********/
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
- 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);
22
+ rb_define_singleton_method(rb_KernAux, "sprintf", rb_KernAux_sprintf, -1);
62
23
  }
63
24
 
64
- /*************
65
- * ::KernAux *
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
- 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");
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 *fmt = format;
34
+ const char *format = StringValueCStr(argv[0]);
35
+ int arg_index = 1;
36
+ VALUE result = rb_str_new_literal("");
84
37
 
85
- while (*fmt && *fmt != '%') ++fmt;
86
- if (*(fmt++) != '%') rb_raise(rb_eArgError, "invalid format");
38
+ while (*format) {
39
+ if (*format != '%') {
40
+ rb_str_cat(result, format, 1);
41
+ ++format;
42
+ continue;
43
+ }
87
44
 
88
- struct KernAux_PrintfFmt_Spec spec = KernAux_PrintfFmt_Spec_create_out(&fmt);
45
+ ++format;
46
+ struct KernAux_PrintfFmt_Spec spec =
47
+ KernAux_PrintfFmt_Spec_create_out(&format);
89
48
 
90
- while (*fmt) {
91
- if (*(fmt++) == '%') rb_raise(rb_eArgError, "invalid format");
92
- }
93
-
94
- int arg_index = 2;
95
- if (spec.set_width && argc > arg_index) {
96
- KernAux_PrintfFmt_Spec_set_width(&spec, NUM2INT(argv_rb[arg_index++]));
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
- struct DynArg dynarg = DynArg_create();
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
- VALUE rb_KernAux_snprintf1_PROTECT(VALUE userdata_rb)
158
- {
159
- const struct rb_KernAux_Snprintf1_DATA *userdata = NULL;
160
- TypedData_Get_Struct(
161
- userdata_rb,
162
- struct rb_KernAux_Snprintf1_DATA,
163
- &rb_KernAux_Snprintf1_DTYPE,
164
- userdata
165
- );
166
-
167
- int slen;
168
- if (userdata->spec->set_width) {
169
- if (userdata->spec->set_precision) {
170
- slen = userdata->dynarg->use_dbl
171
- ? kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->width, userdata->spec->precision, userdata->dynarg->dbl)
172
- : kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->width, userdata->spec->precision, userdata->dynarg->arg);
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
- slen = userdata->dynarg->use_dbl
175
- ? kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->width, userdata->dynarg->dbl)
176
- : kernaux_snprintf(userdata->str, userdata->size, userdata->format, userdata->spec->width, userdata->dynarg->arg);
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
- const VALUE output_rb =
191
- rb_funcall(rb_str_new2(userdata->str), rb_intern_freeze, 0);
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
- size_t rb_KernAux_Snprintf1_DSIZE(const void *const ptr)
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  module KernAux
4
4
  # Gem version.
5
- VERSION = '0.6.1'
5
+ VERSION = '0.7.0'
6
6
 
7
7
  ##
8
8
  # This module includes functions to determine if specific features are
data/lib/kernaux.rb CHANGED
@@ -17,4 +17,3 @@ require_relative 'kernaux/assert'
17
17
  require_relative 'kernaux/cmdline'
18
18
  require_relative 'kernaux/errors'
19
19
  require_relative 'kernaux/ntoa'
20
- require_relative 'kernaux/printf'
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.6.1
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-05 00:00:00.000000000 Z
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.6.1
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:
@@ -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