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 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