ruby-magic 0.3.2 → 0.5.3

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.
@@ -10,11 +10,8 @@ extern "C" {
10
10
 
11
11
  #define MAGIC_SYNCHRONIZED(f, d) magic_lock(object, (f), (d))
12
12
 
13
- #define MAGIC_OBJECT(o) \
14
- Data_Get_Struct(object, magic_object_t, (o))
15
-
16
- #define MAGIC_COOKIE(o, c) \
17
- ((c) = MAGIC_OBJECT((o))->cookie)
13
+ #define MAGIC_OBJECT(o, t) \
14
+ TypedData_Get_Struct((o), rb_mgc_object_t, &rb_mgc_type, (t))
18
15
 
19
16
  #define MAGIC_CLOSED_P(o) RTEST(rb_mgc_close_p((o)))
20
17
  #define MAGIC_LOADED_P(o) RTEST(rb_mgc_load_p((o)))
@@ -25,64 +22,66 @@ extern "C" {
25
22
  rb_mgc_warning |= BIT(i); \
26
23
  rb_warn(__VA_ARGS__); \
27
24
  } \
28
- } while(0)
25
+ } while (0)
26
+
27
+ #define MAGIC_ERRORS(t) ruby_magic_errors[(t)]
29
28
 
30
29
  #define MAGIC_ARGUMENT_TYPE_ERROR(o, ...) \
31
- rb_raise(rb_eTypeError, error(E_ARGUMENT_TYPE_INVALID), CLASS_NAME((o)), __VA_ARGS__)
30
+ rb_raise(rb_eTypeError, MAGIC_ERRORS(E_ARGUMENT_TYPE_INVALID), CLASS_NAME((o)), __VA_ARGS__)
32
31
 
33
32
  #define MAGIC_GENERIC_ERROR(k, e, m) \
34
- rb_exc_raise(magic_generic_error((k), (e), error(m)))
33
+ rb_exc_raise(magic_generic_error((k), (e), MAGIC_ERRORS(m)))
35
34
 
36
35
  #define MAGIC_LIBRARY_ERROR(c) \
37
- rb_exc_raise(magic_library_error(rb_mgc_eMagicError, (c)))
36
+ rb_exc_raise(magic_library_error(rb_mgc_eMagicError, (c)->cookie))
38
37
 
39
38
  #define MAGIC_CHECK_INTEGER_TYPE(o) magic_check_type((o), T_FIXNUM)
40
39
  #define MAGIC_CHECK_STRING_TYPE(o) magic_check_type((o), T_STRING)
41
40
 
42
- #define MAGIC_CHECK_ARGUMENT_MISSING(t, o) \
43
- do { \
44
- if ((t) < (o)) \
45
- rb_raise(rb_eArgError, error(E_ARGUMENT_MISSING), (t), (o)); \
46
- } while(0)
47
-
48
- #define MAGIC_CHECK_ARRAY_EMPTY(o) \
49
- do { \
50
- if (RARRAY_EMPTY_P(o)) \
51
- rb_raise(rb_eArgError, "%s", error(E_ARGUMENT_TYPE_ARRAY_EMPTY)); \
52
- } while(0)
53
-
54
41
  #define MAGIC_CHECK_ARRAY_OF_STRINGS(o) \
55
42
  magic_check_type_array_of_strings((o))
56
43
 
44
+ #define MAGIC_CHECK_ARGUMENT_MISSING(t, o) \
45
+ do { \
46
+ if ((t) < (o)) \
47
+ rb_raise(rb_eArgError, MAGIC_ERRORS(E_ARGUMENT_MISSING), (t), (o)); \
48
+ } while (0)
49
+
50
+ #define MAGIC_CHECK_ARRAY_EMPTY(o) \
51
+ do { \
52
+ if (RARRAY_EMPTY_P(o)) \
53
+ rb_raise(rb_eArgError, "%s", MAGIC_ERRORS(E_ARGUMENT_TYPE_ARRAY_EMPTY)); \
54
+ } while (0)
55
+
56
+
57
57
  #define MAGIC_CHECK_OPEN(o) \
58
58
  do { \
59
59
  if (MAGIC_CLOSED_P(o)) \
60
60
  MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError, EFAULT, \
61
61
  E_MAGIC_LIBRARY_CLOSED); \
62
- } while(0)
62
+ } while (0)
63
63
 
64
64
  #define MAGIC_CHECK_LOADED(o) \
