value_t Hash::to_s(Hash *self) { RecursionDetector<RecursionType::Hash_to_s, false> rd(self); if(rd.recursion()) return String::get("{...}"); CharArray result = "{"; OnStack<1> os1(self); OnStackString<1> os2(result); HashAccess::each_pair(self, [&](value_t key, value_t value) -> bool { OnStack<1> os(value); result += inspect(key); result += "=>"; result += inspect(value); result += ", "; return true; }); if(result.size() > 1) result.shrink(result.size() - 2); result += "}"; return result.to_string(); }
template<typename F1, typename F2> void split(const CharArray &input, F1 data, F2 split) { compile_pattern(); int ovector[vector_size]; size_t prev = 0; while(true) { int groups = match(input, ovector, prev); if(groups <= 0) { if(prev < input.size()) data(input.copy(prev, input.size() - prev)); return; } else { int start = ovector[0]; int stop = ovector[1]; for (int i = 0; i < groups; i++) { start = std::min(start, ovector[2 * i]); stop = std::max(stop, ovector[2 * i + 1]); } if((size_t)stop == prev) { split(start, stop); data(input.copy(prev, 1)); prev += 1; } else { data(input.copy(prev, (size_t)start - prev)); split(start, stop); prev = stop; } } } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- String ShaderSourceRepository::shaderSource(ShaderIdent shaderIdent) { String shaderProg; CharArray rawSource; if (rawShaderSource(shaderIdent, &rawSource)) { if (rawSource.size() > 0) { #ifdef CVF_OPENGL_ES // Always version 100 on OpenGL ES shaderProg = "#version 100\nprecision highp float;\n"; #else // Default on desktop is GLSL 1.2 (OpenGL 2.1) unless the shader explicitly specifies a version if (rawSource[0] != '#') { shaderProg = "#version 120\n"; } #endif shaderProg += rawSource.ptr(); } } return shaderProg; }
/// Return a random unicode term, like StressIndexingTest. String randomString() { int32_t end = random->nextInt(20); if (buffer.size() < 1 + end) { buffer.resize((int32_t)((double)(1 + end) * 1.25)); } for (int32_t i = 0; i < end; ++i) { int32_t t = random->nextInt(5); if (t == 0 && i < end - 1) { #ifdef LPP_UNICODE_CHAR_SIZE_2 // Make a surrogate pair // High surrogate buffer[i++] = (wchar_t)nextInt(0xd800, 0xdc00); // Low surrogate buffer[i] = (wchar_t)nextInt(0xdc00, 0xe000); #else buffer[i] = (wchar_t)nextInt(0xdc00, 0xe000); #endif } else if (t <= 1) { buffer[i] = (wchar_t)nextInt(0x01, 0x80); } else if (t == 2) { buffer[i] = (wchar_t)nextInt(0x80, 0x800); } else if (t == 3) { buffer[i] = (wchar_t)nextInt(0x800, 0xd800); } else if (t == 4) { buffer[i] = (wchar_t)nextInt(0xe000, 0xfff0); } } return String(buffer.get(), end); }
value_t IO::rb_readlines(String *path) { Stream *file; Platform::wrap([&] { file = Platform::open(path->string, Platform::Read, Platform::Open); }); Finally finally([&] { delete file; }); auto result = Array::allocate(); while(true) { CharArray line = file->gets(); if(line.size()) result->vector.push(line.to_string()); else break; } return result; }
int32_t StringUtils::toUnicode(const uint8_t* utf8, int32_t length, CharArray unicode) { if (length == 0) return 0; UTF8Decoder utf8Decoder(utf8, utf8 + length); int32_t decodeLength = utf8Decoder.decode(unicode.get(), unicode.size()); return decodeLength == Reader::READER_EOF ? 0 : decodeLength; }
void test_compare_bytes() { CharArray* a = String::create(state, "xyZzyx")->data(); CharArray* b = String::create(state, "xyzzyx")->data(); Fixnum* two = Fixnum::from(2); Fixnum* three = Fixnum::from(3); Fixnum* size = Fixnum::from(8); Fixnum* size1 = Fixnum::from(9); TS_ASSERT_EQUALS(a->size(state)->to_native(), 8); TS_ASSERT_EQUALS(b->size(state)->to_native(), 8); TS_ASSERT_EQUALS(a->compare_bytes(state, b, two, two), Fixnum::from(0)); TS_ASSERT_EQUALS(a->compare_bytes(state, b, two, three), Fixnum::from(-1)); TS_ASSERT_EQUALS(a->compare_bytes(state, b, three, two), Fixnum::from(1)); TS_ASSERT_EQUALS(a->compare_bytes(state, b, three, three), Fixnum::from(-1)); TS_ASSERT_EQUALS(a->compare_bytes(state, b, size, size), Fixnum::from(-1)); TS_ASSERT_EQUALS(a->compare_bytes(state, b, size1, size1), Fixnum::from(-1)); }
void test_get_byte_index_out_of_bounds() { CharArray* c = String::create(state, "xyz")->data(); native_int sz = c->size(state)->to_native(); TS_ASSERT_THROWS_ASSERT(c->get_byte(state, Fixnum::from(sz)), const RubyException &e, TS_ASSERT(Exception::object_bounds_exceeded_error_p(state, e.exception))); TS_ASSERT_THROWS_ASSERT(c->get_byte(state, Fixnum::from(sz+1)), const RubyException &e, TS_ASSERT(Exception::object_bounds_exceeded_error_p(state, e.exception))); TS_ASSERT_THROWS_ASSERT(c->get_byte(state, Fixnum::from(-1)), const RubyException &e, TS_ASSERT(Exception::object_bounds_exceeded_error_p(state, e.exception))); }
CharArray Stream::gets() { static const size_t buffer_size = 0x200; CharArray result, buffer; while(true) { pos_t p = pos(); buffer = read(buffer_size); for(size_t i = 0; i < buffer.size(); ++i) { if(buffer[i] == '\r') { ++i; if(i < buffer.size()) { if(buffer[i] == '\n') ++i; seek(p + i, FromStart); return result + buffer.copy(0, i); } else { CharArray c = read(1); if(c == "\n") buffer += c; else seek(-(pos_t)c.size()); return result + buffer; } } else if(buffer[i] == '\n') { ++i; seek(p + i, FromStart); return result + buffer.copy(0, i); } } if(buffer.size() < buffer_size) return result + buffer; result += buffer; } }
CharArray NativeStream::read(size_t length) { CharArray buf; buf.buffer(length); ssize_t result = ::read(fd, buf.str_ref(), buf.size()); if(result < 0) raise("Unable to read from file descriptor"); buf.shrink((size_t)result); return buf; }
bool is_pattern(const CharArray &fn) { for(size_t i = 0; i < fn.size(); ++i) { switch(fn[i]) { case '*': case '?': return true; default: break; } } return false; }
void test_fetch_bytes_out_of_bounds() { CharArray* c = String::create(state, "xyzzy")->data(); Fixnum* neg = Fixnum::from(-1); Fixnum* zero = Fixnum::from(0); Fixnum* one = Fixnum::from(1); Fixnum* size = c->size(state); TS_ASSERT_THROWS_ASSERT(c->fetch_bytes(state, neg, zero), const RubyException &e, TS_ASSERT(Exception::object_bounds_exceeded_error_p(state, e.exception))); TS_ASSERT_THROWS_ASSERT(c->fetch_bytes(state, zero, neg), const RubyException &e, TS_ASSERT(Exception::object_bounds_exceeded_error_p(state, e.exception))); TS_ASSERT_THROWS_ASSERT(c->fetch_bytes(state, one, size), const RubyException &e, TS_ASSERT(Exception::object_bounds_exceeded_error_p(state, e.exception))); }
value_t rb_each_line(IO *io, value_t block) { OnStack<2> os(io, block); while(true) { io->assert_stream(); CharArray line = io->stream->gets(); if(line.size()) yield(block, line.to_string()); else break; } return io; }
/* We use the garbage collector's feature to "pin" an Object at a * particular memory location to allow C code to write directly into the * contets of a Ruby String (actually, a CharArray, which provides the * storage for String). Since any method on String that mutates self may * cause a new CharArray to be created, we always check whether the * String is pinned and update the RString structure unconditionally. */ void ensure_pinned(NativeMethodEnvironment* env, String* string, RString* rstring) { CharArray* ca = string->data(); size_t byte_size = ca->size(); if(!ca->pinned_p()) { ca = CharArray::create_pinned(env->state(), byte_size); memcpy(ca->raw_bytes(), string->byte_address(), byte_size); string->data(env->state(), ca); } char* ptr = reinterpret_cast<char*>(ca->raw_bytes()); ptr[byte_size-1] = 0; rstring->dmwmb = rstring->ptr = ptr; rstring->len = string->size(); rstring->aux.capa = byte_size; rstring->aux.shared = Qfalse; }
void test_locate() { CharArray* c = String::create(state, "xyZfoo\nzyx")->data(); Fixnum* size = Fixnum::from(c->size()); Fixnum* zero = Fixnum::from(0); Fixnum* three = Fixnum::from(3); Fixnum* seven = Fixnum::from(7); Fixnum* four = Fixnum::from(4); Fixnum* two = Fixnum::from(2); String* foo_nl = String::create(state, "foo\n"); TS_ASSERT_EQUALS(three, (Fixnum*)c->locate(state, String::create(state, ""), three, size)); TS_ASSERT_EQUALS(Qnil, c->locate(state, String::create(state, "\n\n"), zero, size)); TS_ASSERT_EQUALS(seven, (Fixnum*)c->locate(state, String::create(state, "\n"), zero, size)); TS_ASSERT_EQUALS(Qnil, c->locate(state, foo_nl, four, size)); TS_ASSERT_EQUALS(seven, (Fixnum*)c->locate(state, foo_nl, two, size)); TS_ASSERT_EQUALS(seven, (Fixnum*)c->locate(state, foo_nl, three, size)); TS_ASSERT_EQUALS(Fixnum::from(10), (Fixnum*)c->locate(state, String::create(state, "yx"), three, size)); }
void glob(Array *array, std::vector<CharArray> &segments, size_t i, CharArray path) { auto join_path = [&](CharArray filename) -> CharArray { if(path.size()) return path + "/" + filename; else return filename; }; while((i < segments.size() - 1) && !is_pattern(segments[i])) { path = join_path(segments[i]); i++; } if(segments[i] == "**" && (i + 1 < segments.size())) { Platform::list_dir(File::expand_path(path), true, [&](const CharArray &filename, bool directory) { if(directory) glob(array, segments, i, join_path(filename)); }); glob(array, segments, i + 1, path); } else if(i + 1 < segments.size()) { Platform::list_dir(File::expand_path(path), true, [&](const CharArray &filename, bool directory) { if(directory && File::fnmatch(filename, segments[i])) glob(array, segments, i + 1, join_path(filename)); }); } else { Platform::list_dir(File::expand_path(path), true, [&](const CharArray &filename, bool) { if(File::fnmatch(filename, segments[i])) array->vector.push(String::get(join_path(filename))); }); } }
void NativeStream::print(const CharArray &string) { if(write(fd, string.str_ref(), string.size()) == -1) raise("Unable to write to file descriptor"); }
void test_size() { CharArray* c = CharArray::create(state, 1); TS_ASSERT_EQUALS(c->size(state), Fixnum::from(sizeof(Object*))); }
void test_allocate() { CharArray* c = CharArray::allocate(state, Fixnum::from(5)); TS_ASSERT_EQUALS(c->size(state)->to_native(), 8); }