Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | ** etc.c |
3 | | ** |
4 | | ** See Copyright Notice in mruby.h |
5 | | */ |
6 | | |
7 | | #include <mruby.h> |
8 | | #include <mruby/string.h> |
9 | | #include <mruby/data.h> |
10 | | #include <mruby/class.h> |
11 | | #include <mruby/numeric.h> |
12 | | #include <mruby/internal.h> |
13 | | |
14 | | MRB_API struct RData* |
15 | | mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const mrb_data_type *type) |
16 | 5.13k | { |
17 | 5.13k | struct RData *data; |
18 | | |
19 | 5.13k | data = MRB_OBJ_ALLOC(mrb, MRB_TT_CDATA, klass); |
20 | 5.13k | data->data = ptr; |
21 | 5.13k | data->type = type; |
22 | | |
23 | 5.13k | return data; |
24 | 5.13k | } |
25 | | |
26 | | MRB_API void |
27 | | mrb_data_check_type(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) |
28 | 0 | { |
29 | 0 | if (!mrb_data_p(obj)) { |
30 | 0 | mrb_check_type(mrb, obj, MRB_TT_CDATA); |
31 | 0 | } |
32 | 0 | if (DATA_TYPE(obj) != type) { |
33 | 0 | const mrb_data_type *t2 = DATA_TYPE(obj); |
34 | |
|
35 | 0 | if (t2) { |
36 | 0 | mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %s (expected %s)", |
37 | 0 | t2->struct_name, type->struct_name); |
38 | 0 | } |
39 | 0 | else { |
40 | 0 | mrb_raisef(mrb, E_TYPE_ERROR, "uninitialized %t (expected %s)", |
41 | 0 | obj, type->struct_name); |
42 | 0 | } |
43 | 0 | } |
44 | 0 | } |
45 | | |
46 | | MRB_API void* |
47 | | mrb_data_check_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) |
48 | 0 | { |
49 | 0 | if (!mrb_data_p(obj)) { |
50 | 0 | return NULL; |
51 | 0 | } |
52 | 0 | if (DATA_TYPE(obj) != type) { |
53 | 0 | return NULL; |
54 | 0 | } |
55 | 0 | return DATA_PTR(obj); |
56 | 0 | } |
57 | | |
58 | | MRB_API void* |
59 | | mrb_data_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) |
60 | 0 | { |
61 | 0 | mrb_data_check_type(mrb, obj, type); |
62 | 0 | return DATA_PTR(obj); |
63 | 0 | } |
64 | | |
65 | | MRB_API mrb_sym |
66 | | mrb_obj_to_sym(mrb_state *mrb, mrb_value name) |
67 | 19.5k | { |
68 | 19.5k | if (mrb_symbol_p(name)) return mrb_symbol(name); |
69 | 0 | if (mrb_string_p(name)) return mrb_intern_str(mrb, name); |
70 | 0 | mrb_raisef(mrb, E_TYPE_ERROR, "%!v is not a symbol nor a string", name); |
71 | 0 | return 0; /* not reached */ |
72 | 0 | } |
73 | | |
74 | | #if !defined(MRB_NO_FLOAT) && !defined(MRB_NAN_BOXING) |
75 | | static mrb_int |
76 | | mrb_float_id(mrb_float f) |
77 | 0 | { |
78 | | /* normalize -0.0 to 0.0 */ |
79 | 0 | if (f == 0) f = 0.0; |
80 | 0 | return (mrb_int)mrb_byte_hash((uint8_t*)&f, sizeof(f)); |
81 | 0 | } |
82 | | #endif |
83 | | |
84 | | MRB_API mrb_int |
85 | | mrb_obj_id(mrb_value obj) |
86 | 0 | { |
87 | | #if defined(MRB_NAN_BOXING) |
88 | | #ifdef MRB_INT64 |
89 | | return obj.u; |
90 | | #else |
91 | | uint64_t u = obj.u; |
92 | | return (mrb_int)(u>>32)^u; |
93 | | #endif |
94 | | #elif defined(MRB_WORD_BOXING) |
95 | 0 | if (!mrb_immediate_p(obj)) { |
96 | 0 | if (mrb_integer_p(obj)) return mrb_integer(obj); |
97 | 0 | #ifndef MRB_NO_FLOAT |
98 | 0 | if (mrb_float_p(obj)) { |
99 | 0 | return mrb_float_id(mrb_float(obj)); |
100 | 0 | } |
101 | 0 | #endif |
102 | 0 | } |
103 | 0 | return (mrb_int)obj.w; |
104 | | #else /* MRB_NO_BOXING */ |
105 | | |
106 | | #define MakeID(p,t) (mrb_int)(((intptr_t)(p))^(t)) |
107 | | |
108 | | enum mrb_vtype tt = mrb_type(obj); |
109 | | |
110 | | switch (tt) { |
111 | | case MRB_TT_FREE: |
112 | | case MRB_TT_UNDEF: |
113 | | return MakeID(0, tt); /* should not happen */ |
114 | | case MRB_TT_FALSE: |
115 | | if (mrb_nil_p(obj)) |
116 | | return MakeID(4, tt); |
117 | | else |
118 | | return MakeID(0, tt); |
119 | | case MRB_TT_TRUE: |
120 | | return MakeID(2, tt); |
121 | | case MRB_TT_SYMBOL: |
122 | | return MakeID(mrb_symbol(obj), tt); |
123 | | case MRB_TT_INTEGER: |
124 | | return MakeID(mrb_integer(obj), tt); |
125 | | #ifndef MRB_NO_FLOAT |
126 | | case MRB_TT_FLOAT: |
127 | | return MakeID(mrb_float_id(mrb_float(obj)), tt); |
128 | | #endif |
129 | | case MRB_TT_STRING: |
130 | | case MRB_TT_OBJECT: |
131 | | case MRB_TT_CLASS: |
132 | | case MRB_TT_MODULE: |
133 | | case MRB_TT_ICLASS: |
134 | | case MRB_TT_SCLASS: |
135 | | case MRB_TT_PROC: |
136 | | case MRB_TT_ARRAY: |
137 | | case MRB_TT_HASH: |
138 | | case MRB_TT_RANGE: |
139 | | case MRB_TT_EXCEPTION: |
140 | | case MRB_TT_CDATA: |
141 | | case MRB_TT_ISTRUCT: |
142 | | default: |
143 | | return MakeID(mrb_ptr(obj), tt); |
144 | | } |
145 | | #endif |
146 | 0 | } |
147 | | |
148 | | #ifdef MRB_WORD_BOXING |
149 | | #ifndef MRB_NO_FLOAT |
150 | | MRB_API mrb_value |
151 | | mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f) |
152 | 18.5k | { |
153 | 18.5k | union mrb_value_ v; |
154 | | |
155 | | #ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE |
156 | | v.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class); |
157 | | v.fp->f = f; |
158 | | MRB_SET_FROZEN_FLAG(v.bp); |
159 | | #elif defined(MRB_64BIT) && defined(MRB_USE_FLOAT32) |
160 | | v.w = 0; |
161 | | v.f = f; |
162 | | v.w = (v.w<<2) | 2; |
163 | | #else |
164 | 18.5k | v.f = f; |
165 | 18.5k | v.w = (v.w & ~3) | 2; |
166 | 18.5k | #endif |
167 | 18.5k | return v.value; |
168 | 18.5k | } |
169 | | |
170 | | |
171 | | #ifndef MRB_WORDBOX_NO_FLOAT_TRUNCATE |
172 | | MRB_API mrb_float |
173 | | mrb_word_boxing_value_float(mrb_value v) |
174 | 18.2k | { |
175 | 18.2k | union mrb_value_ u; |
176 | 18.2k | u.value = v; |
177 | | #if defined(MRB_64BIT) && defined(MRB_USE_FLOAT32) |
178 | | u.w >>= 2; |
179 | | #else |
180 | 18.2k | u.w &= ~3; |
181 | 18.2k | #endif |
182 | 18.2k | return u.f; |
183 | 18.2k | } |
184 | | #endif |
185 | | #endif /* MRB_NO_FLOAT */ |
186 | | |
187 | | MRB_API mrb_value |
188 | | mrb_word_boxing_cptr_value(mrb_state *mrb, void *p) |
189 | 0 | { |
190 | 0 | mrb_value v; |
191 | 0 | struct RCptr *cptr = MRB_OBJ_ALLOC(mrb, MRB_TT_CPTR, mrb->object_class); |
192 | |
|
193 | 0 | SET_OBJ_VALUE(v, cptr); |
194 | 0 | cptr->p = p; |
195 | 0 | return v; |
196 | 0 | } |
197 | | #endif /* MRB_WORD_BOXING */ |
198 | | |
199 | | #if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_INT64)) |
200 | | MRB_API mrb_value |
201 | | mrb_boxing_int_value(mrb_state *mrb, mrb_int n) |
202 | 191k | { |
203 | 191k | if (FIXABLE(n)) return mrb_fixnum_value(n); |
204 | 3.32k | else { |
205 | 3.32k | mrb_value v; |
206 | 3.32k | struct RInteger *p; |
207 | | |
208 | 3.32k | p = (struct RInteger*)mrb_obj_alloc(mrb, MRB_TT_INTEGER, mrb->integer_class); |
209 | 3.32k | p->i = n; |
210 | 3.32k | MRB_SET_FROZEN_FLAG((struct RBasic*)p); |
211 | 3.32k | SET_OBJ_VALUE(v, p); |
212 | 3.32k | return v; |
213 | 3.32k | } |
214 | 191k | } |
215 | | #endif |
216 | | |
217 | | #if defined _MSC_VER && _MSC_VER < 1900 |
218 | | |
219 | | #ifndef va_copy |
220 | | static void |
221 | | mrb_msvc_va_copy(va_list *dest, va_list src) |
222 | | { |
223 | | *dest = src; |
224 | | } |
225 | | #define va_copy(dest, src) mrb_msvc_va_copy(&(dest), src) |
226 | | #endif |
227 | | |
228 | | MRB_API int |
229 | | mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list arg) |
230 | | { |
231 | | int cnt; |
232 | | va_list argcp; |
233 | | va_copy(argcp, arg); |
234 | | if (n == 0 || (cnt = _vsnprintf_s(s, n, _TRUNCATE, format, argcp)) < 0) { |
235 | | cnt = _vscprintf(format, arg); |
236 | | } |
237 | | va_end(argcp); |
238 | | return cnt; |
239 | | } |
240 | | |
241 | | MRB_API int |
242 | | mrb_msvc_snprintf(char *s, size_t n, const char *format, ...) |
243 | | { |
244 | | va_list arg; |
245 | | int ret; |
246 | | va_start(arg, format); |
247 | | ret = mrb_msvc_vsnprintf(s, n, format, arg); |
248 | | va_end(arg); |
249 | | return ret; |
250 | | } |
251 | | |
252 | | #endif /* defined _MSC_VER && _MSC_VER < 1900 */ |