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 
12 MRB_API struct RData*
mrb_data_object_alloc(mrb_state * mrb,struct RClass * klass,void * ptr,const mrb_data_type * type)13 mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const mrb_data_type *type)
14 {
15   struct RData *data;
16 
17   data = (struct RData*)mrb_obj_alloc(mrb, MRB_TT_DATA, klass);
18   data->data = ptr;
19   data->type = type;
20 
21   return data;
22 }
23 
24 MRB_API void
mrb_data_check_type(mrb_state * mrb,mrb_value obj,const mrb_data_type * type)25 mrb_data_check_type(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
26 {
27   if (!mrb_data_p(obj)) {
28     mrb_check_type(mrb, obj, MRB_TT_DATA);
29   }
30   if (DATA_TYPE(obj) != type) {
31     const mrb_data_type *t2 = DATA_TYPE(obj);
32 
33     if (t2) {
34       mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %s (expected %s)",
35                  t2->struct_name, type->struct_name);
36     }
37     else {
38       mrb_raisef(mrb, E_TYPE_ERROR, "uninitialized %t (expected %s)",
39                  obj, type->struct_name);
40     }
41   }
42 }
43 
44 MRB_API void*
mrb_data_check_get_ptr(mrb_state * mrb,mrb_value obj,const mrb_data_type * type)45 mrb_data_check_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
46 {
47   if (!mrb_data_p(obj)) {
48     return NULL;
49   }
50   if (DATA_TYPE(obj) != type) {
51     return NULL;
52   }
53   return DATA_PTR(obj);
54 }
55 
56 MRB_API void*
mrb_data_get_ptr(mrb_state * mrb,mrb_value obj,const mrb_data_type * type)57 mrb_data_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
58 {
59   mrb_data_check_type(mrb, obj, type);
60   return DATA_PTR(obj);
61 }
62 
63 MRB_API mrb_sym
mrb_obj_to_sym(mrb_state * mrb,mrb_value name)64 mrb_obj_to_sym(mrb_state *mrb, mrb_value name)
65 {
66   if (mrb_symbol_p(name)) return mrb_symbol(name);
67   if (mrb_string_p(name)) return mrb_intern_str(mrb, name);
68   mrb_raisef(mrb, E_TYPE_ERROR, "%!v is not a symbol nor a string", name);
69   return 0;  /* not reached */
70 }
71 
72 MRB_API mrb_int
73 #ifdef MRB_WITHOUT_FLOAT
mrb_fixnum_id(mrb_int f)74 mrb_fixnum_id(mrb_int f)
75 #else
76 mrb_float_id(mrb_float f)
77 #endif
78 {
79   const char *p = (const char*)&f;
80   int len = sizeof(f);
81   uint32_t id = 0;
82 
83 #ifndef MRB_WITHOUT_FLOAT
84   /* normalize -0.0 to 0.0 */
85   if (f == 0) f = 0.0;
86 #endif
87   while (len--) {
88     id = id*65599 + *p;
89     p++;
90   }
91   id = id + (id>>5);
92 
93   return (mrb_int)id;
94 }
95 
96 MRB_API mrb_int
mrb_obj_id(mrb_value obj)97 mrb_obj_id(mrb_value obj)
98 {
99   mrb_int tt = mrb_type(obj);
100 
101 #define MakeID2(p,t) (mrb_int)(((intptr_t)(p))^(t))
102 #define MakeID(p)    MakeID2(p,tt)
103 
104   switch (tt) {
105   case MRB_TT_FREE:
106   case MRB_TT_UNDEF:
107     return MakeID(0); /* not define */
108   case MRB_TT_FALSE:
109     if (mrb_nil_p(obj))
110       return MakeID(1);
111     return MakeID(0);
112   case MRB_TT_TRUE:
113     return MakeID(1);
114   case MRB_TT_SYMBOL:
115     return MakeID(mrb_symbol(obj));
116   case MRB_TT_FIXNUM:
117 #ifdef MRB_WITHOUT_FLOAT
118     return MakeID(mrb_fixnum_id(mrb_fixnum(obj)));
119 #else
120     return MakeID2(mrb_float_id((mrb_float)mrb_fixnum(obj)), MRB_TT_FLOAT);
121   case MRB_TT_FLOAT:
122     return MakeID(mrb_float_id(mrb_float(obj)));
123 #endif
124   case MRB_TT_STRING:
125   case MRB_TT_OBJECT:
126   case MRB_TT_CLASS:
127   case MRB_TT_MODULE:
128   case MRB_TT_ICLASS:
129   case MRB_TT_SCLASS:
130   case MRB_TT_PROC:
131   case MRB_TT_ARRAY:
132   case MRB_TT_HASH:
133   case MRB_TT_RANGE:
134   case MRB_TT_EXCEPTION:
135   case MRB_TT_DATA:
136   case MRB_TT_ISTRUCT:
137   default:
138     return MakeID(mrb_ptr(obj));
139   }
140 }
141 
142 #if defined(MRB_NAN_BOXING) && defined(MRB_64BIT)
143 #define mrb_xxx_boxing_cptr_value mrb_nan_boxing_cptr_value
144 #endif
145 
146 #ifdef MRB_WORD_BOXING
147 #define mrb_xxx_boxing_cptr_value mrb_word_boxing_cptr_value
148 
149 #ifndef MRB_WITHOUT_FLOAT
150 MRB_API mrb_value
mrb_word_boxing_float_value(mrb_state * mrb,mrb_float f)151 mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f)
152 {
153   mrb_value v;
154 
155   v.value.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class);
156   v.value.fp->f = f;
157   MRB_SET_FROZEN_FLAG(v.value.bp);
158   return v;
159 }
160 
161 MRB_API mrb_value
mrb_word_boxing_float_pool(mrb_state * mrb,mrb_float f)162 mrb_word_boxing_float_pool(mrb_state *mrb, mrb_float f)
163 {
164   struct RFloat *nf = (struct RFloat *)mrb_malloc(mrb, sizeof(struct RFloat));
165   nf->tt = MRB_TT_FLOAT;
166   nf->c = mrb->float_class;
167   nf->f = f;
168   MRB_SET_FROZEN_FLAG(nf);
169   return mrb_obj_value(nf);
170 }
171 #endif  /* MRB_WITHOUT_FLOAT */
172 #endif  /* MRB_WORD_BOXING */
173 
174 #if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_64BIT))
175 MRB_API mrb_value
mrb_xxx_boxing_cptr_value(mrb_state * mrb,void * p)176 mrb_xxx_boxing_cptr_value(mrb_state *mrb, void *p)
177 {
178   mrb_value v;
179   struct RCptr *cptr = (struct RCptr*)mrb_obj_alloc(mrb, MRB_TT_CPTR, mrb->object_class);
180 
181   SET_OBJ_VALUE(v, cptr);
182   cptr->p = p;
183   return v;
184 }
185 #endif
186 
187 #if defined _MSC_VER && _MSC_VER < 1900
188 
189 #ifndef va_copy
190 static void
mrb_msvc_va_copy(va_list * dest,va_list src)191 mrb_msvc_va_copy(va_list *dest, va_list src)
192 {
193   *dest = src;
194 }
195 #define va_copy(dest, src) mrb_msvc_va_copy(&(dest), src)
196 #endif
197 
198 MRB_API int
mrb_msvc_vsnprintf(char * s,size_t n,const char * format,va_list arg)199 mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list arg)
200 {
201   int cnt;
202   va_list argcp;
203   va_copy(argcp, arg);
204   if (n == 0 || (cnt = _vsnprintf_s(s, n, _TRUNCATE, format, argcp)) < 0) {
205     cnt = _vscprintf(format, arg);
206   }
207   va_end(argcp);
208   return cnt;
209 }
210 
211 MRB_API int
mrb_msvc_snprintf(char * s,size_t n,const char * format,...)212 mrb_msvc_snprintf(char *s, size_t n, const char *format, ...)
213 {
214   va_list arg;
215   int ret;
216   va_start(arg, format);
217   ret = mrb_msvc_vsnprintf(s, n, format, arg);
218   va_end(arg);
219   return ret;
220 }
221 
222 #endif  /* defined _MSC_VER && _MSC_VER < 1900 */
223