ruby-magic 0.2.0 → 0.3.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.
@@ -1,23 +1,3 @@
1
- /* :enddoc: */
2
-
3
- /*
4
- * ruby-magic.h
5
- *
6
- * Copyright 2013-2015 Krzysztof Wilczynski
7
- *
8
- * Licensed under the Apache License, Version 2.0 (the "License");
9
- * you may not use this file except in compliance with the License.
10
- * You may obtain a copy of the License at
11
- *
12
- * http://www.apache.org/licenses/LICENSE-2.0
13
- *
14
- * Unless required by applicable law or agreed to in writing, software
15
- * distributed under the License is distributed on an "AS IS" BASIS,
16
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
- * See the License for the specific language governing permissions and
18
- * limitations under the License.
19
- */
20
-
21
1
  #if !defined(_RUBY_MAGIC_H)
22
2
  #define _RUBY_MAGIC_H 1
23
3
 
@@ -28,204 +8,289 @@ extern "C" {
28
8
  #include "common.h"
29
9
  #include "functions.h"
30
10
 
31
- #define DATA_P(x) (TYPE(x) == T_DATA)
32
- #define STRING_P(x) (TYPE(x) == T_STRING)
33
- #define ARRAY_P(x) (TYPE(x) == T_ARRAY)
11
+ #define MAGIC_SYNCHRONIZED(f, d) magic_lock(object, (f), (d))
34
12
 
35
- #if !defined(STR2CSTR)
36
- # define STR2CSTR(x) StringValuePtr(x)
37
- #endif
13
+ #define MAGIC_OBJECT(o) \
14
+ Data_Get_Struct(object, magic_object_t, (o))
38
15
 
39
- #if !defined(RVAL2CSTR)
40
- # define RVAL2CSTR(x) (NIL_P(x) ? NULL : STR2CSTR(x))
41
- #endif
16
+ #define MAGIC_COOKIE(o, c) \
17
+ ((c) = MAGIC_OBJECT((o))->cookie)
42
18
 
43
- #if !defined(CSTR2RVAL)
44
- # define CSTR2RVAL(x) ((x) == NULL ? Qnil : rb_str_new2(x))
45
- #endif
19
+ #define MAGIC_CLOSED_P(o) RTEST(rb_mgc_close_p((o)))
20
+ #define MAGIC_LOADED_P(o) RTEST(rb_mgc_load_p((o)))
46
21
 
47
- #if !defined(RARRAY_LEN)
48
- # define RARRAY_LEN(a) (RARRAY(a)->len)
49
- #endif
22
+ #define MAGIC_WARNING(i, ...) \
23
+ do { \
24
+ if (!(i) || !(rb_mgc_warning & BIT(i))) { \
25
+ rb_mgc_warning |= BIT(i); \
26
+ rb_warn(__VA_ARGS__); \
27
+ } \
28
+ } while(0)
50
29
 
51
- #if !defined(RSTRING_LEN)
52
- # define RSTRING_LEN(s) (RSTRING(s)->len)
53
- #endif
30
+ #define MAGIC_ARGUMENT_TYPE_ERROR(o, ...) \
31
+ rb_raise(rb_eTypeError, error(E_ARGUMENT_TYPE_INVALID), CLASS_NAME((o)), __VA_ARGS__)
54
32
 
55
- #if !defined(RSTRING_PTR)
56
- # define RSTRING_PTR(s) (RSTRING(s)->ptr)
57
- #endif
33
+ #define MAGIC_GENERIC_ERROR(k, e, m) \
34
+ rb_exc_raise(magic_generic_error((k), (e), error(m)))
58
35
 
59
- #define RSTRING_EMPTY_P(s) (RSTRING_LEN(s) == 0)
60
- #define RARRAY_EMPTY_P(a) (RARRAY_LEN(a) == 0)
61
- #define RARRAY_FIRST(a) (RARRAY_EMPTY_P(a) ? Qnil : RARRAY_PTR(a)[0])
62
-
63
- #define NOGVL_FUNCTION (VALUE (*)(void *))
64
-
65
- #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) && \
66
- defined(HAVE_RUBY_THREAD_H) && HAVE_RUBY_THREAD_H
67
- # include <ruby/thread.h>
68
- # define NOGVL(f, d) \
69
- rb_thread_call_without_gvl((f), (d), RUBY_UBF_IO, NULL)
70
- #elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
71
- # define NOGVL(f, d) \
72
- rb_thread_blocking_region(NOGVL_FUNCTION(f), (d), RUBY_UBF_IO, NULL)
73
- #else
74
- # include <rubysig.h>
75
- static inline VALUE
76
- fake_blocking_region(VALUE (*f)(ANYARGS), void *data)
77
- {
78
- VALUE rv;
36
+ #define MAGIC_LIBRARY_ERROR(c) \
37
+ rb_exc_raise(magic_library_error(rb_mgc_eMagicError, (c)))
79
38
 
80
- TRAP_BEG;
81
- rv = f(data);
82
- TRAP_END;
39
+ #define MAGIC_CHECK_INTEGER_TYPE(o) magic_check_type((o), T_FIXNUM)
40
+ #define MAGIC_CHECK_STRING_TYPE(o) magic_check_type((o), T_STRING)
83
41
 
84
- return rv;
85
- }
86
- # define NOGVL(f, d) fake_blocking_region(NOGVL_FUNCTION(f), (d))
87
- #endif
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)
88
47
 
