ruby-magic 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 : */