void Environment::load_argv(int argc, char** argv) { String* str = 0; Encoding* enc = Encoding::default_external(state); Array* os_ary = Array::create(state, argc); for(int i = 0; i < argc; i++) { str = String::create(state, argv[i]); str->encoding(state, enc); os_ary->set(state, i, str); } G(rubinius)->set_const(state, "OS_ARGV", os_ary); char buf[MAXPATHLEN]; str = String::create(state, getcwd(buf, MAXPATHLEN)); str->encoding(state, enc); G(rubinius)->set_const(state, "OS_STARTUP_DIR", str); str = String::create(state, argv[0]); str->encoding(state, enc); state->vm()->set_const("ARG0", str); Array* ary = Array::create(state, argc - 1); int which_arg = 0; bool skip_xflags = true; for(int i=1; i < argc; i++) { char* arg = argv[i]; if(strcmp(arg, "--") == 0) { skip_xflags = false; } else if(strncmp(arg, "-X", 2) == 0) { if(skip_xflags) continue; } else if(arg[1] != '-') { skip_xflags = false; } str = String::create(state, arg); str->taint(state); str->encoding(state, enc); ary->set(state, which_arg++, str); } state->vm()->set_const("ARGV", ary); // Now finish up with the config if(config.print_config > 1) { std::cout << "========= Configuration =========\n"; config.print(true); std::cout << "=================================\n"; } else if(config.print_config) { config.print(); } state->shared().set_use_capi_lock(config.capi_lock); }
String* Time::strftime(STATE, String* format) { struct tm64 tm = get_tm(); struct timespec64 ts; ts.tv_sec = seconds_; ts.tv_nsec = nanoseconds_; int off = 0; if(Fixnum* offset = try_as<Fixnum>(utc_offset(state))) { off = offset->to_int(); } if(format->byte_size() == 0) return String::create(state, NULL, 0); char stack_str[STRFTIME_STACK_BUF]; size_t chars = ::strftime_extended(stack_str, STRFTIME_STACK_BUF, format->c_str(state), &tm, &ts, CBOOL(is_gmt_) ? 1 : 0, off); size_t buf_size = format->byte_size(); String* result = 0; if(chars == 0) { buf_size *= 2; char* malloc_str = (char*)malloc(buf_size); if(!malloc_str) { Exception::memory_error(state); return NULL; } chars = ::strftime_extended(malloc_str, buf_size, format->c_str(state), &tm, &ts, CBOOL(is_gmt_) ? 1 : 0, off); if(chars) { result = String::create(state, malloc_str, chars); result->encoding(state, format->encoding()); } free(malloc_str); } else { result = String::create(state, stack_str, chars); result->encoding(state, format->encoding()); } return result; }
Object* MatchData::nth_capture(STATE, native_int which) { if(region_->num_fields() <= which) return cNil; Tuple* sub = try_as<Tuple>(region_->at(state, which)); if(!sub) return cNil; Fixnum* beg = try_as<Fixnum>(sub->at(state, 0)); Fixnum* fin = try_as<Fixnum>(sub->at(state, 1)); native_int b = beg->to_native(); native_int f = fin->to_native(); native_int max = source_->byte_size(); if(!beg || !fin || f > max || b < 0) { return cNil; } const char* str = (char*)source_->byte_address(); native_int sz = f - b; if(sz > max) sz = max; String* string = String::create(state, str + b, sz); string->encoding(state, source_->encoding()); return string; }
Symbol* UnMarshaller::get_symbol() { char stack_data[STACK_BUF_SZ]; char *malloc_data = NULL; char *data = stack_data; size_t count; Encoding* enc = try_as<Encoding>(unmarshal()); stream >> count; stream.get(); if(count >= STACK_BUF_SZ) { malloc_data = (char*)malloc(count + 1); data = malloc_data; } stream.read(data, count + 1); data[count] = 0; // clamp String* str = String::create(state, data, count); if(enc) str->encoding(state, enc); Symbol* sym = state->symbol(str); if(malloc_data) { free(malloc_data); } return sym; }
String* String::string_dup(STATE) { Module* mod = klass_; Class* cls = try_as_instance<Class>(mod); if(unlikely(!cls)) { while(!cls) { mod = mod->superclass(); if(mod->nil_p()) rubinius::bug("Object::class_object() failed to find a class"); cls = try_as_instance<Class>(mod); } } String* so = state->new_object<String>(cls); so->set_tainted(is_tainted_p()); so->num_bytes(state, num_bytes()); so->encoding(state, encoding()); so->data(state, data()); so->hash_value(state, hash_value()); so->shared(state, Qtrue); shared(state, Qtrue); return so; }
String* Time::locale_string(STATE, const char* data) { String* str = String::create(state, data); Encoding* locale = Encoding::find(state, "locale"); if(!locale->nil_p()) { str->encoding(state, locale); } return str; }
VALUE rb_external_str_new_with_enc(const char* string, long size, rb_encoding* encoding) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); String* str = String::create(env->state(), string, size); str->taint(env->state()); Encoding* enc = Encoding::find(env->state(), encoding->name); if(enc == Encoding::usascii_encoding(env->state()) && !CBOOL(str->ascii_only_p(env->state()))) { str->encoding(env->state(), Encoding::ascii8bit_encoding(env->state())); } else { str->encoding(env->state(), enc); } // TODO: handle transcoding if necessary return env->get_handle(str); }
void test_string_with_encoding() { mar->sstream.str(std::string("s\nE\n10\nASCII-8BIT\n4\nblah\n")); Object* obj = mar->unmarshal(); TS_ASSERT(kind_of<String>(obj)); String *str = as<String>(obj); TS_ASSERT_EQUALS(std::string(str->c_str(state)), "blah"); TS_ASSERT_EQUALS(std::string(str->encoding()->name()->c_str(state)), "ASCII-8BIT"); }
void test_string_no_encoding() { mar->sstream.str(std::string("s\nE\n0\n\n4\nblah\n")); Object* obj = mar->unmarshal(); TS_ASSERT(kind_of<String>(obj)); String *str = as<String>(obj); TS_ASSERT_EQUALS(std::string(str->c_str(state)), "blah"); TS_ASSERT_EQUALS(str->encoding(), Qnil); }
String* Float::to_s_minimal(STATE) { char buffer[FLOAT_TO_S_STRLEN]; int len = double_to_string(buffer, FLOAT_TO_S_STRLEN, val); String* str = String::create(state, buffer, len); infect(state, str); str->encoding(state, Encoding::usascii_encoding(state)); str->ascii_only(state, cTrue); str->valid_encoding(state, cTrue); return str; }
String* String::from_bytearray(STATE, ByteArray* ba, Integer* start, Integer* count) { String* s = state->new_object<String>(G(string)); s->num_bytes(state, count); s->characters(state, count); s->encoding(state, Qnil); s->hash_value(state, (Integer*)Qnil); s->shared(state, Qfalse); // fetch_bytes NULL terminates s->data(state, ba->fetch_bytes(state, start, count)); return s; }
String* SymbolTable::lookup_string(STATE, const Symbol* sym) { if(sym->nil_p()) { Exception::argument_error(state, "Cannot look up Symbol from nil"); return NULL; } size_t sym_index = sym->index(); if(sym_index >= strings.size()) { return NULL; } std::string& str = strings[sym_index]; String* s = String::create(state, str.data(), str.size()); s->encoding(state, Encoding::usascii_encoding(state)); return s; }
String* String::from_chararray(STATE, CharArray* ca, Fixnum* start, Fixnum* count) { String* s = state->new_object<String>(G(string)); s->num_bytes(state, count); s->encoding(state, Qnil); s->hash_value(state, nil<Fixnum>()); s->shared(state, Qfalse); // fetch_bytes NULL terminates s->data(state, ca->fetch_bytes(state, start, count)); return s; }
Object* Dir::read(STATE) { guard(state); struct dirent ent; struct dirent* entp = &ent; if(int erno = readdir_r(os(), entp, &entp)) { Exception::raise_errno_error(state, "readdir_r(3) failed", erno); } if(!entp) return cNil; String* str = String::create(state, ent.d_name); str->encoding(state, encoding()); return str; }
String* String::create_reserved(STATE, native_int bytes) { String *so; so = state->new_object<String>(G(string)); so->num_bytes(state, Fixnum::from(0)); so->encoding(state, Qnil); so->hash_value(state, nil<Fixnum>()); so->shared(state, Qfalse); CharArray* ba = CharArray::create(state, bytes+1); ba->raw_bytes()[bytes] = 0; so->data(state, ba); return so; }
String* Float::to_s_formatted(STATE, String* format) { char buf[FLOAT_TO_S_STRLEN]; size_t size = snprintf(buf, FLOAT_TO_S_STRLEN, format->c_str(state), val); if(size >= FLOAT_TO_S_STRLEN) { std::ostringstream msg; msg << "formatted string exceeds " << FLOAT_TO_S_STRLEN << " bytes"; Exception::argument_error(state, msg.str().c_str()); } String* str = String::create(state, buf, size); infect(state, str); str->encoding(state, Encoding::usascii_encoding(state)); str->ascii_only(state, cTrue); str->valid_encoding(state, cTrue); return str; }
String* SymbolTable::lookup_string(STATE, const Symbol* sym) { utilities::thread::SpinLock::LockGuard guard(lock_); if(sym->nil_p()) { Exception::argument_error(state, "Cannot look up Symbol from nil"); return NULL; } size_t sym_index = sym->index(); if(sym_index >= strings.size()) { return NULL; } std::string& str = strings[sym_index]; int enc = encodings[sym_index]; String* s = String::create(state, str.data(), str.size()); s->encoding(state, Encoding::from_index(state, enc)); return s; }
/* * Creates a String instance with +num_bytes+ bytes of storage. * It also pins the CharArray used for storage, so it can be passed * to an external function (like ::read) */ String* String::create_pinned(STATE, Fixnum* size) { String *so; so = state->new_object<String>(G(string)); so->num_bytes(state, size); so->encoding(state, Qnil); so->hash_value(state, nil<Fixnum>()); so->shared(state, Qfalse); native_int bytes = size->to_native() + 1; CharArray* ba = CharArray::create_pinned(state, bytes); ba->raw_bytes()[bytes-1] = 0; so->data(state, ba); return so; }
String* String::create_reserved(STATE, size_t bytes) { String *so; so = state->new_object<String>(G(string)); so->num_bytes(state, Fixnum::from(0)); so->characters(state, Fixnum::from(0)); so->encoding(state, Qnil); so->hash_value(state, (Integer*)Qnil); so->shared(state, Qfalse); ByteArray* ba = ByteArray::create(state, bytes); ba->raw_bytes()[bytes-1] = 0; so->data(state, ba); return so; }
/* * Creates a String instance with +num_bytes+ bytes of storage. * It also pins the ByteArray used for storage, so it can be passed * to an external function (like ::read) */ String* String::create_pinned(STATE, Fixnum* size) { String *so; so = state->new_object<String>(G(string)); so->num_bytes(state, size); so->characters(state, size); so->encoding(state, Qnil); so->hash_value(state, (Integer*)Qnil); so->shared(state, Qfalse); size_t bytes = size->to_native() + 1; ByteArray* ba = ByteArray::create_pinned(state, bytes); ba->bytes[bytes-1] = 0; so->data(state, ba); return so; }
String* UnMarshaller::get_string() { size_t count; Encoding* enc = try_as<Encoding>(unmarshal()); stream >> count; // String::create adds room for a trailing null on its own // using pinned here allows later stages to optimize these literal // strings better. String* str = String::create(state, NULL, count); stream.get(); // read off newline stream.read(reinterpret_cast<char*>(str->byte_address()), count); stream.get(); // read off newline if(enc) str->encoding(state, enc); return str; }
String* MatchData::pre_matched(STATE) { Fixnum* beg = try_as<Fixnum>(full_->at(state, 0)); native_int max = source_->byte_size(); native_int sz = beg->to_native(); String* string; if(!beg || sz <= 0) { string = String::create(state, 0, 0); } else { if(sz > max) sz = max; const char* str = (char*)source_->byte_address(); string = String::create(state, str, sz); } string->encoding(state, source_->encoding()); return string; }
String* MatchData::post_matched(STATE) { Fixnum* fin = try_as<Fixnum>(full_->at(state, 1)); native_int f = fin->to_native(); native_int max = source_->byte_size(); String* string; if(!fin || f >= max) { string = String::create(state, 0, 0); } else { const char* str = (char*)source_->byte_address(); native_int sz = max - f; if(sz > max) sz = max; string = String::create(state, str + f, sz); } string->encoding(state, source_->encoding()); return string; }
String* MatchData::matched_string(STATE) { Fixnum* beg = try_as<Fixnum>(full_->at(state, 0)); Fixnum* fin = try_as<Fixnum>(full_->at(state, 1)); native_int max = source_->byte_size(); native_int f = fin->to_native(); native_int b = beg->to_native(); String* string; if(!beg || !fin || f > max || b > max || b < 0) { string = String::create(state, 0, 0); } else { const char* str = (char*)source_->byte_address(); native_int sz = fin->to_native() - beg->to_native(); string = String::create(state, str + beg->to_native(), sz); } string->encoding(state, source_->encoding()); return string; }
void Environment::load_argv(int argc, char** argv) { String* str = 0; Encoding* enc = Encoding::default_external(state); Array* os_ary = Array::create(state, argc); for(int i = 0; i < argc; i++) { str = String::create(state, argv[i]); str->encoding(state, enc); os_ary->set(state, i, str); } G(rubinius)->set_const(state, "OS_ARGV", os_ary); char buf[MAXPATHLEN]; str = String::create(state, getcwd(buf, MAXPATHLEN)); str->encoding(state, enc); G(rubinius)->set_const(state, "OS_STARTUP_DIR", str); str = String::create(state, argv[0]); str->encoding(state, enc); state->vm()->set_const("ARG0", str); Array* ary = Array::create(state, argc - 1); int which_arg = 0; bool skip_xflags = true; for(int i=1; i < argc; i++) { char* arg = argv[i]; if(strcmp(arg, "--") == 0) { skip_xflags = false; } else if(strncmp(arg, "-X", 2) == 0) { if(skip_xflags) continue; } else if(arg[1] != '-') { skip_xflags = false; } str = String::create(state, arg); str->taint(state); str->encoding(state, enc); ary->set(state, which_arg++, str); } state->vm()->set_const("ARGV", ary); // Now finish up with the config if(config.print_config > 1) { std::cout << "========= Configuration =========\n"; config.print(true); std::cout << "=================================\n"; } else if(config.print_config) { config.print(); } if(config.agent_start > 0) { // if port_ is 1, the user wants to use a randomly assigned local // port which will be written to the temp file for console to pick // up. int port = config.agent_start; if(port == 1) port = 0; start_agent(port); } if(config.report_path.set_p()) { // Test that we can actually use this path int fd = open(config.report_path, O_RDONLY | O_CREAT, 0666); if(!fd) { std::cerr << "Unable to use " << config.report_path << " for crash reports.\n"; std::cerr << "Unable to open path: " << strerror(errno) << "\n"; // Don't use the home dir path even, just use stderr report_path[0] = 0; } else { close(fd); unlink(config.report_path); strncpy(report_path, config.report_path, sizeof(report_path) - 1); } } state->shared().set_use_capi_lock(config.capi_lock); }
void Environment::load_argv(int argc, char** argv) { String* str = 0; Encoding* enc = Encoding::default_external(state); Array* os_ary = Array::create(state, argc); for(int i = 0; i < argc; i++) { str = String::create(state, argv[i]); str->encoding(state, enc); os_ary->set(state, i, str); } G(rubinius)->set_const(state, "OS_ARGV", os_ary); char buf[MAXPATHLEN]; str = String::create(state, getcwd(buf, MAXPATHLEN)); str->encoding(state, enc); G(rubinius)->set_const(state, "OS_STARTUP_DIR", str); str = String::create(state, argv[0]); str->encoding(state, enc); state->vm()->set_const("ARG0", str); Array* ary = Array::create(state, argc - 1); int which_arg = 0; bool skip_xflags = true; for(int i=1; i < argc; i++) { char* arg = argv[i]; if(strcmp(arg, "--") == 0) { skip_xflags = false; } else if(strncmp(arg, "-X", 2) == 0) { if(skip_xflags) continue; } else if(arg[1] != '-') { skip_xflags = false; } str = String::create(state, arg); str->taint(state); str->encoding(state, enc); ary->set(state, which_arg++, str); } state->vm()->set_const("ARGV", ary); // Now finish up with the config if(config.print_config > 1) { std::cout << "========= Configuration =========\n"; config.print(true); std::cout << "=================================\n"; } else if(config.print_config) { config.print(); } if(config.agent_start > 0) { // if port_ is 1, the user wants to use a randomly assigned local // port which will be written to the temp file for console to pick // up. int port = config.agent_start; if(port == 1) port = 0; start_agent(port); } state->shared().set_use_capi_lock(config.capi_lock); }