65
65
  do { \
66
66
  if (!MAGIC_LOADED_P(o)) \
67
67
  MAGIC_GENERIC_ERROR(rb_mgc_eMagicError, EFAULT, \
68
68
  E_MAGIC_LIBRARY_NOT_LOADED); \
69
- } while(0)
69
+ } while (0)
70
70
 
71
71
  #define MAGIC_STRINGIFY(s) #s
72
72
 
73
73
  #define MAGIC_DEFINE_FLAG(c) \
74
- rb_define_const(rb_cMagic, MAGIC_STRINGIFY(c), INT2NUM(MAGIC_##c));
74
+ rb_define_const(rb_cMagic, MAGIC_STRINGIFY(c), INT2NUM(MAGIC_##c))
75
75
 
76
76
  #define MAGIC_DEFINE_PARAMETER(c) \
77
- rb_define_const(rb_cMagic, MAGIC_STRINGIFY(PARAM_##c), INT2NUM(MAGIC_PARAM_##c));
78
-
79
- #define error(t) errors[(t)]
77
+ rb_define_const(rb_cMagic, MAGIC_STRINGIFY(PARAM_##c), INT2NUM(MAGIC_PARAM_##c))
80
78
 
81
- enum error {
79
+ enum ruby_magic_error {
82
80
  E_UNKNOWN = 0,
83
81
  E_NOT_ENOUGH_MEMORY,
84
82
  E_ARGUMENT_MISSING,
85
83
  E_ARGUMENT_TYPE_INVALID,
84
+ E_ARGUMENT_TYPE_UNKNOWN,
86
85
  E_ARGUMENT_TYPE_ARRAY_EMPTY,
87
86
  E_ARGUMENT_TYPE_ARRAY_STRINGS,
88
87
  E_MAGIC_LIBRARY_INITIALIZE,
@@ -94,53 +93,53 @@ enum error {
94
93
  E_FLAG_INVALID_TYPE
95
94
  };
96
95
 
97
- typedef struct parameter {
98
- size_t value;
96
+ struct parameter {
99
97
  int tag;
100
- } parameter_t;
98
+ size_t value;
99
+ };
101
100
 
102
- typedef union file {
101
+ union file {
103
102
  const char *path;
104
103
  int fd;
105
- } file_t;
104
+ };
106
105
 
107
- typedef struct buffers {
106
+ struct buffers {
108
107
  size_t count;
109
108
  size_t *sizes;
110
109
  void **pointers;
111
- } buffers_t;
110
+ };
112
111
 
113
112
  typedef struct magic_object {
114
113
  magic_t cookie;
115
114
  VALUE mutex;
116
115
  unsigned int database_loaded:1;
117
116
  unsigned int stop_on_errors:1;
118
- } magic_object_t;
117
+ } rb_mgc_object_t;
119
118
 
120
119
  typedef struct magic_arguments {
120
+ rb_mgc_object_t *magic_object;
121
121
  union {
122
- file_t file;
123
- parameter_t parameter;
124
- buffers_t buffers;
125
- } type;
126
- magic_t cookie;
122
+ struct parameter parameter;
123
+ union file file;
124
+ struct buffers buffers;
125
+ };
127
126
  const char *result;
128
- int flags;
129
127
  int status;
130
- unsigned int stop_on_errors:1;
131
- } magic_arguments_t;
128
+ int flags;
129
+ } rb_mgc_arguments_t;
132
130
 
133
- typedef struct magic_exception {
131
+ typedef struct magic_error {
134
132
  const char *magic_error;
135
133
  VALUE klass;
136
134
  int magic_errno;
137
- } magic_exception_t;
135
+ } rb_mgc_error_t;
138
136
 
139
- static const char *errors[] = {
137
+ static const char * const ruby_magic_errors[] = {
140
138
  [E_UNKNOWN] = "an unknown error has occurred",
141
139
  [E_NOT_ENOUGH_MEMORY] = "cannot allocate memory",
142
140
  [E_ARGUMENT_MISSING] = "wrong number of arguments (given %d, expected %d)",
143
141
  [E_ARGUMENT_TYPE_INVALID] = "wrong argument type %s (expected %s)",
142
+ [E_ARGUMENT_TYPE_UNKNOWN] = "unknown type 0x%x (0x%x given)",
144
143
  [E_ARGUMENT_TYPE_ARRAY_EMPTY] = "arguments list cannot be empty (expected array of String)",
145
144
  [E_ARGUMENT_TYPE_ARRAY_STRINGS] = "wrong argument type %s in arguments list (expected String)",
146
145
  [E_MAGIC_LIBRARY_INITIALIZE] = "failed to initialize Magic library",
@@ -153,38 +152,158 @@ static const char *errors[] = {
153
152
  NULL
154
153
  };
155
154
 
155
+ #if defined(MAGIC_CUSTOM_CHECK_TYPE)
156
+ static const char * const magic_ruby_types[] = {
157
+ "", /* Not an object */
158
+ [T_OBJECT] = "Object",
159
+ [T_CLASS] = "Class",
160
+ [T_MODULE] = "Module",
161
+ [T_FLOAT] = "Float",
162
+ [T_STRING] = "String",
163
+ [T_REGEXP] = "Regexp",
164
+ [T_ARRAY] = "Array",
165
+ [T_HASH] = "Hash",
166
+ [T_STRUCT] = "Struct",
167
+ [T_BIGNUM] = "Integer",
168
+ [T_FILE] = "File",
169
+ "", /* Internal use */
170
+ [T_MATCH] = "MatchData",
171
+ [T_COMPLEX] = "Complex",
172
+ [T_RATIONAL] = "Rational",
173
+ "", /* Internal use */
174
+ [T_NIL] = "nil",
175
+ [T_TRUE] = "true",
176
+ [T_FALSE] = "false",
177
+ [T_SYMBOL] = "Symbol",
178
+ [T_FIXNUM] = "Integer",
179
+ "", /* Internal use */
180
+ NULL
181
+ };
182
+
183
+ static const char *
184
+ magic_ruby_type_name(int type)
185
+ {
186
+ const char *name;
187
+
188
+ if (type >= ARRAY_SIZE(magic_ruby_types))
189
+ return NULL;
190
+
191
+ name = magic_ruby_types[type];
192
+ if (name)
193
+ return name;
194
+
195
+ return NULL;
196
+ }
197
+
198
+ static const char *
199
+ magic_ruby_class_name(VALUE object)
200
+ {
201
+ const char *name = NULL;
202
+
203
+ if (NIL_P(object))
204
+ name = "nil";
205
+ else if (RB_TYPE_P(object, T_TRUE))
206
+ name = "true";
207
+ else if (RB_TYPE_P(object, T_FALSE))
208
+ name = "false";
209
+ else
210
+ name = CLASS_NAME(object);
211
+
212
+ return name;
213
+ }
214
+
215
+ void
216
+ magic_check_ruby_type(VALUE object, int type)
217
+ {
218
+ const char *name;
219
+ int object_type = TYPE(object);
220
+
221
+ if (object == Qundef)
222
+ rb_bug("invalid type leaked to the Ruby space");
223
+
224
+ if (object_type > T_MASK || object_type == T_DATA)
225
+ goto error;
226
+
227
+ if (object_type == type)
228
+ return;
229
+
230
+ name = magic_ruby_type_name(type);
231
+ if (name)
232
+ rb_raise(rb_eTypeError,
233
+ MAGIC_ERRORS(E_ARGUMENT_TYPE_INVALID),
234
+ magic_ruby_class_name(object),
235
+ name);
236
+ error:
237
+ rb_raise(rb_eTypeError,
238
+ MAGIC_ERRORS(E_ARGUMENT_TYPE_UNKNOWN),
239
+ object_type,
240
+ type);
241
+ }
242
+ #endif /* MAGIC_CUSTOM_CHECK_TYPE */
243
+
244
+ static inline VALUE
245
+ magic_strip(VALUE v)
246
+ {
247
+ return (ARRAY_P(v) || STRING_P(v)) ?
248
+ rb_funcall(v, rb_intern("strip"), 0) :
249
+ Qnil;
250
+ }
251
+
156
252
  static inline VALUE
157
253
  magic_shift(VALUE v)
158
254
  {
159
- return ARRAY_P(v) ? \
160
- rb_funcall(v, rb_intern("shift"), 0) : \
255
+ return ARRAY_P(v) ?
256
+ rb_funcall(v, rb_intern("shift"), 0) :
161
257
  Qnil;
162
258
  }
163
259
 
164
260
  static inline VALUE
165
261
  magic_split(VALUE a, VALUE b)
166
262
  {
167
- return (STRING_P(a) && STRING_P(b)) ? \
168
- rb_funcall(a, rb_intern("split"), 1, b) : \
263
+ return (STRING_P(a) && STRING_P(b)) ?
264
+ rb_funcall(a, rb_intern("split"), 1, b) :
169
265
  Qnil;
170
266
  }
171
267
 
172
268
  static inline VALUE
173
269
  magic_join(VALUE a, VALUE b)
174
270
  {
175
- return (ARRAY_P(a) && STRING_P(b)) ? \
176
- rb_funcall(a, rb_intern("join"), 1, b) : \
271
+ return (ARRAY_P(a) && STRING_P(b)) ?
272
+ rb_funcall(a, rb_intern("join"), 1, b) :
177
273
  Qnil;
178
274
  }
179
275
 
180
276
  static inline VALUE
181
277
  magic_flatten(VALUE v)
182
278
  {
183
- return ARRAY_P(v) ? \
184
- rb_funcall(v, rb_intern("flatten"), 0) : \
279
+ return ARRAY_P(v) ?
280
+ rb_funcall(v, rb_intern("flatten"), 0) :
185
281
  Qnil;
186
282
  }
187
283
 
284
+ static inline VALUE
285
+ magic_strip_array(VALUE value) {
286
+ VALUE entry;
287
+ VALUE array = rb_ary_new();
288
+
289
+ for (int i = 0; i < RARRAY_LEN(value); i++) {
290
+ entry = rb_ary_entry(value, i);
291
+ if (NIL_P(entry))
292
+ continue;
293
+
294
+ if (STRING_P(entry)) {
295
+ if (RSTRING_EMPTY_P(entry))
296
+ continue;
297
+
298
+ entry = magic_strip(entry);
299
+ }
300
+
301
+ rb_ary_push(array, entry);
302
+ }
303
+
304
+ return array;
305
+ }
306
+
188
307
  static int
189
308
  magic_fileno(VALUE object)
190
309
  {
@@ -200,7 +319,9 @@ magic_fileno(VALUE object)
200
319
  object = rb_convert_type(object, T_FILE, "IO", "to_io");
201
320
 
202
321
  GetOpenFile(object, io);
203
- if ((fd = FPTR_TO_FD(io)) < 0)
322
+
323
+ fd = FPTR_TO_FD(io);
324
+ if (fd < 0)
204
325
  rb_raise(rb_eIOError, "closed stream");
205
326
 
206
327
  return fd;
@@ -227,33 +348,66 @@ magic_path(VALUE object)
227
348
  static inline void
228
349
  magic_check_type(VALUE object, RVALUE_TYPE type)
229
350
  {
230
- VALUE boolean = Qundef;
351
+ VALUE boolean;
231
352
 
232
353
  boolean = rb_obj_is_kind_of(object, T_INTEGER);
233
354
  if (type == T_FIXNUM && !RVAL2CBOOL(boolean))
234
355
  MAGIC_ARGUMENT_TYPE_ERROR(object, rb_class2name(T_INTEGER));
235
356
 
236
- Check_Type(object, type);
357
+ MAGIC_CHECK_RUBY_TYPE(object, type);
237
358
  }
238
359
 
239
360
  static inline void
240
361
  magic_check_type_array_of_strings(VALUE object)
241
362
  {
242
- VALUE value = Qundef;
363
+ VALUE value;
243
364
 
244
365
  for (int i = 0; i < RARRAY_LEN(object); i++) {
245
366
  value = RARRAY_AREF(object, (long)i);
246
367
  if (NIL_P(value) || !STRING_P(value))
247
368
  rb_raise(rb_eTypeError,
248
- error(E_ARGUMENT_TYPE_ARRAY_STRINGS),
369
+ MAGIC_ERRORS(E_ARGUMENT_TYPE_ARRAY_STRINGS),
249
370
  CLASS_NAME(value));
250
371
  }
251
372
  }
252
373
 
374
+ void Init_magic(void);
375
+
376
+ VALUE rb_mgc_get_do_not_auto_load_global(VALUE object);
377
+ VALUE rb_mgc_set_do_not_auto_load_global(VALUE object, VALUE value);
378
+ VALUE rb_mgc_get_do_not_stop_on_error_global(VALUE object);
379
+ VALUE rb_mgc_set_do_not_stop_on_error_global(VALUE object, VALUE value);
380
+
381
+ VALUE rb_mgc_initialize(VALUE object, VALUE arguments);
382
+
383
+ VALUE rb_mgc_get_do_not_stop_on_error(VALUE object);
384
+ VALUE rb_mgc_set_do_not_stop_on_error(VALUE object, VALUE value);
385
+
386
+ VALUE rb_mgc_open_p(VALUE object);
387
+ VALUE rb_mgc_close(VALUE object);
253
388
  VALUE rb_mgc_close_p(VALUE object);
389
+
390
+ VALUE rb_mgc_get_paths(VALUE object);
391
+
392
+ VALUE rb_mgc_get_parameter(VALUE object, VALUE tag);
393
+ VALUE rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value);
394
+
395
+ VALUE rb_mgc_get_flags(VALUE object);
396
+ VALUE rb_mgc_set_flags(VALUE object, VALUE value);
397
+
254
398
  VALUE rb_mgc_load(VALUE object, VALUE arguments);
399
+ VALUE rb_mgc_load_buffers(VALUE object, VALUE arguments);
400
+ VALUE rb_mgc_load_p(VALUE object);
401
+
402
+ VALUE rb_mgc_compile(VALUE object, VALUE arguments);
403
+ VALUE rb_mgc_check(VALUE object, VALUE arguments);
404
+
405
+ VALUE rb_mgc_file(VALUE object, VALUE value);
406
+ VALUE rb_mgc_buffer(VALUE object, VALUE value);
255
407
  VALUE rb_mgc_descriptor(VALUE object, VALUE value);
256
408
 
409
+ VALUE rb_mgc_version(VALUE object);
410
+
257
411
  #if defined(__cplusplus)
258
412
  }
259
413
  #endif
data/lib/magic/version.rb CHANGED
@@ -4,7 +4,7 @@ class Magic
4
4
  #
5
5
  # Current version of _Magic_.
6
6
  #
7
- VERSION = '0.3.2'.freeze
7
+ VERSION = '0.5.3'.freeze
8
8
 
9
9
  class << self
10
10
  #
data/lib/magic.rb CHANGED
@@ -1,6 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'magic/magic'
3
+ begin
4
+ ::RUBY_VERSION =~ /(\d+\.\d+)/
5
+ require_relative "magic/#{Regexp.last_match(1)}/magic"
6
+ rescue LoadError
7
+ # use "require" instead of "require_relative" because non-native gems will place C extension files
8
+ # in Gem::BasicSpecification#extension_dir after compilation (during normal installation), which
9
+ # is in $LOAD_PATH but not necessarily relative to this file (see #21 and nokogiri#2300)
10
+ require 'magic/magic'
11
+ end
12
+
4
13
  require_relative 'magic/version'
5
14
  require_relative 'magic/core/file'
6
15
  require_relative 'magic/core/string'
@@ -95,6 +104,8 @@ class Magic
95
104
  open(Magic::MIME, &block)
96
105
  end
97
106
 
107
+ alias_method :mime_type, :mime
108
+
98
109
  #
99
110
  # call-seq:
100
111
  # Magic.type -> self
@@ -175,6 +186,13 @@ class Magic
175
186
  end
176
187
 
177
188
  alias_method :fd, :descriptor
189
+
190
+ private
191
+
192
+ def default_paths
193
+ paths = Dir.glob(File.expand_path(File.join(File.dirname(__FILE__), "../ext/magic/share/*.mgc")))
194
+ paths.empty? ? nil : paths
195
+ end
178
196
  end
179
197
 
180
198
  private
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-magic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Krzysztof Wilczyński
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
- cert_chain:
11
- - kwilczynski-public.pem
12
- date: 2021-04-03 00:00:00.000000000 Z
10
+ cert_chain: []
11
+ date: 2021-12-22 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: mini_portile2
@@ -17,14 +16,14 @@ dependencies:
17
16
  requirements:
18
17
  - - "~>"
19
18
  - !ruby/object:Gem::Version
20
- version: 2.5.0
19
+ version: '2.6'
21
20
  type: :runtime
22
21
  prerelease: false
23
22
  version_requirements: !ruby/object:Gem::Requirement
24
23
  requirements:
25
24
  - - "~>"
26
25
  - !ruby/object:Gem::Version
27
- version: 2.5.0
26
+ version: '2.6'
28
27
  description: |
29
28
  File Magic in Ruby.
30
29
 
@@ -42,6 +41,7 @@ files:
42
41
  - LICENSE
43
42
  - NOTICE
44
43
  - README.md
44
+ - dependencies.yml
45
45
  - ext/magic/common.h
46
46
  - ext/magic/extconf.rb
47
47
  - ext/magic/functions.c
@@ -64,7 +64,7 @@ metadata:
64
64
  wiki_uri: https://github.com/kwilczynski/ruby-magic/wiki
65
65
  post_install_message: 'Thank you for installing!
66
66
 
67
- '
67
+ '
68
68
  rdoc_options: []
69
69
  require_paths:
70
70
  - lib
@@ -80,8 +80,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
80
  - !ruby/object:Gem::Version
81
81
  version: '0'
82
82
  requirements: []
83
- rubygems_version: 3.1.4
84
- signing_key:
83
+ rubygems_version: 3.2.28
84
+ signing_key:
85
85
  specification_version: 4
86
86
  summary: File Magic in Ruby
87
87
  test_files: []