mruby/c VM Source Code release 3.4
Loading...
Searching...
No Matches
symbol.c
Go to the documentation of this file.
1
13
14/***** Feature test switches ************************************************/
15/***** System headers *******************************************************/
16//@cond
17#include "vm_config.h"
18#include <stdint.h>
19#include <string.h>
20#include <limits.h>
21#include <assert.h>
22//@endcond
23
24/***** Local headers ********************************************************/
25#define MRBC_DEFINE_SYMBOL_TABLE
26#include "_autogen_builtin_symbol.h"
27#undef MRBC_DEFINE_SYMBOL_TABLE
28#include "mrubyc.h"
29
30/***** Constant values ******************************************************/
31#if !defined(MRBC_SYMBOL_SEARCH_LINEAR) && !defined(MRBC_SYMBOL_SEARCH_BTREE)
32#define MRBC_SYMBOL_SEARCH_BTREE
33#endif
34
35#if MAX_SYMBOLS_COUNT <= UCHAR_MAX
36#define MRBC_SYMBOL_TABLE_INDEX_TYPE uint8_t
37#else
38#define MRBC_SYMBOL_TABLE_INDEX_TYPE uint16_t
39#endif
40
41#define OFFSET_BUILTIN_SYMBOL 256
42
43
44/***** Macros ***************************************************************/
45/***** Typedefs *************************************************************/
46struct SYM_INDEX {
47 uint16_t hash;
48#ifdef MRBC_SYMBOL_SEARCH_BTREE
51#endif
52 const char *cstr;
53};
54
55
56/***** Function prototypes **************************************************/
57/***** Local variables ******************************************************/
59static int sym_index_pos; // point to the last(free) sym_index array.
60
61
62/***** Global variables *****************************************************/
63/***** Signal catching functions ********************************************/
64/***** Local functions ******************************************************/
65
66//================================================================
72static inline uint16_t calc_hash(const char *str)
73{
74 uint16_t h = 0;
75
76 while( *str != '\0' ) {
77 h = h * 17 + *str++;
78 }
79 return h;
80}
81
82
83//================================================================
89static int search_builtin_symbol( const char *str )
90{
91 int left = 0;
92 int right = sizeof(builtin_symbols) / sizeof(builtin_symbols[0]);
93
94 while( left < right ) {
95 int mid = (left + right) / 2;
96 const unsigned char *p1 = (const unsigned char *)builtin_symbols[mid];
97 const unsigned char *p2 = (const unsigned char *)str;
98
99 while( 1 ) { // string compare, same order as cruby.
100 if( *p1 < *p2 ) {
101 left = mid + 1;
102 break;
103 }
104 if( *p1 > *p2 ) {
105 right = mid;
106 break;
107 }
108 if( *p1 == 0 ) {
109 return mid;
110 }
111
112 p1++;
113 p2++;
114 }
115 }
116
117 return -1;
118}
119
120
121//================================================================
128static int search_index( uint16_t hash, const char *str )
129{
130#ifdef MRBC_SYMBOL_SEARCH_LINEAR
131 for( int i = 0; i < sym_index_pos; i++ ) {
132 if( sym_index[i].hash == hash && strcmp(str, sym_index[i].cstr) == 0 ) {
133 return i;
134 }
135 }
136 return -1;
137#endif
138
139#ifdef MRBC_SYMBOL_SEARCH_BTREE
140 int i = 0;
141 do {
142 if( sym_index[i].hash == hash && strcmp(str, sym_index[i].cstr) == 0 ) {
143 return i;
144 }
145 if( hash < sym_index[i].hash ) {
146 i = sym_index[i].left;
147 } else {
148 i = sym_index[i].right;
149 }
150 } while( i != 0 );
151 return -1;
152#endif
153}
154
155
156//================================================================
163static int add_index( uint16_t hash, const char *str )
164{
165 if( sym_index_pos >= MAX_SYMBOLS_COUNT ) return -1; // check overflow.
166
167 int idx = sym_index_pos++;
168
169 // append table.
170 sym_index[idx].hash = hash;
171 sym_index[idx].cstr = str;
172
173#ifdef MRBC_SYMBOL_SEARCH_BTREE
174 int i = 0;
175
176 while( 1 ) {
177 if( hash < sym_index[i].hash ) {
178 // left side
179 if( sym_index[i].left == 0 ) { // left is empty?
180 sym_index[i].left = idx;
181 break;
182 }
183 i = sym_index[i].left;
184 } else {
185 // right side
186 if( sym_index[i].right == 0 ) { // right is empty?
187 sym_index[i].right = idx;
188 break;
189 }
190 i = sym_index[i].right;
191 }
192 }
193#endif
194
195 return idx;
196}
197
198
199/***** Global functions *****************************************************/
200
201//================================================================
205{
206 memset(sym_index, 0, sizeof(sym_index));
207 sym_index_pos = 0;
208}
209
210
211//================================================================
218{
219 mrbc_sym sym_id = search_builtin_symbol(str);
220 if( sym_id >= 0 ) return sym_id;
221
222 uint16_t h = calc_hash(str);
223 sym_id = search_index(h, str);
224 if( sym_id < 0 ) sym_id = add_index( h, str );
225 if( sym_id < 0 ) return sym_id;
226
227 return sym_id + OFFSET_BUILTIN_SYMBOL;
228}
229
230
231//================================================================
238const char * mrbc_symid_to_str(mrbc_sym sym_id)
239{
240 if( sym_id < OFFSET_BUILTIN_SYMBOL ) {
241 return builtin_symbols[sym_id];
242 }
243
244 sym_id -= OFFSET_BUILTIN_SYMBOL;
245 if( sym_id < 0 ) return NULL;
246 if( sym_id >= sym_index_pos ) return NULL;
247
248 return sym_index[sym_id].cstr;
249}
250
251
252//================================================================
258mrbc_sym mrbc_search_symid( const char *str )
259{
260 mrbc_sym sym_id = search_builtin_symbol(str);
261 if( sym_id >= 0 ) return sym_id;
262
263 uint16_t h = calc_hash(str);
264 sym_id = search_index(h, str);
265 if( sym_id < 0 ) return sym_id;
266
267 return sym_id + OFFSET_BUILTIN_SYMBOL;
268}
269
270
271//================================================================
278void make_nested_symbol_s( char *buf, mrbc_sym id1, mrbc_sym id2 )
279{
280 static const int w = sizeof(mrbc_sym) * 2;
281 char *p = buf + w * 2;
282 *p = 0;
283
284 int i;
285 for( i = w; i > 0; i-- ) {
286 *--p = '0' + (id2 & 0x0f);
287 id2 >>= 4;
288 }
289
290 for( i = w; i > 0; i-- ) {
291 *--p = '0' + (id1 & 0x0f);
292 id1 >>= 4;
293 }
294}
295
296
297//================================================================
306{
307 static const int w = sizeof(mrbc_sym) * 2;
308 const char *s = mrbc_symid_to_str(sym_id);
309
310 assert( mrbc_is_nested_symid( sym_id ));
311 assert( strlen(s) == w*2 );
312
313 *id1 = 0;
314 int i = 0;
315 while( i < w ) {
316 *id1 = (*id1 << 4) + (s[i++] - '0');
317 }
318
319 if( id2 == NULL ) return;
320 *id2 = 0;
321 while( i < w*2 ) {
322 *id2 = (*id2 << 4) + (s[i++] - '0');
323 }
324}
325
326
327//================================================================
334mrbc_value mrbc_symbol_new(struct VM *vm, const char *str)
335{
336 mrbc_sym sym_id = mrbc_search_symid( str );
337 if( sym_id >= 0 ) goto DONE;
338
339 // create symbol object dynamically.
340 int size = strlen(str) + 1;
341 char *buf = mrbc_raw_alloc_no_free(size);
342 if( buf == NULL ) return mrbc_nil_value(); // ENOMEM raise?
343
344 memcpy(buf, str, size);
345 sym_id = add_index( calc_hash(buf), buf );
346 if( sym_id < 0 ) {
347 mrbc_raisef(vm, MRBC_CLASS(Exception),
348 "Overflow MAX_SYMBOLS_COUNT for '%s'", str );
349 return mrbc_nil_value();
350 }
351
352 sym_id += OFFSET_BUILTIN_SYMBOL;
353
354 DONE:
355 return mrbc_symbol_value( sym_id );
356}
357
358
359/***** mruby/c methods ******************************************************/
360
361//================================================================
364static void c_symbol_all_symbols(struct VM *vm, mrbc_value v[], int argc)
365{
367
368 for( int i = 0; i < sizeof(builtin_symbols) / sizeof(builtin_symbols[0]); i++ ) {
370 }
371
372 for( int i = 0; i < sym_index_pos; i++ ) {
374 }
375 SET_RETURN(ret);
376}
377
378
379#if MRBC_USE_STRING
380//================================================================
383static void c_symbol_inspect(struct VM *vm, mrbc_value v[], int argc)
384{
385 const char *s = mrbc_symid_to_str( mrbc_symbol(v[0]) );
386 v[0] = mrbc_string_new_cstr(vm, ":");
387 mrbc_string_append_cstr(&v[0], s);
388}
389
390
391//================================================================
394static void c_symbol_to_s(struct VM *vm, mrbc_value v[], int argc)
395{
396 if( v[0].tt == MRBC_TT_CLASS ) {
397 v[0] = mrbc_string_new_cstr(vm, mrbc_symid_to_str( v[0].cls->sym_id ));
398 return;
399 }
400
402}
403#endif
404
405
406/* MRBC_AUTOGEN_METHOD_TABLE
407
408 CLASS("Symbol")
409 FILE("_autogen_class_symbol.h")
410
411 METHOD( "all_symbols", c_symbol_all_symbols )
412#if MRBC_USE_STRING
413 METHOD( "inspect", c_symbol_inspect )
414 METHOD( "to_s", c_symbol_to_s )
415 METHOD( "id2name", c_symbol_to_s )
416#endif
417 METHOD( "to_sym", c_ineffect )
418*/
419#include "_autogen_class_symbol.h"
420
421
422
423#if defined(MRBC_DEBUG)
424//================================================================
430void mrbc_debug_dump_symbol(void)
431{
432 mrbc_printf("<< Symbol table dump >>\n");
433
434 for( int i = 0; i < sym_index_pos; i++ ) {
435 mrbc_sym sym_id = i + OFFSET_BUILTIN_SYMBOL;
436 mrbc_printf(" %04x: %s", sym_id, sym_index[i].cstr );
437 if( mrbc_is_nested_symid(sym_id) ) {
438 mrbc_printf(" as ");
439 mrbc_print_symbol(sym_id);
440 }
441 mrbc_printf("\n");
442 }
443
444 mrbc_printf("\n");
445}
446
447
448//================================================================
457void mrbc_symbol_statistics( int *total_used )
458{
459 *total_used = sym_index_pos;
460}
461#endif
void * mrbc_raw_alloc_no_free(unsigned int size)
Definition alloc.c:619
int mrbc_array_push(mrbc_value *ary, mrbc_value *set_val)
Definition c_array.c:252
mrbc_value mrbc_array_new(struct VM *vm, int size)
Definition c_array.c:82
static mrbc_value mrbc_string_new_cstr(struct VM *vm, const char *src)
Definition c_string.h:85
static int mrbc_string_append_cstr(mrbc_value *s1, const char *s2)
Definition c_string.h:128
#define MRBC_CLASS(cls)
Definition class.h:51
void mrbc_printf(const char *fstr,...)
Definition console.c:180
void mrbc_print_symbol(mrbc_sym sym_id)
Definition console.c:127
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:173
Include at once the necessary header files.
uint16_t hash
hash value, returned by calc_hash().
Definition symbol.c:47
MRBC_SYMBOL_TABLE_INDEX_TYPE right
Definition symbol.c:50
const char * cstr
point to the symbol string.
Definition symbol.c:52
MRBC_SYMBOL_TABLE_INDEX_TYPE left
Definition symbol.c:49
Virtual Machine.
Definition vm.h:140
mrbc_sym mrbc_search_symid(const char *str)
Definition symbol.c:258
static int sym_index_pos
Definition symbol.c:59
mrbc_value mrbc_symbol_new(struct VM *vm, const char *str)
Definition symbol.c:334
mrbc_sym mrbc_str_to_symid(const char *str)
Definition symbol.c:217
static int search_index(uint16_t hash, const char *str)
Definition symbol.c:128
static int add_index(uint16_t hash, const char *str)
Definition symbol.c:163
void mrbc_separate_nested_symid(mrbc_sym sym_id, mrbc_sym *id1, mrbc_sym *id2)
Definition symbol.c:305
#define MRBC_SYMBOL_TABLE_INDEX_TYPE
Definition symbol.c:36
void mrbc_cleanup_symbol(void)
Definition symbol.c:204
static uint16_t calc_hash(const char *str)
Definition symbol.c:72
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:238
void make_nested_symbol_s(char *buf, mrbc_sym id1, mrbc_sym id2)
Definition symbol.c:278
#define OFFSET_BUILTIN_SYMBOL
Definition symbol.c:41
static struct SYM_INDEX sym_index[MAX_SYMBOLS_COUNT]
Definition symbol.c:58
static int search_builtin_symbol(const char *str)
Definition symbol.c:89
static int mrbc_is_nested_symid(mrbc_sym sym_id)
Definition symbol.h:68
#define mrbc_symbol(o)
Definition value.h:196
#define mrbc_nil_value()
Definition value.h:210
#define mrbc_symbol_value(n)
Definition value.h:214
int16_t mrbc_sym
mruby/c symbol ID
Definition value.h:59
@ MRBC_TT_CLASS
Class.
Definition value.h:87
struct RObject mrbc_value
Definition value.h:174
#define SET_RETURN(n)
Definition value.h:261
Global configuration of mruby/c VM's.
#define MAX_SYMBOLS_COUNT
Definition vm_config.h:28