89
- #define MAGIC_SYNCHRONIZED(f, d) magic_lock(object, (f), (d))
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
+ #define MAGIC_CHECK_ARRAY_OF_STRINGS(o) \
55
+ magic_check_type_array_of_strings((o))
90
56
 
91
- #define MAGIC_COOKIE(c) \
92
- Data_Get_Struct(object, struct magic_set, (c))
57
+ #define MAGIC_CHECK_OPEN(o) \
58
+ do { \
59
+ if (MAGIC_CLOSED_P(o)) \
60
+ MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError, EFAULT, \
61
+ E_MAGIC_LIBRARY_CLOSED); \
62
+ } while(0)
93
63
 
94
- #define MAGIC_CLOSED_P(o) RTEST(rb_mgc_closed((o)))
64
+ #define MAGIC_CHECK_LOADED(o) \
65
+ do { \
66
+ if (!MAGIC_LOADED_P(o)) \
67
+ MAGIC_GENERIC_ERROR(rb_mgc_eMagicError, EFAULT, \
68
+ E_MAGIC_LIBRARY_NOT_LOADED); \
69
+ } while(0)
95
70
 
96
- #define MAGIC_GENERIC_ERROR(k, e, m) \
97
- do { \
98
- VALUE __e_##k = magic_generic_error((k), (e), (m)); \
99
- rb_exc_raise(__e_##k); \
100
- } while(0)
71
+ #define MAGIC_STRINGIFY(s) #s
101
72
 
102
- #define MAGIC_LIBRARY_ERROR(c) \
103
- do { \
104
- VALUE __e_library = magic_library_error(rb_mgc_eMagicError, (c)); \
105
- rb_exc_raise(__e_library); \
106
- } while(0)
73
+ #define MAGIC_DEFINE_FLAG(c) \
74
+ rb_define_const(rb_cMagic, MAGIC_STRINGIFY(c), INT2NUM(MAGIC_##c));
107
75
 
108
- #define CHECK_MAGIC_OPEN(o) \
109
- do { \
110
- if (MAGIC_CLOSED_P(o)) { \
111
- MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError, EFAULT, \
112
- error(E_MAGIC_LIBRARY_CLOSED)); \
113
- } \
114
- } while(0) \
76
+ #define MAGIC_DEFINE_PARAMETER(c) \
77
+ rb_define_const(rb_cMagic, MAGIC_STRINGIFY(PARAM_##c), INT2NUM(MAGIC_PARAM_##c));
115
78
 
116
79
  #define error(t) errors[(t)]
117
80
 
118
81
  enum error {
119
- E_UNKNOWN = 0,
120
- E_NOT_IMPLEMENTED,
121
- E_MAGIC_LIBRARY_INITIALIZE,
122
- E_MAGIC_LIBRARY_CLOSED,
123
- E_FLAG_INVALID_VALUE,
124
- E_FLAG_NOT_IMPLEMENTED
82
+ E_UNKNOWN = 0,
83
+ E_NOT_ENOUGH_MEMORY,
84
+ E_ARGUMENT_MISSING,
85
+ E_ARGUMENT_TYPE_INVALID,
86
+ E_ARGUMENT_TYPE_ARRAY_EMPTY,
87
+ E_ARGUMENT_TYPE_ARRAY_STRINGS,
88
+ E_MAGIC_LIBRARY_INITIALIZE,
89
+ E_MAGIC_LIBRARY_CLOSED,
90
+ E_MAGIC_LIBRARY_NOT_LOADED,
91
+ E_PARAM_INVALID_TYPE,
92
+ E_PARAM_INVALID_VALUE,
93
+ E_FLAG_NOT_IMPLEMENTED,
94
+ E_FLAG_INVALID_TYPE
125
95
  };
126
96
 
127
- union file {
128
- int fd;
129
- const char *path;
130
- };
97
+ typedef struct parameter {
98
+ size_t value;
99
+ int tag;
100
+ } parameter_t;
101
+
102
+ typedef union file {
103
+ const char *path;
104
+ int fd;
105
+ } file_t;
106
+
107
+ typedef struct buffers {
108
+ size_t count;
109
+ size_t *sizes;
110
+ void **pointers;
111
+ } buffers_t;
112
+
113
+ typedef struct magic_object {
114
+ magic_t cookie;
115
+ VALUE mutex;
116
+ unsigned int database_loaded:1;
117
+ unsigned int stop_on_errors:1;
118
+ } magic_object_t;
119
+
120
+ typedef struct magic_arguments {
121
+ union {
122
+ file_t file;
123
+ parameter_t parameter;
124
+ buffers_t buffers;
125
+ } type;
126
+ magic_t cookie;
127
+ const char *result;
128
+ int flags;
129
+ int status;
130
+ unsigned int stop_on_errors:1;
131
+ } magic_arguments_t;
132
+
133
+ typedef struct magic_exception {
134
+ const char *magic_error;
135
+ VALUE klass;
136
+ int magic_errno;
137
+ } magic_exception_t;
131
138
 
132
- struct buffer {
133
- size_t size;
134
- const char *buffer;
139
+ static const char *errors[] = {
140
+ [E_UNKNOWN] = "an unknown error has occurred",
141
+ [E_NOT_ENOUGH_MEMORY] = "cannot allocate memory",
142
+ [E_ARGUMENT_MISSING] = "wrong number of arguments (given %d, expected %d)",
143
+ [E_ARGUMENT_TYPE_INVALID] = "wrong argument type %s (expected %s)",
144
+ [E_ARGUMENT_TYPE_ARRAY_EMPTY] = "arguments list cannot be empty (expected array of String)",
145
+ [E_ARGUMENT_TYPE_ARRAY_STRINGS] = "wrong argument type %s in arguments list (expected String)",
146
+ [E_MAGIC_LIBRARY_INITIALIZE] = "failed to initialize Magic library",
147
+ [E_MAGIC_LIBRARY_CLOSED] = "Magic library is not open",
148
+ [E_MAGIC_LIBRARY_NOT_LOADED] = "Magic library not loaded",
149
+ [E_PARAM_INVALID_TYPE] = "unknown or invalid parameter specified",
150
+ [E_PARAM_INVALID_VALUE] = "invalid parameter value specified",
151
+ [E_FLAG_NOT_IMPLEMENTED] = "flag is not implemented",
152
+ [E_FLAG_INVALID_TYPE] = "unknown or invalid flag specified",
153
+ NULL
135
154
  };
136
155
 
137
- typedef union file file_t;
138
- typedef struct buffer buffer_t;
139
-
140
- struct magic_arguments {
141
- int flags;
142
- magic_t cookie;
143
- union {
144
- file_t file;
145
- buffer_t buffer;
146
- } data;
147
- };
156
+ static inline VALUE
157
+ magic_shift(VALUE v)
158
+ {
159
+ return ARRAY_P(v) ? \
160
+ rb_funcall(v, rb_intern("shift"), 0, Qundef) : \
161
+ Qnil;
162
+ }
148
163
 
149
- struct magic_exception {
150
- int magic_errno;
151
- const char *magic_error;
152
- VALUE klass;
153
- };
164
+ static inline VALUE
165
+ magic_split(VALUE a, VALUE b)
166
+ {
167
+ return (STRING_P(a) && STRING_P(b)) ? \
168
+ rb_funcall(a, rb_intern("split"), 1, b) : \
169
+ Qnil;
170
+ }
154
171
 
155
- typedef struct magic_arguments magic_arguments_t;
156
- typedef struct magic_exception magic_exception_t;
172
+ static inline VALUE
173
+ magic_join(VALUE a, VALUE b)
174
+ {
175
+ return (ARRAY_P(a) && STRING_P(b)) ? \
176
+ rb_funcall(a, rb_intern("join"), 1, b) : \
177
+ Qnil;
178
+ }
157
179
 
158
- static const char *errors[] = {
159
- "unknown error",
160
- "function is not implemented",
161
- "failed to initialize Magic library",
162
- "Magic library is not open",
163
- "unknown or invalid flag specified",
164
- "flag is not implemented",
165
- NULL
166
- };
180
+ static inline VALUE
181
+ magic_flatten(VALUE v)
182
+ {
183
+ return ARRAY_P(v) ? \
184
+ rb_funcall(v, rb_intern("flatten"), 0, Qundef) : \
185
+ Qnil;
186
+ }
167
187
 
168
- inline static VALUE
169
- magic_size(VALUE v)
188
+ static int
189
+ magic_fileno(VALUE object)
170
190
  {
171
- if (ARRAY_P(v) || STRING_P(v)) {
172
- return rb_funcall(v, rb_intern("size"), 0, NULL);
173
- }
191
+ int fd;
192
+ rb_io_t *io;
193
+
194
+ if (rb_respond_to(object, rb_intern("fileno"))) {
195
+ object = rb_funcall(object, rb_intern("fileno"), 0, Qundef);
196
+ return NUM2INT(object);
197
+ }
198
+
199
+ if (!FILE_P(object))
200
+ object = rb_convert_type(object, T_FILE, "IO", "to_io");
174
201
 
175
- return Qnil;
202
+ GetOpenFile(object, io);
203
+ if ((fd = FPTR_TO_FD(io)) < 0)
204
+ rb_raise(rb_eIOError, "closed stream");
205
+
206
+ return fd;
176
207
  }
177
208
 
178
- inline static VALUE
179
- magic_shift(VALUE v)
209
+ static inline VALUE
210
+ magic_path(VALUE object)
180
211
  {
181
- if (ARRAY_P(v)) {
182
- return rb_funcall(v, rb_intern("shift"), 0, NULL);
183
- }
212
+ if (STRING_P(object))
213
+ return object;
184
214
 
185
- return Qnil;
215
+ if (rb_respond_to(object, rb_intern("to_path")))
216
+ return rb_funcall(object, rb_intern("to_path"), 0, Qundef);
217
+
218
+ if (rb_respond_to(object, rb_intern("path")))
219
+ return rb_funcall(object, rb_intern("path"), 0, Qundef);
220
+
221
+ if (rb_respond_to(object, rb_intern("to_s")))
222
+ return rb_funcall(object, rb_intern("to_s"), 0, Qundef);
223
+
224
+ return Qnil;
186
225
  }
187
226
 
188
- inline static VALUE
189
- magic_split(VALUE a, VALUE b)
227
+ static inline void
228
+ magic_check_type(VALUE object, int type)
190
229
  {
191
- if (STRING_P(a) && STRING_P(b)) {
192
- return rb_funcall(a, rb_intern("split"), 1, b);
193
- }
230
+ VALUE boolean = Qundef;
194
231
 
195
- return Qnil;
232
+ boolean = rb_obj_is_kind_of(object, T_INTEGER);
233
+ if (type == T_FIXNUM && !RVAL2CBOOL(boolean))
234
+ MAGIC_ARGUMENT_TYPE_ERROR(object, rb_class2name(T_INTEGER));
235
+
236
+ Check_Type(object, type);
196
237
  }
197
238
 
198
- inline static VALUE
199
- magic_join(VALUE a, VALUE b)
239
+ static inline void
240
+ magic_check_type_array_of_strings(VALUE object)
200
241
  {
201
- if (ARRAY_P(a) && STRING_P(b)) {
202
- return rb_funcall(a, rb_intern("join"), 1, b);
203
- }
204
-
205
- return Qnil;
242
+ VALUE value = Qundef;
243
+
244
+ for (int i = 0; i < RARRAY_LEN(object); i++) {
245
+ value = RARRAY_AREF(object, (long)i);
246
+ if (NIL_P(value) || !STRING_P(value))
247
+ rb_raise(rb_eTypeError,
248
+ error(E_ARGUMENT_TYPE_ARRAY_STRINGS),
249
+ CLASS_NAME(value));
250
+ }
206
251
  }
207
252
 
208
- RUBY_EXTERN ID id_at_flags, id_at_path, id_at_mutex;
253
+ RUBY_EXTERN ID id_at_flags;
254
+ RUBY_EXTERN ID id_at_paths;
209
255
 
210
256
  RUBY_EXTERN VALUE rb_cMagic;
211
257
 
212
258
  RUBY_EXTERN VALUE rb_mgc_eError;
213
259
  RUBY_EXTERN VALUE rb_mgc_eMagicError;
214
260
  RUBY_EXTERN VALUE rb_mgc_eLibraryError;
261
+ RUBY_EXTERN VALUE rb_mgc_eParameterError;
215
262
  RUBY_EXTERN VALUE rb_mgc_eFlagsError;
216
263
  RUBY_EXTERN VALUE rb_mgc_eNotImplementedError;
217
264
 
265
+ RUBY_EXTERN VALUE rb_mgc_get_do_not_auto_load_global(VALUE object);
266
+ RUBY_EXTERN VALUE rb_mgc_set_do_not_auto_load_global(VALUE object,
267
+ VALUE value);
268
+
269
+ RUBY_EXTERN VALUE rb_mgc_get_do_not_stop_on_error_global(VALUE object);
270
+ RUBY_EXTERN VALUE rb_mgc_set_do_not_stop_on_error_global(VALUE object,
271
+ VALUE value);
272
+
218
273
  RUBY_EXTERN VALUE rb_mgc_initialize(VALUE object, VALUE arguments);
219
274
 
275
+ RUBY_EXTERN VALUE rb_mgc_get_do_not_stop_on_error(VALUE object);
276
+ RUBY_EXTERN VALUE rb_mgc_set_do_not_stop_on_error(VALUE object, VALUE value);
277
+
278
+ RUBY_EXTERN VALUE rb_mgc_open_p(VALUE object);
220
279
  RUBY_EXTERN VALUE rb_mgc_close(VALUE object);
221
- RUBY_EXTERN VALUE rb_mgc_closed(VALUE object);
280
+ RUBY_EXTERN VALUE rb_mgc_close_p(VALUE object);
222
281
 
223
- RUBY_EXTERN VALUE rb_mgc_get_path(VALUE object);
282
+ RUBY_EXTERN VALUE rb_mgc_get_paths(VALUE object);
283
+
284
+ RUBY_EXTERN VALUE rb_mgc_get_parameter(VALUE object, VALUE tag);
285
+ RUBY_EXTERN VALUE rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value);
224
286
 
225
287
  RUBY_EXTERN VALUE rb_mgc_get_flags(VALUE object);
226
288
  RUBY_EXTERN VALUE rb_mgc_set_flags(VALUE object, VALUE value);
227
289
 
228
290
  RUBY_EXTERN VALUE rb_mgc_load(VALUE object, VALUE arguments);
291
+ RUBY_EXTERN VALUE rb_mgc_load_buffers(VALUE object, VALUE arguments);
292
+ RUBY_EXTERN VALUE rb_mgc_load_p(VALUE object);
293
+
229
294
  RUBY_EXTERN VALUE rb_mgc_compile(VALUE object, VALUE arguments);
230
295
  RUBY_EXTERN VALUE rb_mgc_check(VALUE object, VALUE arguments);
231
296
 
@@ -240,5 +305,3 @@ RUBY_EXTERN VALUE rb_mgc_version(VALUE object);
240
305
  #endif
241
306
 
242
307
  #endif /* _RUBY_MAGIC_H */
243
-
244
- /* vim: set ts=8 sw=4 sts=2 et : */