|
@@ -51,6 +51,32 @@ VALUE get_def_obj(const void* def) {
|
|
return rb_hash_aref(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def));
|
|
return rb_hash_aref(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static VALUE cached_empty_string = Qnil;
|
|
|
|
+static VALUE cached_empty_bytes = Qnil;
|
|
|
|
+
|
|
|
|
+static VALUE create_frozen_string(const char* str, size_t size, bool binary) {
|
|
|
|
+ VALUE str_rb = rb_str_new(str, size);
|
|
|
|
+
|
|
|
|
+ rb_enc_associate(str_rb,
|
|
|
|
+ binary ? kRubyString8bitEncoding : kRubyStringUtf8Encoding);
|
|
|
|
+ rb_obj_freeze(str_rb);
|
|
|
|
+ return str_rb;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+VALUE get_frozen_string(const char* str, size_t size, bool binary) {
|
|
|
|
+ if (size == 0) {
|
|
|
|
+ return binary ? cached_empty_bytes : cached_empty_string;
|
|
|
|
+ } else {
|
|
|
|
+ // It is harder to memoize non-empty strings. The obvious approach would be
|
|
|
|
+ // to use a Ruby hash keyed by string as memo table, but looking up in such a table
|
|
|
|
+ // requires constructing a string (the very thing we're trying to avoid).
|
|
|
|
+ //
|
|
|
|
+ // Since few fields have defaults, we will just optimize the empty string
|
|
|
|
+ // case for now.
|
|
|
|
+ return create_frozen_string(str, size, binary);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
// -----------------------------------------------------------------------------
|
|
// -----------------------------------------------------------------------------
|
|
// Utilities.
|
|
// Utilities.
|
|
// -----------------------------------------------------------------------------
|
|
// -----------------------------------------------------------------------------
|
|
@@ -118,4 +144,9 @@ void Init_protobuf_c() {
|
|
|
|
|
|
rb_gc_register_address(&upb_def_to_ruby_obj_map);
|
|
rb_gc_register_address(&upb_def_to_ruby_obj_map);
|
|
upb_def_to_ruby_obj_map = rb_hash_new();
|
|
upb_def_to_ruby_obj_map = rb_hash_new();
|
|
|
|
+
|
|
|
|
+ rb_gc_register_address(&cached_empty_string);
|
|
|
|
+ rb_gc_register_address(&cached_empty_bytes);
|
|
|
|
+ cached_empty_string = create_frozen_string("", 0, false);
|
|
|
|
+ cached_empty_bytes = create_frozen_string("", 0, true);
|
|
}
|
|
}
|