diff --git a/ext/msgpack/buffer.c b/ext/msgpack/buffer.c index 9b7fd4e8..d1583702 100644 --- a/ext/msgpack/buffer.c +++ b/ext/msgpack/buffer.c @@ -300,7 +300,7 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b) static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE string) { VALUE mapped_string; - if(ENCODING_GET(string) == msgpack_rb_encindex_ascii8bit && RTEST(rb_obj_frozen_p(string))) { + if(ENCODING_GET_INLINED(string) == msgpack_rb_encindex_ascii8bit && RB_OBJ_FROZEN_RAW(string)) { mapped_string = string; } else { mapped_string = rb_str_dup(string); @@ -309,8 +309,9 @@ static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE s _msgpack_buffer_add_new_chunk(b); - char* data = RSTRING_PTR(mapped_string); - size_t length = RSTRING_LEN(mapped_string); + char* data; + size_t length; + RSTRING_GETMEM(mapped_string, data, length); b->tail.first = (char*) data; b->tail.last = (char*) data + length; @@ -330,7 +331,7 @@ void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string) { if(b->io != Qnil) { msgpack_buffer_flush(b); - if (ENCODING_GET(string) == msgpack_rb_encindex_ascii8bit) { + if (ENCODING_GET_INLINED(string) == msgpack_rb_encindex_ascii8bit) { rb_funcall(b->io, b->io_write_all_method, 1, string); } else { msgpack_buffer_append(b, RSTRING_PTR(string), RSTRING_LEN(string)); diff --git a/ext/msgpack/buffer.h b/ext/msgpack/buffer.h index c2ed46c4..1c8efe54 100644 --- a/ext/msgpack/buffer.h +++ b/ext/msgpack/buffer.h @@ -237,13 +237,14 @@ void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string); static inline size_t msgpack_buffer_append_string(msgpack_buffer_t* b, VALUE string) { - size_t length = RSTRING_LEN(string); + size_t length; + char *ptr; + RSTRING_GETMEM(string, ptr, length); if(length > b->write_reference_threshold) { _msgpack_buffer_append_long_string(b, string); - } else { - msgpack_buffer_append(b, RSTRING_PTR(string), length); + msgpack_buffer_append(b, ptr, length); } return length; diff --git a/ext/msgpack/extconf.rb b/ext/msgpack/extconf.rb index f6ff2d47..b1b921c8 100644 --- a/ext/msgpack/extconf.rb +++ b/ext/msgpack/extconf.rb @@ -9,12 +9,13 @@ "-fvisibility=hidden", "-I..", "-Wall", - "-O3", "-std=gnu99" ]) -append_cflags(RbConfig::CONFIG["debugflags"]) if RbConfig::CONFIG["debugflags"] -append_cflags("-DRUBY_DEBUG=1") if ENV["MSGPACK_DEBUG"] +if ENV["MSGPACK_DEBUG"] + append_cflags(RbConfig::CONFIG["debugflags"]) if RbConfig::CONFIG["debugflags"] + append_cflags("-DRUBY_DEBUG=1") +end if RUBY_VERSION.start_with?('3.0.') && RUBY_VERSION <= '3.0.5' # https://bugs.ruby-lang.org/issues/18772 diff --git a/ext/msgpack/packer.h b/ext/msgpack/packer.h index 5061b40c..f3441f5f 100644 --- a/ext/msgpack/packer.h +++ b/ext/msgpack/packer.h @@ -25,6 +25,11 @@ #define MSGPACK_PACKER_IO_FLUSH_THRESHOLD_TO_WRITE_STRING_BODY (1024) #endif +#ifndef UNREACHABLE_RETURN +// Ruby 2.5 +#define UNREACHABLE_RETURN() return +#endif + struct msgpack_packer_t; typedef struct msgpack_packer_t msgpack_packer_t; @@ -404,27 +409,33 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex) { return encindex == msgpack_rb_encindex_utf8 || encindex == msgpack_rb_encindex_usascii - || (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v)); + || ENC_CODERANGE_ASCIIONLY(v); } static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v) { - /* actual return type of RSTRING_LEN is long */ - unsigned long len = RSTRING_LEN(v); - if(len > 0xffffffffUL) { - // TODO rb_eArgError? - rb_raise(rb_eArgError, "size of string is too long to pack: %lu bytes should be <= %lu", len, 0xffffffffUL); + long len = RSTRING_LEN(v); + + if(RB_UNLIKELY(len > 0xffffffffL)) { + rb_raise(rb_eArgError, "size of string is too long to pack: %lu bytes should be <= %ld", len, 0xffffffffL); + UNREACHABLE_RETURN(); + } + + if (RB_UNLIKELY(pk->compatibility_mode)) { + msgpack_packer_write_raw_header(pk, (unsigned int)len); + msgpack_buffer_append_string(PACKER_BUFFER_(pk), v); + return; } - int encindex = ENCODING_GET(v); - if(msgpack_packer_is_binary(v, encindex) && !pk->compatibility_mode) { + int encindex = ENCODING_GET_INLINED(v); + if(msgpack_packer_is_binary(v, encindex)) { /* write ASCII-8BIT string using Binary type */ msgpack_packer_write_bin_header(pk, (unsigned int)len); msgpack_buffer_append_string(PACKER_BUFFER_(pk), v); } else { /* write UTF-8, US-ASCII, or 7bit-safe ascii-compatible string using String type directly */ /* in compatibility mode, packer packs String values as is */ - if(!pk->compatibility_mode && !msgpack_packer_is_utf8_compat_string(v, encindex)) { + if(RB_UNLIKELY(!msgpack_packer_is_utf8_compat_string(v, encindex))) { /* transcode other strings to UTF-8 and write using String type */ VALUE enc = rb_enc_from_encoding(rb_utf8_encoding()); /* rb_enc_from_encoding_index is not extern */ v = rb_str_encode(v, enc, 0, Qnil);