size_t msgpack_buffer_flush_to_io(msgpack_buffer_t* b, VALUE io, ID write_method, bool consume) { if(msgpack_buffer_top_readable_size(b) == 0) { return 0; } VALUE s = _msgpack_buffer_head_chunk_as_string(b); rb_funcall(io, write_method, 1, s); size_t sz = RSTRING_LEN(s); if(consume) { while(_msgpack_buffer_shift_chunk(b)) { s = _msgpack_buffer_chunk_as_string(b->head); rb_funcall(io, write_method, 1, s); sz += RSTRING_LEN(s); } return sz; } else { if(b->head == &b->tail) { return sz; } msgpack_buffer_chunk_t* c = b->head->next; while(true) { s = _msgpack_buffer_chunk_as_string(c); rb_funcall(io, write_method, 1, s); sz += RSTRING_LEN(s); if(c == &b->tail) { return sz; } c = c->next; } } }
size_t msgpack_buffer_read_nonblock(msgpack_buffer_t* b, char* buffer, size_t length) { /* buffer == NULL means skip */ size_t const length_orig = length; while(true) { size_t avail = msgpack_buffer_top_readable_size(b); if(length <= avail) { if(buffer != NULL) { memcpy(buffer, b->read_buffer, length); } _msgpack_buffer_consumed(b, length); return length_orig; } if(buffer != NULL) { memcpy(buffer, b->read_buffer, avail); buffer += avail; } length -= avail; if(!_msgpack_buffer_shift_chunk(b)) { return length_orig - length; } } }
VALUE msgpack_buffer_all_as_string(msgpack_buffer_t* b) { if(b->head == &b->tail) { return _msgpack_buffer_head_chunk_as_string(b); } size_t length = msgpack_buffer_all_readable_size(b); VALUE string = rb_str_new(NULL, length); char* buffer = RSTRING_PTR(string); size_t avail = msgpack_buffer_top_readable_size(b); memcpy(buffer, b->read_buffer, avail); buffer += avail; length -= avail; msgpack_buffer_chunk_t* c = b->head->next; while(true) { avail = c->last - c->first; memcpy(buffer, c->first, avail); if(length <= avail) { return string; } buffer += avail; length -= avail; c = c->next; } }
static VALUE Packer_empty_p(VALUE self) { PACKER(self, pk); if(msgpack_buffer_top_readable_size(PACKER_BUFFER_(pk)) == 0) { return Qtrue; } else { return Qfalse; } }
static mrb_value Packer_empty_p(mrb_state *mrb, mrb_value self) { PACKER(mrb, self, pk); if (msgpack_buffer_top_readable_size(PACKER_BUFFER_(pk)) == 0) { return mrb_true_value(); } else { return mrb_false_value(); } }
static VALUE Buffer_empty_p(VALUE self) { BUFFER(self, b); if(msgpack_buffer_top_readable_size(b) == 0) { return Qtrue; } else { return Qfalse; } }
size_t msgpack_buffer_read_to_string_nonblock(msgpack_buffer_t* b, VALUE string, size_t length) { size_t avail = msgpack_buffer_top_readable_size(b); #ifndef DISABLE_BUFFER_READ_REFERENCE_OPTIMIZE /* optimize */ if(length <= avail && RSTRING_LEN(string) == 0 && b->head->mapped_string != NO_MAPPED_STRING && length >= b->read_reference_threshold) { VALUE s = _msgpack_buffer_refer_head_mapped_string(b, length); #ifndef HAVE_RB_STR_REPLACE /* TODO MRI 1.8 */ rb_funcall(string, s_replace, 1, s); #else rb_str_replace(string, s); #endif /* here doesn't have to call ENCODING_SET because * encoding of s is always ASCII-8BIT */ _msgpack_buffer_consumed(b, length); return length; } #endif size_t const length_orig = length; while(true) { if(length <= avail) { rb_str_buf_cat(string, b->read_buffer, length); _msgpack_buffer_consumed(b, length); return length_orig; } rb_str_buf_cat(string, b->read_buffer, avail); length -= avail; if(!_msgpack_buffer_shift_chunk(b)) { return length_orig - length; } avail = msgpack_buffer_top_readable_size(b); } }
VALUE MessagePack_unpack(int argc, VALUE* argv) { VALUE src; switch(argc) { case 1: src = argv[0]; break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc); } VALUE io = Qnil; if(rb_type(src) != T_STRING) { io = src; src = Qnil; } VALUE self = Unpacker_alloc(cMessagePack_Unpacker); UNPACKER(self, uk); //msgpack_unpacker_reset(s_unpacker); //msgpack_buffer_reset_io(UNPACKER_BUFFER_(s_unpacker)); /* prefer reference than copying */ msgpack_buffer_set_write_reference_threshold(UNPACKER_BUFFER_(uk), 0); if(io != Qnil) { MessagePack_Buffer_initialize(UNPACKER_BUFFER_(uk), io, Qnil); } if(src != Qnil) { /* prefer reference than copying; see MessagePack_Unpacker_module_init */ msgpack_buffer_append_string(UNPACKER_BUFFER_(uk), src); } int r = msgpack_unpacker_read(uk, 0); if(r < 0) { raise_unpacker_error(r); } /* raise if extra bytes follow */ if(msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk)) > 0) { rb_raise(eMalformedFormatError, "extra bytes follow after a deserialized object"); } #ifdef RB_GC_GUARD /* This prevents compilers from optimizing out the `self` variable * from stack. Otherwise GC free()s it. */ RB_GC_GUARD(self); #endif return msgpack_unpacker_get_last_object(uk); }
VALUE MessagePack_unpack(int argc, VALUE* argv) { VALUE src; switch(argc) { case 1: src = argv[0]; break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc); } VALUE io = Qnil; if(rb_type(src) != T_STRING) { io = src; src = Qnil; } // TODO create an instance if io is set for thread safety? //VALUE self = Unpacker_alloc(cMessagePack_Unpacker); //UNPACKER(self, uk); msgpack_unpacker_reset(s_unpacker); msgpack_buffer_reset_io(UNPACKER_BUFFER_(s_unpacker)); if(io != Qnil) { MessagePack_Buffer_initialize(UNPACKER_BUFFER_(s_unpacker), io, Qnil); } if(src != Qnil) { /* prefer reference than copying; see MessagePack_Unpacker_module_init */ msgpack_buffer_append_string(UNPACKER_BUFFER_(s_unpacker), src); } int r = msgpack_unpacker_read(s_unpacker, 0); if(r < 0) { raise_unpacker_error(r); } /* raise if extra bytes follow */ if(msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(s_unpacker)) > 0) { rb_raise(eMalformedFormatError, "extra bytes follow after a deserialized object"); } return msgpack_unpacker_get_last_object(s_unpacker); }
size_t msgpack_buffer_all_readable_size(const msgpack_buffer_t* b) { size_t sz = msgpack_buffer_top_readable_size(b); if(b->head == &b->tail) { return sz; } msgpack_buffer_chunk_t* c = b->head->next; while(true) { sz += c->last - c->first; if(c == &b->tail) { return sz; } c = c->next; } }
VALUE MessagePack_unpack(int argc, VALUE* argv) { VALUE src; VALUE self; if (argc < 0 || argc > 2) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc); } src = argv[0]; if(rb_type(src) == T_STRING) { self = MessagePack_Factory_unpacker(argc - 1, argv + 1, cMessagePack_DefaultFactory); UNPACKER(self, uk); msgpack_buffer_append_string(UNPACKER_BUFFER_(uk), src); } else { self = MessagePack_Factory_unpacker(argc, argv, cMessagePack_DefaultFactory); } UNPACKER(self, uk); /* prefer reference than copying; see MessagePack_Unpacker_module_init */ msgpack_buffer_set_write_reference_threshold(UNPACKER_BUFFER_(uk), 0); int r = msgpack_unpacker_read(uk, 0); if(r < 0) { raise_unpacker_error(r); } /* raise if extra bytes follow */ size_t extra = msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk)); if(extra > 0) { rb_raise(eMalformedFormatError, "%zd extra bytes after the deserialized object", extra); } #ifdef RB_GC_GUARD /* This prevents compilers from optimizing out the `self` variable * from stack. Otherwise GC free()s it. */ RB_GC_GUARD(self); #endif return msgpack_unpacker_get_last_object(uk); }