bool rubyval_to_std_vector_string(mrb_state* mrb, mrb_value arg, std::vector<std::string>* ret, const char* funcName) { if (! mrb_array_p(arg)) { return false; } mrb_int len = mrb_ary_len(mrb, arg); for (mrb_int i = 0; i < len; i++) { mrb_value v = mrb_ary_ref(mrb, arg, i); std::string str = ""; if (mrb_fixnum_p(v)) { mrb_int val = mrb_fixnum(v); char *cstr = nullptr; sprintf(cstr, "%d", val); str = std::string(cstr); } else if (mrb_float_p(v)) { mrb_float val = mrb_float(v); char *cstr = nullptr; sprintf(cstr, "%f", val); str = std::string(cstr); } ret->push_back(str); } return true; }
static mrb_value mrb_sdl2_video_surface_fill_rects(mrb_state *mrb, mrb_value self) { uint32_t color; mrb_value rects; mrb_get_args(mrb, "io", &color, &rects); if (!mrb_array_p(rects)) { mrb_raise(mrb, E_TYPE_ERROR, "given 2nd argument is unexpected type (expected Array)."); } mrb_int const n = mrb_ary_len(mrb, rects); SDL_Surface *s = mrb_sdl2_video_surface_get_ptr(mrb, self); SDL_Rect r[n]; mrb_int i; for (i = 0; i < n; ++i) { SDL_Rect const * const ptr = mrb_sdl2_rect_get_ptr(mrb, mrb_ary_ref(mrb, rects, i)); if (NULL != ptr) { r[i] = *ptr; } else { r[i] = (SDL_Rect) { 0, 0, 0, 0 }; } } if (0 != SDL_FillRects(s, r, n, color)) { mruby_sdl2_raise_error(mrb); } return self; }
bool rubyval_to_ccvaluemapintkey(mrb_state* mrb, mrb_value arg, cocos2d::ValueMapIntKey* ret, const char* funcName) { if (! mrb_hash_p(arg)) { return false; } mrb_value key_arr = mrb_hash_keys(mrb, arg); mrb_int len = mrb_ary_len(mrb, key_arr); ValueMapIntKey& dict = *ret; for (mrb_int i = 0; i < len; i++) { mrb_value hk = mrb_ary_ref(mrb, key_arr, i); mrb_value hv = mrb_hash_get(mrb, arg, hk); int int_key = 0; if (mrb_string_p(hk)) { char *kstr = mrb_str_to_cstr(mrb, hk); int_key = atoi(kstr); } else if (mrb_symbol_p(hk)) { mrb_sym sym = mrb_symbol(hk); const char* kstr = mrb_sym2name(mrb, sym); int_key = atoi(kstr); } else { return false; } Value val; if (! rubyval_to_ccvalue(mrb, hv, &val)) { return false; } dict[int_key] = val; } return true; }
bool rubyval_to_dictionary(mrb_state* mrb, mrb_value arg, __Dictionary** outValue, const char* funcName) { if (! mrb_hash_p(arg)) { return false; } mrb_value key_arr = mrb_hash_keys(mrb, arg); mrb_int len = mrb_ary_len(mrb, key_arr); __Dictionary* dic = __Dictionary::create(); for (mrb_int i = 0; i < len; i++) { mrb_value hk = mrb_ary_ref(mrb, key_arr, i); mrb_value hv = mrb_hash_get(mrb, arg, hk); if (mrb_string_p(hk)) { char *kstr = mrb_str_to_cstr(mrb, hk); Ref* ref = to_ref_value(mrb, hv); dic->setObject(ref, std::string(kstr)); } else if (mrb_symbol_p(hk)) { mrb_sym sym = mrb_symbol(hk); const char* kstr = mrb_sym2name(mrb, sym); Ref* ref = to_ref_value(mrb, hv); dic->setObject(ref, std::string(kstr)); } else { CCASSERT(false, "not supported key value type"); } } *outValue = dic; return true; }
mrb_value ruby_global_require(mrb_state* mrb, mrb_value self) { const char* filename_cstr = nullptr; mrb_get_args(mrb, "z", &filename_cstr); std::string filename(filename_cstr); auto engine = cocos2d::RubyEngine::getInstance(); std::string realfile = engine->findFile(filename); mrb_value loaded_path_arr = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$LOADED_FEATURES")); if (mrb_array_p(loaded_path_arr)) { mrb_int len = mrb_ary_len(mrb, loaded_path_arr); for (mrb_int i = 0; i < len; i++) { mrb_value path = mrb_ary_ref(mrb, loaded_path_arr, i); const char* path_cstr = mrb_str_to_cstr(mrb, path); if (realfile.compare(path_cstr) == 0) { return mrb_nil_value(); } } } if (! mrb_array_p(loaded_path_arr)) { loaded_path_arr = mrb_ary_new(mrb); mrb_value path = mrb_str_new_cstr(mrb, realfile.c_str()); mrb_ary_push(mrb, loaded_path_arr, path); mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$LOADED_FEATURES"), loaded_path_arr); } else { mrb_value path = mrb_str_new_cstr(mrb, realfile.c_str()); mrb_ary_push(mrb, loaded_path_arr, path); } engine->executeScriptFile(realfile.c_str()); return mrb_nil_value(); }
bool rubyval_to_array(mrb_state* mrb, mrb_value arg, __Array** outValue, const char* funcName) { if (! mrb_array_p(arg)) { return false; } mrb_int len = mrb_ary_len(mrb, arg); __Array* arr = __Array::createWithCapacity(len); for (mrb_int i = 0; i < len; i++) { mrb_value val = mrb_ary_ref(mrb, arg, i); Ref* ref = to_ref_value(mrb, val); arr->addObject(ref); } *outValue = arr; return true; }
bool rubyval_to_ccvaluevector(mrb_state* mrb, mrb_value arg, cocos2d::ValueVector* ret, const char* funcName) { if (! mrb_array_p(arg)) { return false; } mrb_int len = mrb_ary_len(mrb, arg); for (mrb_int i = 0; i < len; i++) { mrb_value v = mrb_ary_ref(mrb, arg, i); Value val; if (! rubyval_to_ccvalue(mrb, v, &val)) { return false; } ret->push_back(val); } return true; }
bool rubyval_to_carray_float(mrb_state* mrb, mrb_value arg, float** outValue, const char* funcName) { if (! mrb_array_p(arg)) { return false; } mrb_int len = mrb_ary_len(mrb, arg); float arr[len]; for (mrb_int i = 0; i < len; i++) { mrb_value val = mrb_ary_ref(mrb, arg, i); if (! mrb_float_p(val)) { return false; } arr[i] = mrb_float(val); } *outValue = arr; return true; }
int main(int argc, char const *argv[]) { #ifdef _MEM_PROFILER uint8_t checkpoint_set = 0; #endif fd_set rfds; char buffer[PIPE_BUFFER_SIZE]; int i, n; Plugin plugins[MAX_PLUGINS]; int plugins_count = 0; mrb_state *mrb; mrb_value r_output, r_plugins_list; mrb_sym output_gv_sym, plugins_to_load_gv_sym; printf("Version: %s\n", PROBE_VERSION); if( argc != 2 ){ printf("Usage: %s <config_path>\n", argv[0]); exit(1); } #ifdef _MEM_PROFILER init_profiler(); #endif config_path = argv[1]; printf("Initializing core...\n"); mrb = mrb_open_allocf(profiler_allocf, "main"); output_gv_sym = mrb_intern_cstr(mrb, "$output"); plugins_to_load_gv_sym = mrb_intern_cstr(mrb, "$plugins_to_load"); setup_api(mrb); execute_file(mrb, "plugins/main.rb"); execute_file(mrb, config_path); printf("Loading plugins...\n"); r_plugins_list = mrb_gv_get(mrb, plugins_to_load_gv_sym); for(i = 0; i< mrb_ary_len(mrb, r_plugins_list); i++){ char *path, tmp[100]; int ssize; mrb_value r_plugin_name = mrb_ary_ref(mrb, r_plugins_list, i); const char *plugin_name = mrb_string_value_cstr(mrb, &r_plugin_name); snprintf(tmp, sizeof(tmp) - 1, "plugins/%s.rb", plugin_name); ssize = strlen(tmp); path = malloc(ssize + 1); strncpy(path, tmp, ssize); path[ssize] = '\0'; if( access(path, F_OK) == -1 ){ printf("cannot open plugin file \"%s\": %s\n", path, strerror(errno)); exit(1); } init_plugin_from_file(&plugins[plugins_count], path, plugin_name); plugins_count++; } printf("Instanciating output class...\n"); r_output = mrb_gv_get(mrb, output_gv_sym); interval = mrb_fixnum(mrb_funcall(mrb, r_output, "interval", 0)); printf("Interval set to %dms\n", (int)interval); printf("Sending initial report...\n"); mrb_funcall(mrb, r_output, "send_report", 0); if (mrb->exc) { mrb_print_error(mrb); exit(1); } // start all the threads for(i= 0; i< plugins_count; i++){ // printf("== plugin %d\n", i); n = pthread_create(&plugins[i].thread, NULL, plugin_thread, (void *)&plugins[i]); if( n < 0 ){ fprintf(stderr, "create failed\n"); } } if( signal(SIGINT, clean_exit) == SIG_ERR){ perror("signal"); exit(1); } while(running){ int fds[MAX_PLUGINS]; int maxfd = 0, ai; struct timeval tv; mrb_value r_buffer; struct timeval cycle_started_at, cycle_completed_at; gettimeofday(&cycle_started_at, NULL); bzero(fds, sizeof(int) * MAX_PLUGINS); // ask every plugin to send their data for(i= 0; i< plugins_count; i++){ strcpy(buffer, "request"); if( send(plugins[i].host_pipe, buffer, strlen(buffer), 0) == -1 ){ printf("send error when writing in pipe connected to plugin '%s'\n", plugins[i].name); } fds[i] = plugins[i].host_pipe; // printf("sent request to %d\n", i); } // printf("waiting answers...\n"); // and now wait for each answer while(1){ int left = 0; FD_ZERO(&rfds); for(i = 0; i< MAX_PLUGINS; i++){ if( fds[i] != NOPLUGIN_VALUE ){ FD_SET(fds[i], &rfds); left++; if( fds[i] > maxfd ) maxfd = fds[i]; } } // printf("left: %d %d\n", left, left <= 0); if( !running || (0 == left) ) break; // substract 20ms to stay below the loop delay fill_timeout(&tv, cycle_started_at, interval - 20); // printf("before select\n"); n = select(maxfd + 1, &rfds, NULL, NULL, &tv); // printf("after select: %d\n", n); if( n > 0 ){ // find out which pipes have data for(i = 0; i< MAX_PLUGINS; i++){ if( (fds[i] != NOPLUGIN_VALUE) && FD_ISSET(fds[i], &rfds) ){ while (1){ struct timeval answered_at; n = read(fds[i], buffer, sizeof(buffer)); if( n == -1 ){ if( errno != EAGAIN ) perror("read"); break; } if( n == PIPE_BUFFER_SIZE ){ printf("PIPE_BUFFER_SIZE is too small, increase it ! (value: %d)\n", PIPE_BUFFER_SIZE); continue; } gettimeofday(&answered_at, NULL); // printf("received answer from %s in %u ms\n", (const char *) plugins[i].mrb->ud, // (uint32_t)((answered_at.tv_sec - cycle_started_at.tv_sec) * 1000 + // (answered_at.tv_usec - cycle_started_at.tv_usec) / 1000) // ); buffer[n] = 0x00; ai = mrb_gc_arena_save(mrb); r_buffer = mrb_str_buf_new(mrb, n); mrb_str_buf_cat(mrb, r_buffer, buffer, n); // mrb_funcall(mrb, r_output, "tick", 0); mrb_funcall(mrb, r_output, "add", 1, r_buffer); check_exception("add", mrb); // pp(mrb, r_output, 0); mrb_gc_arena_restore(mrb, ai); } fds[i] = 0; } } } else if( n == 0 ) { printf("no responses received from %d plugins.\n", left); break; // timeout } else { perror("select"); } } int idx = mrb_gc_arena_save(mrb); mrb_funcall(mrb, r_output, "flush", 0); check_exception("flush", mrb); mrb_gc_arena_restore(mrb, idx); // and now sleep until the next cycle gettimeofday(&cycle_completed_at, NULL); #ifdef _MEM_PROFILER if( checkpoint_set ){ print_allocations(); } #endif // force a gc run at the end of each cycle mrb_full_gc(mrb); // printf("[main] capa: %d / %d\n", mrb->arena_idx, mrb->arena_capa); // for(i= 0; i< plugins_count; i++){ // printf("[%s] capa: %d / %d\n", plugins[i].name, plugins[i].mrb->arena_idx, plugins[i].mrb->arena_capa); // } #ifdef _MEM_PROFILER checkpoint_set = 1; // and set starting point profiler_set_checkpoint(); #endif #ifdef _MEM_PROFILER_RUBY // dump VMS state dump_state(mrb); for(i= 0; i< plugins_count; i++){ dump_state(plugins[i].mrb); } #endif fflush(stdout); sleep_delay(&cycle_started_at, &cycle_completed_at, interval); } printf("Sending exit signal to all plugins...\n"); strcpy(buffer, "exit"); for(i= 0; i< plugins_count; i++){ C_CHECK("send", send(plugins[i].host_pipe, buffer, strlen(buffer), 0) ); } printf("Giving some time for threads to exit...\n\n"); really_sleep(2000); for(i= 0; i< plugins_count; i++){ int ret = pthread_kill(plugins[i].thread, 0); // if a success is returned then the thread is still alive // which means the thread did not acknoledged the exit message // kill it. if( ret == 0 ){ printf(" - plugin \"%s\" failed to exit properly, killing it...\n", (const char *) plugins[i].mrb->ud); pthread_cancel(plugins[i].thread); } else { printf(" - plugin \"%s\" exited properly.\n", (const char *) plugins[i].mrb->allocf_ud); } if( pthread_join(plugins[i].thread, NULL) < 0){ fprintf(stderr, "join failed\n"); } mrb_close(plugins[i].mrb); } mrb_close(mrb); printf("Exited !\n"); return 0; }
int value_to_node(mrb_state *mrb, yaml_document_t *document, mrb_value value) { int node; switch (mrb_type(value)) { case MRB_TT_ARRAY: { mrb_int len = mrb_ary_len(mrb, value); mrb_int i; int ai = mrb_gc_arena_save(mrb); node = yaml_document_add_sequence(document, NULL, YAML_ANY_SEQUENCE_STYLE); for (i = 0; i < len; i++) { mrb_value child = mrb_ary_ref(mrb, value, i); int child_node = value_to_node(mrb, document, child); /* Add the child to the sequence */ yaml_document_append_sequence_item(document, node, child_node); mrb_gc_arena_restore(mrb, ai); } break; } case MRB_TT_HASH: { /* Iterating a list of keys is slow, but it only * requires use of the interface defined in `hash.h`. */ mrb_value keys = mrb_hash_keys(mrb, value); mrb_int len = mrb_ary_len(mrb, keys); mrb_int i; int ai = mrb_gc_arena_save(mrb); node = yaml_document_add_mapping(document, NULL, YAML_ANY_MAPPING_STYLE); for (i = 0; i < len; i++) { mrb_value key = mrb_ary_ref(mrb, keys, i); mrb_value child = mrb_hash_get(mrb, value, key); int key_node = value_to_node(mrb, document, key); int child_node = value_to_node(mrb, document, child); /* Add the key/value pair to the mapping */ yaml_document_append_mapping_pair(document, node, key_node, child_node); mrb_gc_arena_restore(mrb, ai); } break; } default: { if (mrb_nil_p(value)) { /* http://yaml.org/type/null.html Canonical form */ value = mrb_str_new_lit(mrb, "~"); } else { /* Equivalent to `obj = obj#to_s` */ value = mrb_obj_as_string(mrb, value); } /* Fallthrough */ } case MRB_TT_STRING: { yaml_scalar_style_t style = YAML_ANY_SCALAR_STYLE; if (RSTRING_LEN(value) == 0) { /* If the String is empty, it may be reloaded as a nil instead of an * empty string, to avoid that place a quoted string instead */ style = YAML_SINGLE_QUOTED_SCALAR_STYLE; } yaml_char_t *value_chars = (unsigned char *) RSTRING_PTR(value); node = yaml_document_add_scalar(document, NULL, value_chars, RSTRING_LEN(value), style); break; } } return node; }
static mrb_value mrb_sdl2_misc_bytebuffer_initialize(mrb_state *mrb, mrb_value self) { mrb_value arg; mrb_get_args(mrb, "o", &arg); mrb_sdl2_misc_buffer_data_t *data = (mrb_sdl2_misc_buffer_data_t*)DATA_PTR(self); if (NULL == data) { data = (mrb_sdl2_misc_buffer_data_t*)mrb_malloc(mrb, sizeof(mrb_sdl2_misc_buffer_data_t)); if (NULL == data) { mrb_raise(mrb, E_RUNTIME_ERROR, "insufficient memory."); } data->buffer = NULL; data->size = 0; } enum mrb_vtype const arg_type = mrb_type(arg); switch (arg_type) { case MRB_TT_FIXNUM: data->size = (size_t)mrb_fixnum(arg); break; case MRB_TT_FLOAT: data->size = (size_t)mrb_float(arg); break; case MRB_TT_STRING: data->size = (size_t)mrb_float(mrb_funcall(mrb, arg, "to_f", 0)); break; case MRB_TT_ARRAY: { mrb_int const n = mrb_ary_len(mrb, arg); if (0 == n) { mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot accept empty array."); } data->size = n * sizeof(uint8_t); } break; default: if (mrb_respond_to(mrb, arg, mrb_intern(mrb, "to_f", 4))) { data->size = (size_t)mrb_float(mrb_funcall(mrb, arg, "to_f", 0)); } else if (mrb_respond_to(mrb, arg, mrb_intern(mrb, "to_i", 4))) { data->size = (size_t)mrb_fixnum(mrb_funcall(mrb, arg, "to_i", 0)); } else { mrb_raise(mrb, E_TYPE_ERROR, "expected Fixnum/Float/String/Array or comvertible type"); } break; } data->buffer = mrb_malloc(mrb, data->size); if (NULL == data->buffer) { mrb_free(mrb, data); mrb_raise(mrb, E_RUNTIME_ERROR, "insufficient memory."); } size_t i = 0; for (i = 0; i < data->size/sizeof(uint8_t); ++i) { ((uint8_t*)data->buffer)[i] = 0; } if (arg_type == MRB_TT_ARRAY) { mrb_int const n = mrb_ary_len(mrb, arg); mrb_int i; for (i = 0; i < n; ++i) { mrb_value const item = mrb_ary_ref(mrb, arg, i); switch (mrb_type(item)) { case MRB_TT_FIXNUM: ((uint8_t*)data->buffer)[i] = (uint8_t)(mrb_fixnum(item) & 0xffu); break; case MRB_TT_FLOAT: ((uint8_t*)data->buffer)[i] = (uint8_t)((uint32_t)mrb_float(item) & 0xffu); break; case MRB_TT_STRING: ((uint8_t*)data->buffer)[i] = (uint8_t)((uint32_t)mrb_float(mrb_funcall(mrb, item, "to_f", 0)) & 0xffu); break; default: if (mrb_respond_to(mrb, item, mrb_intern(mrb, "to_f", 4))) { ((uint8_t*)data->buffer)[i] = (uint8_t)((uint32_t)mrb_float(mrb_funcall(mrb, item, "to_f", 0)) & 0xffu); } else if (mrb_respond_to(mrb, item, mrb_intern(mrb, "to_i", 4))) { ((uint8_t*)data->buffer)[i] = (uint8_t)(mrb_fixnum(mrb_funcall(mrb, item, "to_i", 0)) & 0xffu); } else { mrb_free(mrb, data->buffer); mrb_free(mrb, data); mrb_raise(mrb, E_TYPE_ERROR, "expected Fixnum/Float/String or convertible type"); } break; } } } DATA_PTR(self) = data; DATA_TYPE(self) = &mrb_sdl2_misc_buffer_data_type; return self; }