Merge pull request #9436 from haberman/ruby-upb2

Updated Ruby to the current version of upb
pull/9438/head
Joshua Haberman 3 years ago committed by GitHub
commit b696347f80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      CHANGES.txt
  2. 8
      ruby/Rakefile
  3. 229
      ruby/ext/google/protobuf_c/convert.c
  4. 21
      ruby/ext/google/protobuf_c/convert.h
  5. 397
      ruby/ext/google/protobuf_c/defs.c
  6. 38
      ruby/ext/google/protobuf_c/defs.h
  7. 14
      ruby/ext/google/protobuf_c/extconf.rb
  8. 210
      ruby/ext/google/protobuf_c/map.c
  9. 15
      ruby/ext/google/protobuf_c/map.h
  10. 626
      ruby/ext/google/protobuf_c/message.c
  11. 41
      ruby/ext/google/protobuf_c/message.h
  12. 115
      ruby/ext/google/protobuf_c/protobuf.c
  13. 23
      ruby/ext/google/protobuf_c/protobuf.h
  14. 166
      ruby/ext/google/protobuf_c/repeated_field.c
  15. 12
      ruby/ext/google/protobuf_c/repeated_field.h
  16. 8029
      ruby/ext/google/protobuf_c/ruby-upb.c
  17. 3986
      ruby/ext/google/protobuf_c/ruby-upb.h
  18. 7
      ruby/ext/google/protobuf_c/wrap_memcpy.c
  19. 8
      ruby/tests/common_tests.rb
  20. 13
      third_party/utf8_range/BUILD
  21. 21
      third_party/utf8_range/LICENSE
  22. 395
      third_party/utf8_range/utf8_range.c
  23. 9
      third_party/utf8_range/utf8_range.h

@ -1,3 +1,14 @@
Unreleased Changes (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
Ruby
* JSON will now output shorter strings for double and float fields when possible
without losing precision.
* Encoding and decoding of binary format will now work properly on big-endian
systems.
* UTF-8 verification was fixed to properly reject surrogate code points.
* Unknown enums for proto2 protos now properly implement proto2's behavior of
putting such values in unknown fields.
2022-01-10 version 3.19.3 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
Python

@ -80,6 +80,14 @@ if RUBY_PLATFORM == "java"
end
else
unless ENV['IN_DOCKER'] == 'true'
# We need utf8_range in-tree.
FileUtils.mkdir_p("ext/google/protobuf_c/third_party/utf8_range")
FileUtils.cp("../third_party/utf8_range/utf8_range.h", "ext/google/protobuf_c/third_party/utf8_range")
FileUtils.cp("../third_party/utf8_range/utf8_range.c", "ext/google/protobuf_c/third_party/utf8_range")
FileUtils.cp("../third_party/utf8_range/LICENSE", "ext/google/protobuf_c/third_party/utf8_range")
end
Rake::ExtensionTask.new("protobuf_c", spec) do |ext|
unless RUBY_PLATFORM =~ /darwin/
# TODO: also set "no_native to true" for mac if possible. As is,

@ -31,7 +31,7 @@
// -----------------------------------------------------------------------------
// Ruby <-> upb data conversion functions.
//
// This file Also contains a few other assorted algorithms on upb_msgval.
// This file Also contains a few other assorted algorithms on upb_MessageValue.
//
// None of the algorithms in this file require any access to the internal
// representation of Ruby or upb objects.
@ -42,10 +42,10 @@
#include "message.h"
#include "protobuf.h"
static upb_strview Convert_StringData(VALUE str, upb_arena *arena) {
upb_strview ret;
static upb_StringView Convert_StringData(VALUE str, upb_Arena* arena) {
upb_StringView ret;
if (arena) {
char *ptr = upb_arena_malloc(arena, RSTRING_LEN(str));
char* ptr = upb_Arena_Malloc(arena, RSTRING_LEN(str));
memcpy(ptr, RSTRING_PTR(str), RSTRING_LEN(str));
ret.data = ptr;
} else {
@ -57,13 +57,11 @@ static upb_strview Convert_StringData(VALUE str, upb_arena *arena) {
}
static bool is_ruby_num(VALUE value) {
return (TYPE(value) == T_FLOAT ||
TYPE(value) == T_FIXNUM ||
return (TYPE(value) == T_FLOAT || TYPE(value) == T_FIXNUM ||
TYPE(value) == T_BIGNUM);
}
static void Convert_CheckInt(const char* name, upb_fieldtype_t type,
VALUE val) {
static void Convert_CheckInt(const char* name, upb_CType type, VALUE val) {
if (!is_ruby_num(val)) {
rb_raise(cTypeError,
"Expected number type for integral field '%s' (given %s).", name,
@ -82,7 +80,7 @@ static void Convert_CheckInt(const char* name, upb_fieldtype_t type,
name, rb_class2name(CLASS_OF(val)));
}
}
if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
if (type == kUpb_CType_UInt32 || type == kUpb_CType_UInt64) {
if (NUM2DBL(val) < 0) {
rb_raise(
rb_eRangeError,
@ -93,26 +91,31 @@ static void Convert_CheckInt(const char* name, upb_fieldtype_t type,
}
static int32_t Convert_ToEnum(VALUE value, const char* name,
const upb_enumdef* e) {
const upb_EnumDef* e) {
int32_t val;
switch (TYPE(value)) {
case T_FLOAT:
case T_FIXNUM:
case T_BIGNUM:
Convert_CheckInt(name, UPB_TYPE_INT32, value);
Convert_CheckInt(name, kUpb_CType_Int32, value);
val = NUM2INT(value);
break;
case T_STRING:
if (!upb_enumdef_ntoi(e, RSTRING_PTR(value), RSTRING_LEN(value), &val)) {
goto unknownval;
}
case T_STRING: {
const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNameWithSize(
e, RSTRING_PTR(value), RSTRING_LEN(value));
if (!ev) goto unknownval;
val = upb_EnumValueDef_Number(ev);
break;
case T_SYMBOL:
if (!upb_enumdef_ntoiz(e, rb_id2name(SYM2ID(value)), &val)) {
}
case T_SYMBOL: {
const upb_EnumValueDef* ev =
upb_EnumDef_FindValueByName(e, rb_id2name(SYM2ID(value)));
if (!ev)
goto unknownval;
}
val = upb_EnumValueDef_Number(ev);
break;
}
default:
rb_raise(cTypeError,
"Expected number or symbol type for enum field '%s'.", name);
@ -124,47 +127,52 @@ unknownval:
rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
}
upb_msgval Convert_RubyToUpb(VALUE value, const char* name, TypeInfo type_info,
upb_arena* arena) {
upb_msgval ret;
upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name,
TypeInfo type_info, upb_Arena* arena) {
upb_MessageValue ret;
switch (type_info.type) {
case UPB_TYPE_FLOAT:
case kUpb_CType_Float:
if (!is_ruby_num(value)) {
rb_raise(cTypeError, "Expected number type for float field '%s' (given %s).",
name, rb_class2name(CLASS_OF(value)));
rb_raise(cTypeError,
"Expected number type for float field '%s' (given %s).", name,
rb_class2name(CLASS_OF(value)));
}
ret.float_val = NUM2DBL(value);
break;
case UPB_TYPE_DOUBLE:
case kUpb_CType_Double:
if (!is_ruby_num(value)) {
rb_raise(cTypeError, "Expected number type for double field '%s' (given %s).",
name, rb_class2name(CLASS_OF(value)));
rb_raise(cTypeError,
"Expected number type for double field '%s' (given %s).", name,
rb_class2name(CLASS_OF(value)));
}
ret.double_val = NUM2DBL(value);
break;
case UPB_TYPE_BOOL: {
case kUpb_CType_Bool: {
if (value == Qtrue) {
ret.bool_val = 1;
} else if (value == Qfalse) {
ret.bool_val = 0;
} else {
rb_raise(cTypeError, "Invalid argument for boolean field '%s' (given %s).",
name, rb_class2name(CLASS_OF(value)));
rb_raise(cTypeError,
"Invalid argument for boolean field '%s' (given %s).", name,
rb_class2name(CLASS_OF(value)));
}
break;
}
case UPB_TYPE_STRING: {
case kUpb_CType_String: {
VALUE utf8 = rb_enc_from_encoding(rb_utf8_encoding());
if (CLASS_OF(value) == rb_cSymbol) {
value = rb_funcall(value, rb_intern("to_s"), 0);
} else if (CLASS_OF(value) != rb_cString) {
rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).",
name, rb_class2name(CLASS_OF(value)));
rb_raise(cTypeError,
"Invalid argument for string field '%s' (given %s).", name,
rb_class2name(CLASS_OF(value)));
}
if (rb_obj_encoding(value) != utf8) {
// Note: this will not duplicate underlying string data unless necessary.
// Note: this will not duplicate underlying string data unless
// necessary.
value = rb_str_encode(value, utf8, 0, Qnil);
if (rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
@ -175,15 +183,17 @@ upb_msgval Convert_RubyToUpb(VALUE value, const char* name, TypeInfo type_info,
ret.str_val = Convert_StringData(value, arena);
break;
}
case UPB_TYPE_BYTES: {
case kUpb_CType_Bytes: {
VALUE bytes = rb_enc_from_encoding(rb_ascii8bit_encoding());
if (CLASS_OF(value) != rb_cString) {
rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).",
name, rb_class2name(CLASS_OF(value)));
rb_raise(cTypeError,
"Invalid argument for bytes field '%s' (given %s).", name,
rb_class2name(CLASS_OF(value)));
}
if (rb_obj_encoding(value) != bytes) {
// Note: this will not duplicate underlying string data unless necessary.
// Note: this will not duplicate underlying string data unless
// necessary.
// TODO(haberman): is this really necessary to get raw bytes?
value = rb_str_encode(value, bytes, 0, Qnil);
}
@ -191,33 +201,33 @@ upb_msgval Convert_RubyToUpb(VALUE value, const char* name, TypeInfo type_info,
ret.str_val = Convert_StringData(value, arena);
break;
}
case UPB_TYPE_MESSAGE:
case kUpb_CType_Message:
ret.msg_val =
Message_GetUpbMessage(value, type_info.def.msgdef, name, arena);
break;
case UPB_TYPE_ENUM:
case kUpb_CType_Enum:
ret.int32_val = Convert_ToEnum(value, name, type_info.def.enumdef);
break;
case UPB_TYPE_INT32:
case UPB_TYPE_INT64:
case UPB_TYPE_UINT32:
case UPB_TYPE_UINT64:
case kUpb_CType_Int32:
case kUpb_CType_Int64:
case kUpb_CType_UInt32:
case kUpb_CType_UInt64:
Convert_CheckInt(name, type_info.type, value);
switch (type_info.type) {
case UPB_TYPE_INT32:
ret.int32_val = NUM2INT(value);
break;
case UPB_TYPE_INT64:
ret.int64_val = NUM2LL(value);
break;
case UPB_TYPE_UINT32:
ret.uint32_val = NUM2UINT(value);
break;
case UPB_TYPE_UINT64:
ret.uint64_val = NUM2ULL(value);
break;
default:
break;
case kUpb_CType_Int32:
ret.int32_val = NUM2INT(value);
break;
case kUpb_CType_Int64:
ret.int64_val = NUM2LL(value);
break;
case kUpb_CType_UInt32:
ret.uint32_val = NUM2UINT(value);
break;
case kUpb_CType_UInt64:
ret.uint64_val = NUM2ULL(value);
break;
default:
break;
}
break;
default:
@ -227,45 +237,46 @@ upb_msgval Convert_RubyToUpb(VALUE value, const char* name, TypeInfo type_info,
return ret;
}
VALUE Convert_UpbToRuby(upb_msgval upb_val, TypeInfo type_info, VALUE arena) {
VALUE Convert_UpbToRuby(upb_MessageValue upb_val, TypeInfo type_info,
VALUE arena) {
switch (type_info.type) {
case UPB_TYPE_FLOAT:
case kUpb_CType_Float:
return DBL2NUM(upb_val.float_val);
case UPB_TYPE_DOUBLE:
case kUpb_CType_Double:
return DBL2NUM(upb_val.double_val);
case UPB_TYPE_BOOL:
case kUpb_CType_Bool:
return upb_val.bool_val ? Qtrue : Qfalse;
case UPB_TYPE_INT32:
case kUpb_CType_Int32:
return INT2NUM(upb_val.int32_val);
case UPB_TYPE_INT64:
case kUpb_CType_Int64:
return LL2NUM(upb_val.int64_val);
case UPB_TYPE_UINT32:
case kUpb_CType_UInt32:
return UINT2NUM(upb_val.uint32_val);
case UPB_TYPE_UINT64:
case kUpb_CType_UInt64:
return ULL2NUM(upb_val.int64_val);
case UPB_TYPE_ENUM: {
const char* name =
upb_enumdef_iton(type_info.def.enumdef, upb_val.int32_val);
if (name) {
return ID2SYM(rb_intern(name));
case kUpb_CType_Enum: {
const upb_EnumValueDef *ev = upb_EnumDef_FindValueByNumber(
type_info.def.enumdef, upb_val.int32_val);
if (ev) {
return ID2SYM(rb_intern(upb_EnumValueDef_Name(ev)));
} else {
return INT2NUM(upb_val.int32_val);
}
}
case UPB_TYPE_STRING: {
case kUpb_CType_String: {
VALUE str_rb = rb_str_new(upb_val.str_val.data, upb_val.str_val.size);
rb_enc_associate(str_rb, rb_utf8_encoding());
rb_obj_freeze(str_rb);
return str_rb;
}
case UPB_TYPE_BYTES: {
case kUpb_CType_Bytes: {
VALUE str_rb = rb_str_new(upb_val.str_val.data, upb_val.str_val.size);
rb_enc_associate(str_rb, rb_ascii8bit_encoding());
rb_obj_freeze(str_rb);
return str_rb;
}
case UPB_TYPE_MESSAGE:
return Message_GetRubyWrapper((upb_msg*)upb_val.msg_val,
case kUpb_CType_Message:
return Message_GetRubyWrapper((upb_Message*)upb_val.msg_val,
type_info.def.msgdef, arena);
default:
rb_raise(rb_eRuntimeError, "Convert_UpbToRuby(): Unexpected type %d",
@ -273,24 +284,24 @@ VALUE Convert_UpbToRuby(upb_msgval upb_val, TypeInfo type_info, VALUE arena) {
}
}
upb_msgval Msgval_DeepCopy(upb_msgval msgval, TypeInfo type_info,
upb_arena* arena) {
upb_msgval new_msgval;
upb_MessageValue Msgval_DeepCopy(upb_MessageValue msgval, TypeInfo type_info,
upb_Arena* arena) {
upb_MessageValue new_msgval;
switch (type_info.type) {
default:
memcpy(&new_msgval, &msgval, sizeof(msgval));
break;
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
case kUpb_CType_String:
case kUpb_CType_Bytes: {
size_t n = msgval.str_val.size;
char *mem = upb_arena_malloc(arena, n);
char* mem = upb_Arena_Malloc(arena, n);
new_msgval.str_val.data = mem;
new_msgval.str_val.size = n;
memcpy(mem, msgval.str_val.data, n);
break;
}
case UPB_TYPE_MESSAGE:
case kUpb_CType_Message:
new_msgval.msg_val =
Message_deep_copy(msgval.msg_val, type_info.def.msgdef, arena);
break;
@ -299,48 +310,50 @@ upb_msgval Msgval_DeepCopy(upb_msgval msgval, TypeInfo type_info,
return new_msgval;
}
bool Msgval_IsEqual(upb_msgval val1, upb_msgval val2, TypeInfo type_info) {
bool Msgval_IsEqual(upb_MessageValue val1, upb_MessageValue val2,
TypeInfo type_info) {
switch (type_info.type) {
case UPB_TYPE_BOOL:
case kUpb_CType_Bool:
return memcmp(&val1, &val2, 1) == 0;
case UPB_TYPE_FLOAT:
case UPB_TYPE_INT32:
case UPB_TYPE_UINT32:
case UPB_TYPE_ENUM:
case kUpb_CType_Float:
case kUpb_CType_Int32:
case kUpb_CType_UInt32:
case kUpb_CType_Enum:
return memcmp(&val1, &val2, 4) == 0;
case UPB_TYPE_DOUBLE:
case UPB_TYPE_INT64:
case UPB_TYPE_UINT64:
case kUpb_CType_Double:
case kUpb_CType_Int64:
case kUpb_CType_UInt64:
return memcmp(&val1, &val2, 8) == 0;
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
case kUpb_CType_String:
case kUpb_CType_Bytes:
return val1.str_val.size == val2.str_val.size &&
memcmp(val1.str_val.data, val2.str_val.data,
val1.str_val.size) == 0;
case UPB_TYPE_MESSAGE:
memcmp(val1.str_val.data, val2.str_val.data, val1.str_val.size) ==
0;
case kUpb_CType_Message:
return Message_Equal(val1.msg_val, val2.msg_val, type_info.def.msgdef);
default:
rb_raise(rb_eRuntimeError, "Internal error, unexpected type");
}
}
uint64_t Msgval_GetHash(upb_msgval val, TypeInfo type_info, uint64_t seed) {
uint64_t Msgval_GetHash(upb_MessageValue val, TypeInfo type_info,
uint64_t seed) {
switch (type_info.type) {
case UPB_TYPE_BOOL:
case kUpb_CType_Bool:
return Wyhash(&val, 1, seed, kWyhashSalt);
case UPB_TYPE_FLOAT:
case UPB_TYPE_INT32:
case UPB_TYPE_UINT32:
case UPB_TYPE_ENUM:
case kUpb_CType_Float:
case kUpb_CType_Int32:
case kUpb_CType_UInt32:
case kUpb_CType_Enum:
return Wyhash(&val, 4, seed, kWyhashSalt);
case UPB_TYPE_DOUBLE:
case UPB_TYPE_INT64:
case UPB_TYPE_UINT64:
case kUpb_CType_Double:
case kUpb_CType_Int64:
case kUpb_CType_UInt64:
return Wyhash(&val, 8, seed, kWyhashSalt);
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
case kUpb_CType_String:
case kUpb_CType_Bytes:
return Wyhash(val.str_val.data, val.str_val.size, seed, kWyhashSalt);
case UPB_TYPE_MESSAGE:
case kUpb_CType_Message:
return Message_Hash(val.msg_val, type_info.def.msgdef, seed);
default:
rb_raise(rb_eRuntimeError, "Internal error, unexpected type");

@ -36,7 +36,7 @@
#include "protobuf.h"
#include "ruby-upb.h"
// Converts |ruby_val| to a upb_msgval according to |type_info|.
// Converts |ruby_val| to a upb_MessageValue according to |type_info|.
//
// The |arena| parameter indicates the lifetime of the container where this
// value will be assigned. It is used as follows:
@ -47,8 +47,8 @@
// - If type is message and the Ruby value is a message instance, we will fuse
// the message's arena into |arena|, to ensure that this message outlives the
// container.
upb_msgval Convert_RubyToUpb(VALUE ruby_val, const char *name,
TypeInfo type_info, upb_arena *arena);
upb_MessageValue Convert_RubyToUpb(VALUE ruby_val, const char *name,
TypeInfo type_info, upb_Arena *arena);
// Converts |upb_val| to a Ruby VALUE according to |type_info|. This may involve
// creating a Ruby wrapper object.
@ -56,17 +56,20 @@ upb_msgval Convert_RubyToUpb(VALUE ruby_val, const char *name,
// The |arena| parameter indicates the arena that owns the lifetime of
// |upb_val|. Any Ruby wrapper object that is created will reference |arena|
// and ensure it outlives the wrapper.
VALUE Convert_UpbToRuby(upb_msgval upb_val, TypeInfo type_info, VALUE arena);
VALUE Convert_UpbToRuby(upb_MessageValue upb_val, TypeInfo type_info,
VALUE arena);
// Creates a deep copy of |msgval| in |arena|.
upb_msgval Msgval_DeepCopy(upb_msgval msgval, TypeInfo type_info,
upb_arena *arena);
upb_MessageValue Msgval_DeepCopy(upb_MessageValue msgval, TypeInfo type_info,
upb_Arena *arena);
// Returns true if |val1| and |val2| are equal. Their type is given by
// |type_info|.
bool Msgval_IsEqual(upb_msgval val1, upb_msgval val2, TypeInfo type_info);
bool Msgval_IsEqual(upb_MessageValue val1, upb_MessageValue val2,
TypeInfo type_info);
// Returns a hash value for the given upb_msgval.
uint64_t Msgval_GetHash(upb_msgval val, TypeInfo type_info, uint64_t seed);
// Returns a hash value for the given upb_MessageValue.
uint64_t Msgval_GetHash(upb_MessageValue val, TypeInfo type_info,
uint64_t seed);
#endif // RUBY_PROTOBUF_CONVERT_H_

@ -41,11 +41,11 @@
// instances.
// -----------------------------------------------------------------------------
static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def);
static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def);
static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def);
static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def);
static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def);
static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_MessageDef* def);
static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_EnumDef* def);
static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_FieldDef* def);
static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_FileDef* def);
static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_OneofDef* def);
// A distinct object that is not accessible from Ruby. We use this as a
// constructor argument to enforce that certain objects cannot be created from
@ -74,7 +74,7 @@ static VALUE rb_str_maybe_null(const char* s) {
typedef struct {
VALUE def_to_descriptor; // Hash table of def* -> Ruby descriptor.
upb_symtab* symtab;
upb_DefPool* symtab;
} DescriptorPool;
VALUE cDescriptorPool = Qnil;
@ -90,14 +90,14 @@ static void DescriptorPool_mark(void* _self) {
static void DescriptorPool_free(void* _self) {
DescriptorPool* self = _self;
upb_symtab_free(self->symtab);
upb_DefPool_Free(self->symtab);
xfree(self);
}
static const rb_data_type_t DescriptorPool_type = {
"Google::Protobuf::DescriptorPool",
{DescriptorPool_mark, DescriptorPool_free, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
"Google::Protobuf::DescriptorPool",
{DescriptorPool_mark, DescriptorPool_free, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
};
static DescriptorPool* ruby_to_DescriptorPool(VALUE val) {
@ -107,8 +107,8 @@ static DescriptorPool* ruby_to_DescriptorPool(VALUE val) {
}
// Exposed to other modules in defs.h.
const upb_symtab *DescriptorPool_GetSymtab(VALUE desc_pool_rb) {
DescriptorPool *pool = ruby_to_DescriptorPool(desc_pool_rb);
const upb_DefPool* DescriptorPool_GetSymtab(VALUE desc_pool_rb) {
DescriptorPool* pool = ruby_to_DescriptorPool(desc_pool_rb);
return pool->symtab;
}
@ -126,7 +126,7 @@ static VALUE DescriptorPool_alloc(VALUE klass) {
ret = TypedData_Wrap_Struct(klass, &DescriptorPool_type, self);
self->def_to_descriptor = rb_hash_new();
self->symtab = upb_symtab_new();
self->symtab = upb_DefPool_New();
ObjectCache_Add(self->symtab, ret);
return ret;
@ -143,7 +143,7 @@ VALUE DescriptorPool_add_serialized_file(VALUE _self,
DescriptorPool* self = ruby_to_DescriptorPool(_self);
Check_Type(serialized_file_proto, T_STRING);
VALUE arena_rb = Arena_new();
upb_arena *arena = Arena_get(arena_rb);
upb_Arena* arena = Arena_get(arena_rb);
google_protobuf_FileDescriptorProto* file_proto =
google_protobuf_FileDescriptorProto_parse(
RSTRING_PTR(serialized_file_proto),
@ -151,13 +151,13 @@ VALUE DescriptorPool_add_serialized_file(VALUE _self,
if (!file_proto) {
rb_raise(rb_eArgError, "Unable to parse FileDescriptorProto");
}
upb_status status;
upb_status_clear(&status);
const upb_filedef* filedef =
upb_symtab_addfile(self->symtab, file_proto, &status);
upb_Status status;
upb_Status_Clear(&status);
const upb_FileDef* filedef =
upb_DefPool_AddFile(self->symtab, file_proto, &status);
if (!filedef) {
rb_raise(cTypeError, "Unable to build file to DescriptorPool: %s",
upb_status_errmsg(&status));
upb_Status_ErrorMessage(&status));
}
return get_filedef_obj(_self, filedef);
}
@ -172,15 +172,15 @@ VALUE DescriptorPool_add_serialized_file(VALUE _self,
static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
DescriptorPool* self = ruby_to_DescriptorPool(_self);
const char* name_str = get_str(name);
const upb_msgdef* msgdef;
const upb_enumdef* enumdef;
const upb_MessageDef* msgdef;
const upb_EnumDef* enumdef;
msgdef = upb_symtab_lookupmsg(self->symtab, name_str);
msgdef = upb_DefPool_FindMessageByName(self->symtab, name_str);
if (msgdef) {
return get_msgdef_obj(_self, msgdef);
}
enumdef = upb_symtab_lookupenum(self->symtab, name_str);
enumdef = upb_DefPool_FindEnumByName(self->symtab, name_str);
if (enumdef) {
return get_enumdef_obj(_self, enumdef);
}
@ -202,8 +202,7 @@ static VALUE DescriptorPool_generated_pool(VALUE _self) {
}
static void DescriptorPool_register(VALUE module) {
VALUE klass = rb_define_class_under(
module, "DescriptorPool", rb_cObject);
VALUE klass = rb_define_class_under(module, "DescriptorPool", rb_cObject);
rb_define_alloc_func(klass, DescriptorPool_alloc);
rb_define_method(klass, "add_serialized_file",
DescriptorPool_add_serialized_file, 1);
@ -222,7 +221,7 @@ static void DescriptorPool_register(VALUE module) {
// -----------------------------------------------------------------------------
typedef struct {
const upb_msgdef* msgdef;
const upb_MessageDef* msgdef;
VALUE klass;
VALUE descriptor_pool;
} Descriptor;
@ -236,9 +235,9 @@ static void Descriptor_mark(void* _self) {
}
static const rb_data_type_t Descriptor_type = {
"Google::Protobuf::Descriptor",
{Descriptor_mark, RUBY_DEFAULT_FREE, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
"Google::Protobuf::Descriptor",
{Descriptor_mark, RUBY_DEFAULT_FREE, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
};
static Descriptor* ruby_to_Descriptor(VALUE val) {
@ -281,7 +280,7 @@ static VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
}
self->descriptor_pool = descriptor_pool;
self->msgdef = (const upb_msgdef*)NUM2ULL(ptr);
self->msgdef = (const upb_MessageDef*)NUM2ULL(ptr);
return Qnil;
}
@ -294,7 +293,8 @@ static VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
*/
static VALUE Descriptor_file_descriptor(VALUE _self) {
Descriptor* self = ruby_to_Descriptor(_self);
return get_filedef_obj(self->descriptor_pool, upb_msgdef_file(self->msgdef));
return get_filedef_obj(self->descriptor_pool,
upb_MessageDef_File(self->msgdef));
}
/*
@ -306,7 +306,7 @@ static VALUE Descriptor_file_descriptor(VALUE _self) {
*/
static VALUE Descriptor_name(VALUE _self) {
Descriptor* self = ruby_to_Descriptor(_self);
return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef));
return rb_str_maybe_null(upb_MessageDef_FullName(self->msgdef));
}
/*
@ -318,11 +318,9 @@ static VALUE Descriptor_name(VALUE _self) {
static VALUE Descriptor_each(VALUE _self) {
Descriptor* self = ruby_to_Descriptor(_self);
upb_msg_field_iter it;
for (upb_msg_field_begin(&it, self->msgdef);
!upb_msg_field_done(&it);
upb_msg_field_next(&it)) {
const upb_fielddef* field = upb_msg_iter_field(&it);
int n = upb_MessageDef_FieldCount(self->msgdef);
for (int i = 0; i < n; i++) {
const upb_FieldDef* field = upb_MessageDef_Field(self->msgdef, i);
VALUE obj = get_fielddef_obj(self->descriptor_pool, field);
rb_yield(obj);
}
@ -339,7 +337,7 @@ static VALUE Descriptor_each(VALUE _self) {
static VALUE Descriptor_lookup(VALUE _self, VALUE name) {
Descriptor* self = ruby_to_Descriptor(_self);
const char* s = get_str(name);
const upb_fielddef* field = upb_msgdef_ntofz(self->msgdef, s);
const upb_FieldDef* field = upb_MessageDef_FindFieldByName(self->msgdef, s);
if (field == NULL) {
return Qnil;
}
@ -356,11 +354,9 @@ static VALUE Descriptor_lookup(VALUE _self, VALUE name) {
static VALUE Descriptor_each_oneof(VALUE _self) {
Descriptor* self = ruby_to_Descriptor(_self);
upb_msg_oneof_iter it;
for (upb_msg_oneof_begin(&it, self->msgdef);
!upb_msg_oneof_done(&it);
upb_msg_oneof_next(&it)) {
const upb_oneofdef* oneof = upb_msg_iter_oneof(&it);
int n = upb_MessageDef_OneofCount(self->msgdef);
for (int i = 0; i < n; i++) {
const upb_OneofDef* oneof = upb_MessageDef_Oneof(self->msgdef, i);
VALUE obj = get_oneofdef_obj(self->descriptor_pool, oneof);
rb_yield(obj);
}
@ -377,7 +373,7 @@ static VALUE Descriptor_each_oneof(VALUE _self) {
static VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
Descriptor* self = ruby_to_Descriptor(_self);
const char* s = get_str(name);
const upb_oneofdef* oneof = upb_msgdef_ntooz(self->msgdef, s);
const upb_OneofDef* oneof = upb_MessageDef_FindOneofByName(self->msgdef, s);
if (oneof == NULL) {
return Qnil;
}
@ -399,8 +395,7 @@ static VALUE Descriptor_msgclass(VALUE _self) {
}
static void Descriptor_register(VALUE module) {
VALUE klass = rb_define_class_under(
module, "Descriptor", rb_cObject);
VALUE klass = rb_define_class_under(module, "Descriptor", rb_cObject);
rb_define_alloc_func(klass, Descriptor_alloc);
rb_define_method(klass, "initialize", Descriptor_initialize, 3);
rb_define_method(klass, "each", Descriptor_each, 0);
@ -420,8 +415,8 @@ static void Descriptor_register(VALUE module) {
// -----------------------------------------------------------------------------
typedef struct {
const upb_filedef* filedef;
VALUE descriptor_pool; // Owns the upb_filedef.
const upb_FileDef* filedef;
VALUE descriptor_pool; // Owns the upb_FileDef.
} FileDescriptor;
static VALUE cFileDescriptor = Qnil;
@ -432,9 +427,9 @@ static void FileDescriptor_mark(void* _self) {
}
static const rb_data_type_t FileDescriptor_type = {
"Google::Protobuf::FileDescriptor",
{FileDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
"Google::Protobuf::FileDescriptor",
{FileDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
};
static FileDescriptor* ruby_to_FileDescriptor(VALUE val) {
@ -459,7 +454,7 @@ static VALUE FileDescriptor_alloc(VALUE klass) {
* to a builder.
*/
static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
VALUE descriptor_pool, VALUE ptr) {
VALUE descriptor_pool, VALUE ptr) {
FileDescriptor* self = ruby_to_FileDescriptor(_self);
if (cookie != c_only_cookie) {
@ -468,7 +463,7 @@ static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
}
self->descriptor_pool = descriptor_pool;
self->filedef = (const upb_filedef*)NUM2ULL(ptr);
self->filedef = (const upb_FileDef*)NUM2ULL(ptr);
return Qnil;
}
@ -481,7 +476,7 @@ static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
*/
static VALUE FileDescriptor_name(VALUE _self) {
FileDescriptor* self = ruby_to_FileDescriptor(_self);
const char* name = upb_filedef_name(self->filedef);
const char* name = upb_FileDef_Name(self->filedef);
return name == NULL ? Qnil : rb_str_new2(name);
}
@ -497,16 +492,18 @@ static VALUE FileDescriptor_name(VALUE _self) {
static VALUE FileDescriptor_syntax(VALUE _self) {
FileDescriptor* self = ruby_to_FileDescriptor(_self);
switch (upb_filedef_syntax(self->filedef)) {
case UPB_SYNTAX_PROTO3: return ID2SYM(rb_intern("proto3"));
case UPB_SYNTAX_PROTO2: return ID2SYM(rb_intern("proto2"));
default: return Qnil;
switch (upb_FileDef_Syntax(self->filedef)) {
case kUpb_Syntax_Proto3:
return ID2SYM(rb_intern("proto3"));
case kUpb_Syntax_Proto2:
return ID2SYM(rb_intern("proto2"));
default:
return Qnil;
}
}
static void FileDescriptor_register(VALUE module) {
VALUE klass = rb_define_class_under(
module, "FileDescriptor", rb_cObject);
VALUE klass = rb_define_class_under(module, "FileDescriptor", rb_cObject);
rb_define_alloc_func(klass, FileDescriptor_alloc);
rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
rb_define_method(klass, "name", FileDescriptor_name, 0);
@ -520,8 +517,8 @@ static void FileDescriptor_register(VALUE module) {
// -----------------------------------------------------------------------------
typedef struct {
const upb_fielddef* fielddef;
VALUE descriptor_pool; // Owns the upb_fielddef.
const upb_FieldDef* fielddef;
VALUE descriptor_pool; // Owns the upb_FieldDef.
} FieldDescriptor;
static VALUE cFieldDescriptor = Qnil;
@ -532,9 +529,9 @@ static void FieldDescriptor_mark(void* _self) {
}
static const rb_data_type_t FieldDescriptor_type = {
"Google::Protobuf::FieldDescriptor",
{FieldDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
"Google::Protobuf::FieldDescriptor",
{FieldDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
};
static FieldDescriptor* ruby_to_FieldDescriptor(VALUE val) {
@ -573,7 +570,7 @@ static VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
}
self->descriptor_pool = descriptor_pool;
self->fielddef = (const upb_fielddef*)NUM2ULL(ptr);
self->fielddef = (const upb_FieldDef*)NUM2ULL(ptr);
return Qnil;
}
@ -586,31 +583,31 @@ static VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
*/
static VALUE FieldDescriptor_name(VALUE _self) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
return rb_str_maybe_null(upb_fielddef_name(self->fielddef));
return rb_str_maybe_null(upb_FieldDef_Name(self->fielddef));
}
// Non-static, exposed to other .c files.
upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
upb_CType ruby_to_fieldtype(VALUE type) {
if (TYPE(type) != T_SYMBOL) {
rb_raise(rb_eArgError, "Expected symbol for field type.");
}
#define CONVERT(upb, ruby) \
if (SYM2ID(type) == rb_intern( # ruby )) { \
return UPB_TYPE_ ## upb; \
#define CONVERT(upb, ruby) \
if (SYM2ID(type) == rb_intern(#ruby)) { \
return kUpb_CType_##upb; \
}
CONVERT(FLOAT, float);
CONVERT(DOUBLE, double);
CONVERT(BOOL, bool);
CONVERT(STRING, string);
CONVERT(BYTES, bytes);
CONVERT(MESSAGE, message);
CONVERT(ENUM, enum);
CONVERT(INT32, int32);
CONVERT(INT64, int64);
CONVERT(UINT32, uint32);
CONVERT(UINT64, uint64);
CONVERT(Float, float);
CONVERT(Double, double);
CONVERT(Bool, bool);
CONVERT(String, string);
CONVERT(Bytes, bytes);
CONVERT(Message, message);
CONVERT(Enum, enum);
CONVERT(Int32, int32);
CONVERT(Int64, int64);
CONVERT(UInt32, uint32);
CONVERT(UInt64, uint64);
#undef CONVERT
@ -618,28 +615,29 @@ upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
return 0;
}
static VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
static VALUE descriptortype_to_ruby(upb_FieldType type) {
switch (type) {
#define CONVERT(upb, ruby) \
case UPB_DESCRIPTOR_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
CONVERT(FLOAT, float);
CONVERT(DOUBLE, double);
CONVERT(BOOL, bool);
CONVERT(STRING, string);
CONVERT(BYTES, bytes);
CONVERT(MESSAGE, message);
CONVERT(GROUP, group);
CONVERT(ENUM, enum);
CONVERT(INT32, int32);
CONVERT(INT64, int64);
CONVERT(UINT32, uint32);
CONVERT(UINT64, uint64);
CONVERT(SINT32, sint32);
CONVERT(SINT64, sint64);
CONVERT(FIXED32, fixed32);
CONVERT(FIXED64, fixed64);
CONVERT(SFIXED32, sfixed32);
CONVERT(SFIXED64, sfixed64);
#define CONVERT(upb, ruby) \
case kUpb_FieldType_##upb: \
return ID2SYM(rb_intern(#ruby));
CONVERT(Float, float);
CONVERT(Double, double);
CONVERT(Bool, bool);
CONVERT(String, string);
CONVERT(Bytes, bytes);
CONVERT(Message, message);
CONVERT(Group, group);
CONVERT(Enum, enum);
CONVERT(Int32, int32);
CONVERT(Int64, int64);
CONVERT(UInt32, uint32);
CONVERT(UInt64, uint64);
CONVERT(SInt32, sint32);
CONVERT(SInt64, sint64);
CONVERT(Fixed32, fixed32);
CONVERT(Fixed64, fixed64);
CONVERT(SFixed32, sfixed32);
CONVERT(SFixed64, sfixed64);
#undef CONVERT
}
return Qnil;
@ -657,7 +655,7 @@ static VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
*/
static VALUE FieldDescriptor__type(VALUE _self) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
return descriptortype_to_ruby(upb_fielddef_descriptortype(self->fielddef));
return descriptortype_to_ruby(upb_FieldDef_Type(self->fielddef));
}
/*
@ -668,17 +666,16 @@ static VALUE FieldDescriptor__type(VALUE _self) {
*/
static VALUE FieldDescriptor_default(VALUE _self) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
const upb_fielddef *f = self->fielddef;
upb_msgval default_val = {0};
if (upb_fielddef_issubmsg(f)) {
const upb_FieldDef* f = self->fielddef;
upb_MessageValue default_val = {0};
if (upb_FieldDef_IsSubMessage(f)) {
return Qnil;
} else if (!upb_fielddef_isseq(f)) {
default_val = upb_fielddef_default(f);
} else if (!upb_FieldDef_IsRepeated(f)) {
default_val = upb_FieldDef_Default(f);
}
return Convert_UpbToRuby(default_val, TypeInfo_get(self->fielddef), Qnil);
}
/*
* call-seq:
* FieldDescriptor.json_name => json_name
@ -687,8 +684,8 @@ static VALUE FieldDescriptor_default(VALUE _self) {
*/
static VALUE FieldDescriptor_json_name(VALUE _self) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
const upb_fielddef *f = self->fielddef;
const char *json_name = upb_fielddef_jsonname(f);
const upb_FieldDef* f = self->fielddef;
const char* json_name = upb_FieldDef_JsonName(f);
return rb_str_new2(json_name);
}
@ -703,13 +700,14 @@ static VALUE FieldDescriptor_json_name(VALUE _self) {
*/
static VALUE FieldDescriptor_label(VALUE _self) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
switch (upb_fielddef_label(self->fielddef)) {
#define CONVERT(upb, ruby) \
case UPB_LABEL_ ## upb : return ID2SYM(rb_intern( # ruby ));
switch (upb_FieldDef_Label(self->fielddef)) {
#define CONVERT(upb, ruby) \
case kUpb_Label_##upb: \
return ID2SYM(rb_intern(#ruby));
CONVERT(OPTIONAL, optional);
CONVERT(REQUIRED, required);
CONVERT(REPEATED, repeated);
CONVERT(Optional, optional);
CONVERT(Required, required);
CONVERT(Repeated, repeated);
#undef CONVERT
}
@ -725,7 +723,7 @@ static VALUE FieldDescriptor_label(VALUE _self) {
*/
static VALUE FieldDescriptor_number(VALUE _self) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
return INT2NUM(upb_fielddef_number(self->fielddef));
return INT2NUM(upb_FieldDef_Number(self->fielddef));
}
/*
@ -739,13 +737,13 @@ static VALUE FieldDescriptor_number(VALUE _self) {
*/
static VALUE FieldDescriptor_submsg_name(VALUE _self) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
switch (upb_fielddef_type(self->fielddef)) {
case UPB_TYPE_ENUM:
switch (upb_FieldDef_CType(self->fielddef)) {
case kUpb_CType_Enum:
return rb_str_new2(
upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef)));
case UPB_TYPE_MESSAGE:
upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(self->fielddef)));
case kUpb_CType_Message:
return rb_str_new2(
upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef)));
upb_MessageDef_FullName(upb_FieldDef_MessageSubDef(self->fielddef)));
default:
return Qnil;
}
@ -762,13 +760,13 @@ static VALUE FieldDescriptor_submsg_name(VALUE _self) {
*/
static VALUE FieldDescriptor_subtype(VALUE _self) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
switch (upb_fielddef_type(self->fielddef)) {
case UPB_TYPE_ENUM:
switch (upb_FieldDef_CType(self->fielddef)) {
case kUpb_CType_Enum:
return get_enumdef_obj(self->descriptor_pool,
upb_fielddef_enumsubdef(self->fielddef));
case UPB_TYPE_MESSAGE:
upb_FieldDef_EnumSubDef(self->fielddef));
case kUpb_CType_Message:
return get_msgdef_obj(self->descriptor_pool,
upb_fielddef_msgsubdef(self->fielddef));
upb_FieldDef_MessageSubDef(self->fielddef));
default:
return Qnil;
}
@ -783,11 +781,11 @@ static VALUE FieldDescriptor_subtype(VALUE _self) {
*/
static VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
const upb_msgdef *m;
const upb_MessageDef* m;
Message_Get(msg_rb, &m);
if (m != upb_fielddef_containingtype(self->fielddef)) {
if (m != upb_FieldDef_ContainingType(self->fielddef)) {
rb_raise(cTypeError, "get method called on wrong message type");
}
@ -803,16 +801,16 @@ static VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
*/
static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
const upb_msgdef *m;
const upb_msgdef *msg = Message_Get(msg_rb, &m);
const upb_MessageDef* m;
const upb_MessageDef* msg = Message_Get(msg_rb, &m);
if (m != upb_fielddef_containingtype(self->fielddef)) {
if (m != upb_FieldDef_ContainingType(self->fielddef)) {
rb_raise(cTypeError, "has method called on wrong message type");
} else if (!upb_fielddef_haspresence(self->fielddef)) {
} else if (!upb_FieldDef_HasPresence(self->fielddef)) {
rb_raise(rb_eArgError, "does not track presence");
}
return upb_msg_has(msg, self->fielddef) ? Qtrue : Qfalse;
return upb_Message_Has(msg, self->fielddef) ? Qtrue : Qfalse;
}
/*
@ -823,14 +821,14 @@ static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
*/
static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
const upb_msgdef *m;
upb_msgdef *msg = Message_GetMutable(msg_rb, &m);
const upb_MessageDef* m;
upb_MessageDef* msg = Message_GetMutable(msg_rb, &m);
if (m != upb_fielddef_containingtype(self->fielddef)) {
if (m != upb_FieldDef_ContainingType(self->fielddef)) {
rb_raise(cTypeError, "has method called on wrong message type");
}
upb_msg_clearfield(msg, self->fielddef);
upb_Message_ClearField(msg, self->fielddef);
return Qnil;
}
@ -844,24 +842,23 @@ static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
*/
static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
const upb_msgdef *m;
upb_msgdef *msg = Message_GetMutable(msg_rb, &m);
upb_arena *arena = Arena_get(Message_GetArena(msg_rb));
upb_msgval msgval;
const upb_MessageDef* m;
upb_MessageDef* msg = Message_GetMutable(msg_rb, &m);
upb_Arena* arena = Arena_get(Message_GetArena(msg_rb));
upb_MessageValue msgval;
if (m != upb_fielddef_containingtype(self->fielddef)) {
if (m != upb_FieldDef_ContainingType(self->fielddef)) {
rb_raise(cTypeError, "set method called on wrong message type");
}
msgval = Convert_RubyToUpb(value, upb_fielddef_name(self->fielddef),
msgval = Convert_RubyToUpb(value, upb_FieldDef_Name(self->fielddef),
TypeInfo_get(self->fielddef), arena);
upb_msg_set(msg, self->fielddef, msgval, arena);
upb_Message_Set(msg, self->fielddef, msgval, arena);
return Qnil;
}
static void FieldDescriptor_register(VALUE module) {
VALUE klass = rb_define_class_under(
module, "FieldDescriptor", rb_cObject);
VALUE klass = rb_define_class_under(module, "FieldDescriptor", rb_cObject);
rb_define_alloc_func(klass, FieldDescriptor_alloc);
rb_define_method(klass, "initialize", FieldDescriptor_initialize, 3);
rb_define_method(klass, "name", FieldDescriptor_name, 0);
@ -885,8 +882,8 @@ static void FieldDescriptor_register(VALUE module) {
// -----------------------------------------------------------------------------
typedef struct {
const upb_oneofdef* oneofdef;
VALUE descriptor_pool; // Owns the upb_oneofdef.
const upb_OneofDef* oneofdef;
VALUE descriptor_pool; // Owns the upb_OneofDef.
} OneofDescriptor;
static VALUE cOneofDescriptor = Qnil;
@ -930,7 +927,7 @@ static VALUE OneofDescriptor_alloc(VALUE klass) {
* Creates a descriptor wrapper object. May only be called from C.
*/
static VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
VALUE descriptor_pool, VALUE ptr) {
VALUE descriptor_pool, VALUE ptr) {
OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
if (cookie != c_only_cookie) {
@ -939,7 +936,7 @@ static VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
}
self->descriptor_pool = descriptor_pool;
self->oneofdef = (const upb_oneofdef*)NUM2ULL(ptr);
self->oneofdef = (const upb_OneofDef*)NUM2ULL(ptr);
return Qnil;
}
@ -952,7 +949,7 @@ static VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
*/
static VALUE OneofDescriptor_name(VALUE _self) {
OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
return rb_str_maybe_null(upb_OneofDef_Name(self->oneofdef));
}
/*
@ -963,11 +960,10 @@ static VALUE OneofDescriptor_name(VALUE _self) {
*/
static VALUE OneofDescriptor_each(VALUE _self) {
OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
upb_oneof_iter it;
for (upb_oneof_begin(&it, self->oneofdef);
!upb_oneof_done(&it);
upb_oneof_next(&it)) {
const upb_fielddef* f = upb_oneof_iter_field(&it);
int n = upb_OneofDef_FieldCount(self->oneofdef);
for (int i = 0; i < n; i++) {
const upb_FieldDef* f = upb_OneofDef_Field(self->oneofdef, i);
VALUE obj = get_fielddef_obj(self->descriptor_pool, f);
rb_yield(obj);
}
@ -975,8 +971,7 @@ static VALUE OneofDescriptor_each(VALUE _self) {
}
static void OneofDescriptor_register(VALUE module) {
VALUE klass = rb_define_class_under(
module, "OneofDescriptor", rb_cObject);
VALUE klass = rb_define_class_under(module, "OneofDescriptor", rb_cObject);
rb_define_alloc_func(klass, OneofDescriptor_alloc);
rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
rb_define_method(klass, "name", OneofDescriptor_name, 0);
@ -991,9 +986,9 @@ static void OneofDescriptor_register(VALUE module) {
// -----------------------------------------------------------------------------
typedef struct {
const upb_enumdef* enumdef;
VALUE module; // begins as nil
VALUE descriptor_pool; // Owns the upb_enumdef.
const upb_EnumDef* enumdef;
VALUE module; // begins as nil
VALUE descriptor_pool; // Owns the upb_EnumDef.
} EnumDescriptor;
static VALUE cEnumDescriptor = Qnil;
@ -1005,9 +1000,9 @@ static void EnumDescriptor_mark(void* _self) {
}
static const rb_data_type_t EnumDescriptor_type = {
"Google::Protobuf::EnumDescriptor",
{EnumDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
"Google::Protobuf::EnumDescriptor",
{EnumDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
};
static EnumDescriptor* ruby_to_EnumDescriptor(VALUE val) {
@ -1026,8 +1021,8 @@ static VALUE EnumDescriptor_alloc(VALUE klass) {
}
// Exposed to other modules in defs.h.
const upb_enumdef *EnumDescriptor_GetEnumDef(VALUE enum_desc_rb) {
EnumDescriptor *desc = ruby_to_EnumDescriptor(enum_desc_rb);
const upb_EnumDef* EnumDescriptor_GetEnumDef(VALUE enum_desc_rb) {
EnumDescriptor* desc = ruby_to_EnumDescriptor(enum_desc_rb);
return desc->enumdef;
}
@ -1047,7 +1042,7 @@ static VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
}
self->descriptor_pool = descriptor_pool;
self->enumdef = (const upb_enumdef*)NUM2ULL(ptr);
self->enumdef = (const upb_EnumDef*)NUM2ULL(ptr);
return Qnil;
}
@ -1061,7 +1056,7 @@ static VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
static VALUE EnumDescriptor_file_descriptor(VALUE _self) {
EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
return get_filedef_obj(self->descriptor_pool,
upb_enumdef_file(self->enumdef));
upb_EnumDef_File(self->enumdef));
}
/*
@ -1072,7 +1067,7 @@ static VALUE EnumDescriptor_file_descriptor(VALUE _self) {
*/
static VALUE EnumDescriptor_name(VALUE _self) {
EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef));
return rb_str_maybe_null(upb_EnumDef_FullName(self->enumdef));
}
/*
@ -1084,10 +1079,11 @@ static VALUE EnumDescriptor_name(VALUE _self) {
*/
static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
const char* name_str= rb_id2name(SYM2ID(name));
int32_t val = 0;
if (upb_enumdef_ntoiz(self->enumdef, name_str, &val)) {
return INT2NUM(val);
const char* name_str = rb_id2name(SYM2ID(name));
const upb_EnumValueDef *ev =
upb_EnumDef_FindValueByName(self->enumdef, name_str);
if (ev) {
return INT2NUM(upb_EnumValueDef_Number(ev));
} else {
return Qnil;
}
@ -1103,9 +1099,9 @@ static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
static VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
int32_t val = NUM2INT(number);
const char* name = upb_enumdef_iton(self->enumdef, val);
if (name != NULL) {
return ID2SYM(rb_intern(name));
const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(self->enumdef, val);
if (ev) {
return ID2SYM(rb_intern(upb_EnumValueDef_Name(ev)));
} else {
return Qnil;
}
@ -1121,12 +1117,11 @@ static VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
static VALUE EnumDescriptor_each(VALUE _self) {
EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
upb_enum_iter it;
for (upb_enum_begin(&it, self->enumdef);
!upb_enum_done(&it);
upb_enum_next(&it)) {
VALUE key = ID2SYM(rb_intern(upb_enum_iter_name(&it)));
VALUE number = INT2NUM(upb_enum_iter_number(&it));
int n = upb_EnumDef_ValueCount(self->enumdef);
for (int i = 0; i < n; i++) {
const upb_EnumValueDef* ev = upb_EnumDef_Value(self->enumdef, i);
VALUE key = ID2SYM(rb_intern(upb_EnumValueDef_Name(ev)));
VALUE number = INT2NUM(upb_EnumValueDef_Number(ev));
rb_yield_values(2, key, number);
}
@ -1148,8 +1143,7 @@ static VALUE EnumDescriptor_enummodule(VALUE _self) {
}
static void EnumDescriptor_register(VALUE module) {
VALUE klass = rb_define_class_under(
module, "EnumDescriptor", rb_cObject);
VALUE klass = rb_define_class_under(module, "EnumDescriptor", rb_cObject);
rb_define_alloc_func(klass, EnumDescriptor_alloc);
rb_define_method(klass, "initialize", EnumDescriptor_initialize, 3);
rb_define_method(klass, "name", EnumDescriptor_name, 0);
@ -1176,7 +1170,7 @@ static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
if (def == Qnil) {
// Lazily create wrapper object.
VALUE args[3] = { c_only_cookie, _descriptor_pool, key };
VALUE args[3] = {c_only_cookie, _descriptor_pool, key};
def = rb_class_new_instance(3, args, klass);
rb_hash_aset(descriptor_pool->def_to_descriptor, key, def);
}
@ -1184,23 +1178,23 @@ static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
return def;
}
static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def) {
static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_MessageDef* def) {
return get_def_obj(descriptor_pool, def, cDescriptor);
}
static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def) {
static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_EnumDef* def) {
return get_def_obj(descriptor_pool, def, cEnumDescriptor);
}
static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def) {
static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_FieldDef* def) {
return get_def_obj(descriptor_pool, def, cFieldDescriptor);
}
static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def) {
static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_FileDef* def) {
return get_def_obj(descriptor_pool, def, cFileDescriptor);
}
static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def) {
static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_OneofDef* def) {
return get_def_obj(descriptor_pool, def, cOneofDescriptor);
}
@ -1210,8 +1204,8 @@ static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def) {
// Functions exposed to other modules in defs.h.
VALUE Descriptor_DefToClass(const upb_msgdef *m) {
const upb_symtab *symtab = upb_filedef_symtab(upb_msgdef_file(m));
VALUE Descriptor_DefToClass(const upb_MessageDef* m) {
const upb_DefPool* symtab = upb_FileDef_Pool(upb_MessageDef_File(m));
VALUE pool = ObjectCache_Get(symtab);
PBRUBY_ASSERT(pool != Qnil);
VALUE desc_rb = get_msgdef_obj(pool, m);
@ -1219,15 +1213,16 @@ VALUE Descriptor_DefToClass(const upb_msgdef *m) {
return desc->klass;
}
const upb_msgdef *Descriptor_GetMsgDef(VALUE desc_rb) {
const upb_MessageDef* Descriptor_GetMsgDef(VALUE desc_rb) {
const Descriptor* desc = ruby_to_Descriptor(desc_rb);
return desc->msgdef;
}
VALUE TypeInfo_InitArg(int argc, VALUE *argv, int skip_arg) {
VALUE TypeInfo_InitArg(int argc, VALUE* argv, int skip_arg) {
if (argc > skip_arg) {
if (argc > 1 + skip_arg) {
rb_raise(rb_eArgError, "Expected a maximum of %d arguments.", skip_arg + 1);
rb_raise(rb_eArgError, "Expected a maximum of %d arguments.",
skip_arg + 1);
}
return argv[skip_arg];
} else {
@ -1239,7 +1234,7 @@ TypeInfo TypeInfo_FromClass(int argc, VALUE* argv, int skip_arg,
VALUE* type_class, VALUE* init_arg) {
TypeInfo ret = {ruby_to_fieldtype(argv[skip_arg])};
if (ret.type == UPB_TYPE_MESSAGE || ret.type == UPB_TYPE_ENUM) {
if (ret.type == kUpb_CType_Message || ret.type == kUpb_CType_Enum) {
*init_arg = TypeInfo_InitArg(argc, argv, skip_arg + 2);
if (argc < 2 + skip_arg) {
@ -1257,11 +1252,11 @@ TypeInfo TypeInfo_FromClass(int argc, VALUE* argv, int skip_arg,
"class or enum as returned by the DescriptorPool.");
}
if (ret.type == UPB_TYPE_MESSAGE) {
if (ret.type == kUpb_CType_Message) {
ret.def.msgdef = ruby_to_Descriptor(desc)->msgdef;
Message_CheckClass(klass);
} else {
PBRUBY_ASSERT(ret.type == UPB_TYPE_ENUM);
PBRUBY_ASSERT(ret.type == kUpb_CType_Enum);
ret.def.enumdef = ruby_to_EnumDescriptor(desc)->enumdef;
}
} else {

@ -40,9 +40,9 @@
// TypeInfo
// -----------------------------------------------------------------------------
// This bundles a upb_fieldtype_t and msgdef/enumdef when appropriate. This is
// This bundles a upb_CType and msgdef/enumdef when appropriate. This is
// convenient for functions that need type information but cannot necessarily
// assume a upb_fielddef will be available.
// assume a upb_FieldDef will be available.
//
// For example, Google::Protobuf::Map and Google::Protobuf::RepeatedField can
// be constructed with type information alone:
@ -51,21 +51,21 @@
// Google::Protobuf::RepeatedField.new(:message, FooMessage)
typedef struct {
upb_fieldtype_t type;
upb_CType type;
union {
const upb_msgdef* msgdef; // When type == UPB_TYPE_MESSAGE
const upb_enumdef* enumdef; // When type == UPB_TYPE_ENUM
const upb_MessageDef* msgdef; // When type == kUpb_CType_Message
const upb_EnumDef* enumdef; // When type == kUpb_CType_Enum
} def;
} TypeInfo;
static inline TypeInfo TypeInfo_get(const upb_fielddef *f) {
TypeInfo ret = {upb_fielddef_type(f), {NULL}};
static inline TypeInfo TypeInfo_get(const upb_FieldDef* f) {
TypeInfo ret = {upb_FieldDef_CType(f), {NULL}};
switch (ret.type) {
case UPB_TYPE_MESSAGE:
ret.def.msgdef = upb_fielddef_msgsubdef(f);
case kUpb_CType_Message:
ret.def.msgdef = upb_FieldDef_MessageSubDef(f);
break;
case UPB_TYPE_ENUM:
ret.def.enumdef = upb_fielddef_enumsubdef(f);
case kUpb_CType_Enum:
ret.def.enumdef = upb_FieldDef_EnumSubDef(f);
break;
default:
break;
@ -76,9 +76,9 @@ static inline TypeInfo TypeInfo_get(const upb_fielddef *f) {
TypeInfo TypeInfo_FromClass(int argc, VALUE* argv, int skip_arg,
VALUE* type_class, VALUE* init_arg);
static inline TypeInfo TypeInfo_from_type(upb_fieldtype_t type) {
static inline TypeInfo TypeInfo_from_type(upb_CType type) {
TypeInfo ret = {type};
assert(type != UPB_TYPE_MESSAGE && type != UPB_TYPE_ENUM);
assert(type != kUpb_CType_Message && type != kUpb_CType_Enum);
return ret;
}
@ -86,17 +86,17 @@ static inline TypeInfo TypeInfo_from_type(upb_fieldtype_t type) {
// Other utilities
// -----------------------------------------------------------------------------
VALUE Descriptor_DefToClass(const upb_msgdef *m);
VALUE Descriptor_DefToClass(const upb_MessageDef* m);
// Returns the underlying msgdef, enumdef, or symtab (respectively) for the
// given Descriptor, EnumDescriptor, or DescriptorPool Ruby object.
const upb_enumdef *EnumDescriptor_GetEnumDef(VALUE enum_desc_rb);
const upb_symtab *DescriptorPool_GetSymtab(VALUE desc_pool_rb);
const upb_msgdef *Descriptor_GetMsgDef(VALUE desc_rb);
const upb_EnumDef* EnumDescriptor_GetEnumDef(VALUE enum_desc_rb);
const upb_DefPool* DescriptorPool_GetSymtab(VALUE desc_pool_rb);
const upb_MessageDef* Descriptor_GetMsgDef(VALUE desc_rb);
// Returns a upb field type for the given Ruby symbol
// (eg. :float => UPB_TYPE_FLOAT).
upb_fieldtype_t ruby_to_fieldtype(VALUE type);
// (eg. :float => kUpb_CType_Float).
upb_CType ruby_to_fieldtype(VALUE type);
// The singleton generated pool (a DescriptorPool object).
extern VALUE generated_pool;

@ -2,6 +2,10 @@
require 'mkmf'
ext_name = "google/protobuf_c"
dir_config(ext_name)
if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/
$CFLAGS += " -std=gnu99 -O3 -DNDEBUG -fvisibility=hidden -Wall -Wsign-compare -Wno-declaration-after-statement"
else
@ -14,7 +18,11 @@ if RUBY_PLATFORM =~ /linux/
$LDFLAGS += " -Wl,-wrap,memcpy"
end
$objs = ["protobuf.o", "convert.o", "defs.o", "message.o",
"repeated_field.o", "map.o", "ruby-upb.o", "wrap_memcpy.o"]
$VPATH << "$(srcdir)/third_party/utf8_range"
$INCFLAGS << "$(srcdir)/third_party/utf8_range"
$srcs = ["protobuf.c", "convert.c", "defs.c", "message.c",
"repeated_field.c", "map.c", "ruby-upb.c", "wrap_memcpy.c",
"utf8_range.c"]
create_makefile("google/protobuf_c")
create_makefile(ext_name)

@ -34,7 +34,7 @@
#include "protobuf.h"
// -----------------------------------------------------------------------------
// Basic map operations on top of upb_map.
// Basic map operations on top of upb_Map.
//
// Note that we roll our own `Map` container here because, as for
// `RepeatedField`, we want a strongly-typed container. This is so that any user
@ -48,8 +48,8 @@
// -----------------------------------------------------------------------------
typedef struct {
const upb_map *map; // Can convert to mutable when non-frozen.
upb_fieldtype_t key_type;
const upb_Map* map; // Can convert to mutable when non-frozen.
upb_CType key_type;
TypeInfo value_type_info;
VALUE value_type_class;
VALUE arena;
@ -62,9 +62,9 @@ static void Map_mark(void* _self) {
}
const rb_data_type_t Map_type = {
"Google::Protobuf::Map",
{ Map_mark, RUBY_DEFAULT_FREE, NULL },
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
"Google::Protobuf::Map",
{Map_mark, RUBY_DEFAULT_FREE, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
};
VALUE cMap;
@ -84,8 +84,8 @@ static VALUE Map_alloc(VALUE klass) {
return TypedData_Wrap_Struct(klass, &Map_type, self);
}
VALUE Map_GetRubyWrapper(upb_map* map, upb_fieldtype_t key_type,
TypeInfo value_type, VALUE arena) {
VALUE Map_GetRubyWrapper(upb_Map* map, upb_CType key_type, TypeInfo value_type,
VALUE arena) {
PBRUBY_ASSERT(map);
VALUE val = ObjectCache_Get(map);
@ -99,8 +99,8 @@ VALUE Map_GetRubyWrapper(upb_map* map, upb_fieldtype_t key_type,
self->arena = arena;
self->key_type = key_type;
self->value_type_info = value_type;
if (self->value_type_info.type == UPB_TYPE_MESSAGE) {
const upb_msgdef *val_m = self->value_type_info.def.msgdef;
if (self->value_type_info.type == kUpb_CType_Message) {
const upb_MessageDef* val_m = self->value_type_info.def.msgdef;
self->value_type_class = Descriptor_DefToClass(val_m);
}
}
@ -108,9 +108,9 @@ VALUE Map_GetRubyWrapper(upb_map* map, upb_fieldtype_t key_type,
return val;
}
static VALUE Map_new_this_type(Map *from) {
static VALUE Map_new_this_type(Map* from) {
VALUE arena_rb = Arena_new();
upb_map* map = upb_map_new(Arena_get(arena_rb), from->key_type,
upb_Map* map = upb_Map_New(Arena_get(arena_rb), from->key_type,
from->value_type_info.type);
VALUE ret =
Map_GetRubyWrapper(map, from->key_type, from->value_type_info, arena_rb);
@ -125,22 +125,22 @@ static TypeInfo Map_keyinfo(Map* self) {
return ret;
}
static upb_map *Map_GetMutable(VALUE _self) {
static upb_Map* Map_GetMutable(VALUE _self) {
rb_check_frozen(_self);
return (upb_map*)ruby_to_Map(_self)->map;
return (upb_Map*)ruby_to_Map(_self)->map;
}
VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type,
VALUE Map_CreateHash(const upb_Map* map, upb_CType key_type,
TypeInfo val_info) {
VALUE hash = rb_hash_new();
size_t iter = UPB_MAP_BEGIN;
size_t iter = kUpb_Map_Begin;
TypeInfo key_info = TypeInfo_from_type(key_type);
if (!map) return hash;
while (upb_mapiter_next(map, &iter)) {
upb_msgval key = upb_mapiter_key(map, iter);
upb_msgval val = upb_mapiter_value(map, iter);
while (upb_MapIterator_Next(map, &iter)) {
upb_MessageValue key = upb_MapIterator_Key(map, iter);
upb_MessageValue val = upb_MapIterator_Value(map, iter);
VALUE key_val = Convert_UpbToRuby(key, key_info, Qnil);
VALUE val_val = Scalar_CreateHash(val, val_info);
rb_hash_aset(hash, key_val, val_val);
@ -152,25 +152,26 @@ VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type,
VALUE Map_deep_copy(VALUE obj) {
Map* self = ruby_to_Map(obj);
VALUE new_arena_rb = Arena_new();
upb_arena *arena = Arena_get(new_arena_rb);
upb_map* new_map =
upb_map_new(arena, self->key_type, self->value_type_info.type);
size_t iter = UPB_MAP_BEGIN;
while (upb_mapiter_next(self->map, &iter)) {
upb_msgval key = upb_mapiter_key(self->map, iter);
upb_msgval val = upb_mapiter_value(self->map, iter);
upb_msgval val_copy = Msgval_DeepCopy(val, self->value_type_info, arena);
upb_map_set(new_map, key, val_copy, arena);
upb_Arena* arena = Arena_get(new_arena_rb);
upb_Map* new_map =
upb_Map_New(arena, self->key_type, self->value_type_info.type);
size_t iter = kUpb_Map_Begin;
while (upb_MapIterator_Next(self->map, &iter)) {
upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
upb_MessageValue val_copy =
Msgval_DeepCopy(val, self->value_type_info, arena);
upb_Map_Set(new_map, key, val_copy, arena);
}
return Map_GetRubyWrapper(new_map, self->key_type, self->value_type_info,
new_arena_rb);
}
const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef* field,
upb_arena* arena) {
const upb_fielddef* key_field = map_field_key(field);
const upb_fielddef* value_field = map_field_value(field);
const upb_Map* Map_GetUpbMap(VALUE val, const upb_FieldDef* field,
upb_Arena* arena) {
const upb_FieldDef* key_field = map_field_key(field);
const upb_FieldDef* value_field = map_field_value(field);
TypeInfo value_type_info = TypeInfo_get(value_field);
Map* self;
@ -180,7 +181,7 @@ const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef* field,
}
self = ruby_to_Map(val);
if (self->key_type != upb_fielddef_type(key_field)) {
if (self->key_type != upb_FieldDef_CType(key_field)) {
rb_raise(cTypeError, "Map key type does not match field's key type");
}
if (self->value_type_info.type != value_type_info.type) {
@ -194,16 +195,16 @@ const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef* field,
return self->map;
}
void Map_Inspect(StringBuilder* b, const upb_map* map, upb_fieldtype_t key_type,
void Map_Inspect(StringBuilder* b, const upb_Map* map, upb_CType key_type,
TypeInfo val_type) {
bool first = true;
TypeInfo key_type_info = {key_type};
StringBuilder_Printf(b, "{");
if (map) {
size_t iter = UPB_MAP_BEGIN;
while (upb_mapiter_next(map, &iter)) {
upb_msgval key = upb_mapiter_key(map, iter);
upb_msgval val = upb_mapiter_value(map, iter);
size_t iter = kUpb_Map_Begin;
while (upb_MapIterator_Next(map, &iter)) {
upb_MessageValue key = upb_MapIterator_Key(map, iter);
upb_MessageValue val = upb_MapIterator_Value(map, iter);
if (first) {
first = false;
} else {
@ -219,10 +220,12 @@ void Map_Inspect(StringBuilder* b, const upb_map* map, upb_fieldtype_t key_type,
static int merge_into_self_callback(VALUE key, VALUE val, VALUE _self) {
Map* self = ruby_to_Map(_self);
upb_arena *arena = Arena_get(self->arena);
upb_msgval key_val = Convert_RubyToUpb(key, "", Map_keyinfo(self), arena);
upb_msgval val_val = Convert_RubyToUpb(val, "", self->value_type_info, arena);
upb_map_set(Map_GetMutable(_self), key_val, val_val, arena);
upb_Arena* arena = Arena_get(self->arena);
upb_MessageValue key_val =
Convert_RubyToUpb(key, "", Map_keyinfo(self), arena);
upb_MessageValue val_val =
Convert_RubyToUpb(val, "", self->value_type_info, arena);
upb_Map_Set(Map_GetMutable(_self), key_val, val_val, arena);
return ST_CONTINUE;
}
@ -234,9 +237,9 @@ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
RTYPEDDATA_TYPE(hashmap) == &Map_type) {
Map* self = ruby_to_Map(_self);
Map* other = ruby_to_Map(hashmap);
upb_arena *arena = Arena_get(self->arena);
upb_msg *self_msg = Map_GetMutable(_self);
size_t iter = UPB_MAP_BEGIN;
upb_Arena* arena = Arena_get(self->arena);
upb_Message* self_msg = Map_GetMutable(_self);
size_t iter = kUpb_Map_Begin;
Arena_fuse(other->arena, arena);
@ -246,10 +249,10 @@ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
}
while (upb_mapiter_next(other->map, &iter)) {
upb_msgval key = upb_mapiter_key(other->map, iter);
upb_msgval val = upb_mapiter_value(other->map, iter);
upb_map_set(self_msg, key, val, arena);
while (upb_MapIterator_Next(other->map, &iter)) {
upb_MessageValue key = upb_MapIterator_Key(other->map, iter);
upb_MessageValue val = upb_MapIterator_Value(other->map, iter);
upb_Map_Set(self_msg, key, val, arena);
}
} else {
rb_raise(rb_eArgError, "Unknown type merging into Map");
@ -305,20 +308,20 @@ static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
// Check that the key type is an allowed type.
switch (self->key_type) {
case UPB_TYPE_INT32:
case UPB_TYPE_INT64:
case UPB_TYPE_UINT32:
case UPB_TYPE_UINT64:
case UPB_TYPE_BOOL:
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
case kUpb_CType_Int32:
case kUpb_CType_Int64:
case kUpb_CType_UInt32:
case kUpb_CType_UInt64:
case kUpb_CType_Bool:
case kUpb_CType_String:
case kUpb_CType_Bytes:
// These are OK.
break;
default:
rb_raise(rb_eArgError, "Invalid key type for map.");
}
self->map = upb_map_new(Arena_get(self->arena), self->key_type,
self->map = upb_Map_New(Arena_get(self->arena), self->key_type,
self->value_type_info.type);
ObjectCache_Add(self->map, _self);
@ -339,11 +342,11 @@ static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
*/
static VALUE Map_each(VALUE _self) {
Map* self = ruby_to_Map(_self);
size_t iter = UPB_MAP_BEGIN;
size_t iter = kUpb_Map_Begin;
while (upb_mapiter_next(self->map, &iter)) {
upb_msgval key = upb_mapiter_key(self->map, iter);
upb_msgval val = upb_mapiter_value(self->map, iter);
while (upb_MapIterator_Next(self->map, &iter)) {
upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
rb_yield_values(2, key_val, val_val);
@ -360,11 +363,11 @@ static VALUE Map_each(VALUE _self) {
*/
static VALUE Map_keys(VALUE _self) {
Map* self = ruby_to_Map(_self);
size_t iter = UPB_MAP_BEGIN;
size_t iter = kUpb_Map_Begin;
VALUE ret = rb_ary_new();
while (upb_mapiter_next(self->map, &iter)) {
upb_msgval key = upb_mapiter_key(self->map, iter);
while (upb_MapIterator_Next(self->map, &iter)) {
upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
rb_ary_push(ret, key_val);
}
@ -380,11 +383,11 @@ static VALUE Map_keys(VALUE _self) {
*/
static VALUE Map_values(VALUE _self) {
Map* self = ruby_to_Map(_self);
size_t iter = UPB_MAP_BEGIN;
size_t iter = kUpb_Map_Begin;
VALUE ret = rb_ary_new();
while (upb_mapiter_next(self->map, &iter)) {
upb_msgval val = upb_mapiter_value(self->map, iter);
while (upb_MapIterator_Next(self->map, &iter)) {
upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
rb_ary_push(ret, val_val);
}
@ -401,10 +404,11 @@ static VALUE Map_values(VALUE _self) {
*/
static VALUE Map_index(VALUE _self, VALUE key) {
Map* self = ruby_to_Map(_self);
upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
upb_msgval val;
upb_MessageValue key_upb =
Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
upb_MessageValue val;
if (upb_map_get(self->map, key_upb, &val)) {
if (upb_Map_Get(self->map, key_upb, &val)) {
return Convert_UpbToRuby(val, self->value_type_info, self->arena);
} else {
return Qnil;
@ -421,11 +425,13 @@ static VALUE Map_index(VALUE _self, VALUE key) {
*/
static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) {
Map* self = ruby_to_Map(_self);
upb_arena *arena = Arena_get(self->arena);
upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
upb_msgval val_upb = Convert_RubyToUpb(val, "", self->value_type_info, arena);
upb_Arena* arena = Arena_get(self->arena);
upb_MessageValue key_upb =
Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
upb_MessageValue val_upb =
Convert_RubyToUpb(val, "", self->value_type_info, arena);
upb_map_set(Map_GetMutable(_self), key_upb, val_upb, arena);
upb_Map_Set(Map_GetMutable(_self), key_upb, val_upb, arena);
return val;
}
@ -439,9 +445,10 @@ static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) {
*/
static VALUE Map_has_key(VALUE _self, VALUE key) {
Map* self = ruby_to_Map(_self);
upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
upb_MessageValue key_upb =
Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
if (upb_map_get(self->map, key_upb, NULL)) {
if (upb_Map_Get(self->map, key_upb, NULL)) {
return Qtrue;
} else {
return Qfalse;
@ -457,21 +464,22 @@ static VALUE Map_has_key(VALUE _self, VALUE key) {
*/
static VALUE Map_delete(VALUE _self, VALUE key) {
Map* self = ruby_to_Map(_self);
upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
upb_msgval val_upb;
upb_MessageValue key_upb =
Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
upb_MessageValue val_upb;
VALUE ret;
rb_check_frozen(_self);
// TODO(haberman): make upb_map_delete() also capable of returning the deleted
// TODO(haberman): make upb_Map_Delete() also capable of returning the deleted
// value.
if (upb_map_get(self->map, key_upb, &val_upb)) {
if (upb_Map_Get(self->map, key_upb, &val_upb)) {
ret = Convert_UpbToRuby(val_upb, self->value_type_info, self->arena);
} else {
ret = Qnil;
}
upb_map_delete(Map_GetMutable(_self), key_upb);
upb_Map_Delete(Map_GetMutable(_self), key_upb);
return ret;
}
@ -483,7 +491,7 @@ static VALUE Map_delete(VALUE _self, VALUE key) {
* Removes all entries from the map.
*/
static VALUE Map_clear(VALUE _self) {
upb_map_clear(Map_GetMutable(_self));
upb_Map_Clear(Map_GetMutable(_self));
return Qnil;
}
@ -495,7 +503,7 @@ static VALUE Map_clear(VALUE _self) {
*/
static VALUE Map_length(VALUE _self) {
Map* self = ruby_to_Map(_self);
return ULL2NUM(upb_map_size(self->map));
return ULL2NUM(upb_Map_Size(self->map));
}
/*
@ -509,16 +517,16 @@ static VALUE Map_dup(VALUE _self) {
Map* self = ruby_to_Map(_self);
VALUE new_map_rb = Map_new_this_type(self);
Map* new_self = ruby_to_Map(new_map_rb);
size_t iter = UPB_MAP_BEGIN;
upb_arena *arena = Arena_get(new_self->arena);
upb_map *new_map = Map_GetMutable(new_map_rb);
size_t iter = kUpb_Map_Begin;
upb_Arena* arena = Arena_get(new_self->arena);
upb_Map* new_map = Map_GetMutable(new_map_rb);
Arena_fuse(self->arena, arena);
while (upb_mapiter_next(self->map, &iter)) {
upb_msgval key = upb_mapiter_key(self->map, iter);
upb_msgval val = upb_mapiter_value(self->map, iter);
upb_map_set(new_map, key, val, arena);
while (upb_MapIterator_Next(self->map, &iter)) {
upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
upb_Map_Set(new_map, key, val, arena);
}
return new_map_rb;
@ -559,18 +567,18 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
self->value_type_class != other->value_type_class) {
return Qfalse;
}
if (upb_map_size(self->map) != upb_map_size(other->map)) {
if (upb_Map_Size(self->map) != upb_Map_Size(other->map)) {
return Qfalse;
}
// For each member of self, check that an equal member exists at the same key
// in other.
size_t iter = UPB_MAP_BEGIN;
while (upb_mapiter_next(self->map, &iter)) {
upb_msgval key = upb_mapiter_key(self->map, iter);
upb_msgval val = upb_mapiter_value(self->map, iter);
upb_msgval other_val;
if (!upb_map_get(other->map, key, &other_val)) {
size_t iter = kUpb_Map_Begin;
while (upb_MapIterator_Next(self->map, &iter)) {
upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
upb_MessageValue other_val;
if (!upb_Map_Get(other->map, key, &other_val)) {
// Not present in other map.
return Qfalse;
}
@ -609,11 +617,11 @@ VALUE Map_hash(VALUE _self) {
Map* self = ruby_to_Map(_self);
uint64_t hash = 0;
size_t iter = UPB_MAP_BEGIN;
size_t iter = kUpb_Map_Begin;
TypeInfo key_info = {self->key_type};
while (upb_mapiter_next(self->map, &iter)) {
upb_msgval key = upb_mapiter_key(self->map, iter);
upb_msgval val = upb_mapiter_value(self->map, iter);
while (upb_MapIterator_Next(self->map, &iter)) {
upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
hash = Msgval_GetHash(key, key_info, hash);
hash = Msgval_GetHash(val, self->value_type_info, hash);
}

@ -38,22 +38,21 @@
// Returns a Ruby wrapper object for the given map, which will be created if
// one does not exist already.
VALUE Map_GetRubyWrapper(upb_map *map, upb_fieldtype_t key_type,
TypeInfo value_type, VALUE arena);
VALUE Map_GetRubyWrapper(upb_Map *map, upb_CType key_type, TypeInfo value_type,
VALUE arena);
// Gets the underlying upb_map for this Ruby map object, which must have
// Gets the underlying upb_Map for this Ruby map object, which must have
// key/value type that match |field|. If this is not a map or the type doesn't
// match, raises an exception.
const upb_map *Map_GetUpbMap(VALUE val, const upb_fielddef *field,
upb_arena *arena);
const upb_Map *Map_GetUpbMap(VALUE val, const upb_FieldDef *field,
upb_Arena *arena);
// Implements #inspect for this map by appending its contents to |b|.
void Map_Inspect(StringBuilder *b, const upb_map *map, upb_fieldtype_t key_type,
void Map_Inspect(StringBuilder *b, const upb_Map *map, upb_CType key_type,
TypeInfo val_type);
// Returns a new Hash object containing the contents of this Map.
VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type,
TypeInfo val_info);
VALUE Map_CreateHash(const upb_Map *map, upb_CType key_type, TypeInfo val_info);
// Returns a deep copy of this Map object.
VALUE Map_deep_copy(VALUE obj);

File diff suppressed because it is too large Load Diff

@ -36,55 +36,58 @@
#include "protobuf.h"
#include "ruby-upb.h"
// Gets the underlying upb_msg* and upb_msgdef for the given Ruby message
// wrapper. Requires that |value| is indeed a message object.
const upb_msg *Message_Get(VALUE value, const upb_msgdef **m);
// Gets the underlying upb_Message* and upb_MessageDef for the given Ruby
// message wrapper. Requires that |value| is indeed a message object.
const upb_Message* Message_Get(VALUE value, const upb_MessageDef** m);
// Like Message_Get(), but checks that the object is not frozen and returns a
// mutable pointer.
upb_msg *Message_GetMutable(VALUE value, const upb_msgdef **m);
upb_Message* Message_GetMutable(VALUE value, const upb_MessageDef** m);
// Returns the Arena object for this message.
VALUE Message_GetArena(VALUE value);
// Converts |value| into a upb_msg value of the expected upb_msgdef type,
// raising an error if this is not possible. Used when assigning |value| to a
// field of another message, which means the message must be of a particular
// type.
// Converts |value| into a upb_Message value of the expected upb_MessageDef
// type, raising an error if this is not possible. Used when assigning |value|
// to a field of another message, which means the message must be of a
// particular type.
//
// This will perform automatic conversions in some cases (for example, Time ->
// Google::Protobuf::Timestamp). If any new message is created, it will be
// created on |arena|, and any existing message will have its arena fused with
// |arena|.
const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
const char* name, upb_arena* arena);
const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
const char* name, upb_Arena* arena);
// Gets or constructs a Ruby wrapper object for the given message. The wrapper
// object will reference |arena| and ensure that it outlives this object.
VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena);
VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
VALUE arena);
// Gets the given field from this message.
VALUE Message_getfield(VALUE _self, const upb_fielddef* f);
VALUE Message_getfield(VALUE _self, const upb_FieldDef* f);
// Implements #inspect for this message, printing the text to |b|.
void Message_PrintMessage(StringBuilder* b, const upb_msg* msg,
const upb_msgdef* m);
void Message_PrintMessage(StringBuilder* b, const upb_Message* msg,
const upb_MessageDef* m);
// Returns a hash value for the given message.
uint64_t Message_Hash(const upb_msg *msg, const upb_msgdef *m, uint64_t seed);
uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
uint64_t seed);
// Returns a deep copy of the given message.
upb_msg* Message_deep_copy(const upb_msg* msg, const upb_msgdef* m,
upb_arena *arena);
upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
upb_Arena* arena);
// Returns true if these two messages are equal.
bool Message_Equal(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m);
bool Message_Equal(const upb_Message* m1, const upb_Message* m2,
const upb_MessageDef* m);
// Checks that this Ruby object is a message, and raises an exception if not.
void Message_CheckClass(VALUE klass);
// Returns a new Hash object containing the contents of this message.
VALUE Scalar_CreateHash(upb_msgval val, TypeInfo type_info);
VALUE Scalar_CreateHash(upb_MessageValue val, TypeInfo type_info);
// Creates a message class or enum module for this descriptor, respectively.
VALUE build_class_from_descriptor(VALUE descriptor);

@ -40,14 +40,14 @@
VALUE cParseError;
VALUE cTypeError;
const upb_fielddef* map_field_key(const upb_fielddef* field) {
const upb_msgdef *entry = upb_fielddef_msgsubdef(field);
return upb_msgdef_itof(entry, 1);
const upb_FieldDef *map_field_key(const upb_FieldDef *field) {
const upb_MessageDef *entry = upb_FieldDef_MessageSubDef(field);
return upb_MessageDef_FindFieldByNumberWithSize(entry, 1);
}
const upb_fielddef* map_field_value(const upb_fielddef* field) {
const upb_msgdef *entry = upb_fielddef_msgsubdef(field);
return upb_msgdef_itof(entry, 2);
const upb_FieldDef *map_field_value(const upb_FieldDef *field) {
const upb_MessageDef *entry = upb_FieldDef_MessageSubDef(field);
return upb_MessageDef_FindFieldByNumberWithSize(entry, 2);
}
// -----------------------------------------------------------------------------
@ -66,21 +66,21 @@ static size_t StringBuilder_SizeOf(size_t cap) {
return sizeof(StringBuilder) + cap;
}
StringBuilder* StringBuilder_New() {
StringBuilder *StringBuilder_New() {
const size_t cap = 128;
StringBuilder* builder = malloc(sizeof(*builder));
StringBuilder *builder = malloc(sizeof(*builder));
builder->size = 0;
builder->cap = cap;
builder->data = malloc(builder->cap);
return builder;
}
void StringBuilder_Free(StringBuilder* b) {
void StringBuilder_Free(StringBuilder *b) {
free(b->data);
free(b);
}
void StringBuilder_Printf(StringBuilder* b, const char *fmt, ...) {
void StringBuilder_Printf(StringBuilder *b, const char *fmt, ...) {
size_t have = b->cap - b->size;
size_t n;
va_list args;
@ -104,60 +104,62 @@ void StringBuilder_Printf(StringBuilder* b, const char *fmt, ...) {
b->size += n;
}
VALUE StringBuilder_ToRubyString(StringBuilder* b) {
VALUE StringBuilder_ToRubyString(StringBuilder *b) {
VALUE ret = rb_str_new(b->data, b->size);
rb_enc_associate(ret, rb_utf8_encoding());
return ret;
}
static void StringBuilder_PrintEnum(StringBuilder* b, int32_t val,
const upb_enumdef* e) {
const char *name = upb_enumdef_iton(e, val);
if (name) {
StringBuilder_Printf(b, ":%s", name);
static void StringBuilder_PrintEnum(StringBuilder *b, int32_t val,
const upb_EnumDef *e) {
const upb_EnumValueDef *ev = upb_EnumDef_FindValueByNumber(e, val);
if (ev) {
StringBuilder_Printf(b, ":%s", upb_EnumValueDef_Name(ev));
} else {
StringBuilder_Printf(b, "%" PRId32, val);
}
}
void StringBuilder_PrintMsgval(StringBuilder* b, upb_msgval val,
void StringBuilder_PrintMsgval(StringBuilder *b, upb_MessageValue val,
TypeInfo info) {
switch (info.type) {
case UPB_TYPE_BOOL:
case kUpb_CType_Bool:
StringBuilder_Printf(b, "%s", val.bool_val ? "true" : "false");
break;
case UPB_TYPE_FLOAT: {
case kUpb_CType_Float: {
VALUE str = rb_inspect(DBL2NUM(val.float_val));
StringBuilder_Printf(b, "%s", RSTRING_PTR(str));
break;
}
case UPB_TYPE_DOUBLE: {
case kUpb_CType_Double: {
VALUE str = rb_inspect(DBL2NUM(val.double_val));
StringBuilder_Printf(b, "%s", RSTRING_PTR(str));
break;
}
case UPB_TYPE_INT32:
case kUpb_CType_Int32:
StringBuilder_Printf(b, "%" PRId32, val.int32_val);
break;
case UPB_TYPE_UINT32:
case kUpb_CType_UInt32:
StringBuilder_Printf(b, "%" PRIu32, val.uint32_val);
break;
case UPB_TYPE_INT64:
case kUpb_CType_Int64:
StringBuilder_Printf(b, "%" PRId64, val.int64_val);
break;
case UPB_TYPE_UINT64:
case kUpb_CType_UInt64:
StringBuilder_Printf(b, "%" PRIu64, val.uint64_val);
break;
case UPB_TYPE_STRING:
StringBuilder_Printf(b, "\"%.*s\"", (int)val.str_val.size, val.str_val.data);
case kUpb_CType_String:
StringBuilder_Printf(b, "\"%.*s\"", (int)val.str_val.size,
val.str_val.data);
break;
case UPB_TYPE_BYTES:
StringBuilder_Printf(b, "\"%.*s\"", (int)val.str_val.size, val.str_val.data);
case kUpb_CType_Bytes:
StringBuilder_Printf(b, "\"%.*s\"", (int)val.str_val.size,
val.str_val.data);
break;
case UPB_TYPE_ENUM:
case kUpb_CType_Enum:
StringBuilder_PrintEnum(b, val.int32_val, info.def.enumdef);
break;
case UPB_TYPE_MESSAGE:
case kUpb_CType_Message:
Message_PrintMessage(b, val.msg_val, info.def.msgdef);
break;
}
@ -168,7 +170,7 @@ void StringBuilder_PrintMsgval(StringBuilder* b, upb_msgval val,
// -----------------------------------------------------------------------------
typedef struct {
upb_arena *arena;
upb_Arena *arena;
VALUE pinned_objs;
} Arena;
@ -179,44 +181,42 @@ static void Arena_mark(void *data) {
static void Arena_free(void *data) {
Arena *arena = data;
upb_arena_free(arena->arena);
upb_Arena_Free(arena->arena);
xfree(arena);
}
static VALUE cArena;
const rb_data_type_t Arena_type = {
"Google::Protobuf::Internal::Arena",
{ Arena_mark, Arena_free, NULL },
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
"Google::Protobuf::Internal::Arena",
{Arena_mark, Arena_free, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
};
static VALUE Arena_alloc(VALUE klass) {
Arena *arena = ALLOC(Arena);
arena->arena = upb_arena_new();
arena->arena = upb_Arena_New();
arena->pinned_objs = Qnil;
return TypedData_Wrap_Struct(klass, &Arena_type, arena);
}
upb_arena *Arena_get(VALUE _arena) {
upb_Arena *Arena_get(VALUE _arena) {
Arena *arena;
TypedData_Get_Struct(_arena, Arena, &Arena_type, arena);
return arena->arena;
}
void Arena_fuse(VALUE _arena, upb_arena *other) {
void Arena_fuse(VALUE _arena, upb_Arena *other) {
Arena *arena;
TypedData_Get_Struct(_arena, Arena, &Arena_type, arena);
if (!upb_arena_fuse(arena->arena, other)) {
if (!upb_Arena_Fuse(arena->arena, other)) {
rb_raise(rb_eRuntimeError,
"Unable to fuse arenas. This should never happen since Ruby does "
"not use initial blocks");
}
}
VALUE Arena_new() {
return Arena_alloc(cArena);
}
VALUE Arena_new() { return Arena_alloc(cArena); }
void Arena_Pin(VALUE _arena, VALUE obj) {
Arena *arena;
@ -333,8 +333,8 @@ static void SecondaryMap_MaybeGC() {
// avoid O(N^2) CPU costs.
size_t threshold = PBRUBY_MAX(secondary_len * 0.2, 2000);
if (waste > threshold) {
rb_funcall(gc_secondary_map_lambda, rb_intern("call"), 2,
secondary_map, weak_obj_cache);
rb_funcall(gc_secondary_map_lambda, rb_intern("call"), 2, secondary_map,
weak_obj_cache);
}
}
@ -353,7 +353,7 @@ static VALUE SecondaryMap_Get(VALUE key, bool create) {
#endif
// Requires: secondary_map_mutex is held by this thread iff create == true.
static VALUE ObjectCache_GetKey(const void* key, bool create) {
static VALUE ObjectCache_GetKey(const void *key, bool create) {
VALUE key_val = (VALUE)key;
PBRUBY_ASSERT((key_val & 3) == 0);
VALUE ret = LL2NUM(key_val >> 2);
@ -380,7 +380,7 @@ static void ObjectCache_Init() {
#endif
}
void ObjectCache_Add(const void* key, VALUE val) {
void ObjectCache_Add(const void *key, VALUE val) {
PBRUBY_ASSERT(ObjectCache_Get(key) == Qnil);
#if USE_SECONDARY_MAP
rb_mutex_lock(secondary_map_mutex);
@ -394,7 +394,7 @@ void ObjectCache_Add(const void* key, VALUE val) {
}
// Returns the cached object for this key, if any. Otherwise returns Qnil.
VALUE ObjectCache_Get(const void* key) {
VALUE ObjectCache_Get(const void *key) {
VALUE key_rb = ObjectCache_GetKey(key, false);
return rb_funcall(weak_obj_cache, item_get, 1, key_rb);
}
@ -407,9 +407,9 @@ VALUE ObjectCache_Get(const void* key) {
* unknown fields in submessages.
*/
static VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb) {
const upb_msgdef *m;
upb_msg *msg = Message_GetMutable(msg_rb, &m);
if (!upb_msg_discardunknown(msg, m, 128)) {
const upb_MessageDef *m;
upb_Message *msg = Message_GetMutable(msg_rb, &m);
if (!upb_Message_DiscardUnknown(msg, m, 128)) {
rb_raise(rb_eRuntimeError, "Messages nested too deeply.");
}
@ -431,10 +431,10 @@ VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
return Map_deep_copy(obj);
} else {
VALUE new_arena_rb = Arena_new();
upb_arena *new_arena = Arena_get(new_arena_rb);
const upb_msgdef *m;
const upb_msg *msg = Message_Get(obj, &m);
upb_msg* new_msg = Message_deep_copy(msg, m, new_arena);
upb_Arena *new_arena = Arena_get(new_arena_rb);
const upb_MessageDef *m;
const upb_Message *msg = Message_Get(obj, &m);
upb_Message *new_msg = Message_deep_copy(msg, m, new_arena);
return Message_GetRubyWrapper(new_msg, m, new_arena_rb);
}
}
@ -445,8 +445,7 @@ VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
// This must be named "Init_protobuf_c" because the Ruby module is named
// "protobuf_c" -- the VM looks for this symbol in our .so.
__attribute__ ((visibility ("default")))
void Init_protobuf_c() {
__attribute__((visibility("default"))) void Init_protobuf_c() {
ObjectCache_Init();
VALUE google = rb_define_module("Google");
@ -465,6 +464,6 @@ void Init_protobuf_c() {
rb_define_singleton_method(protobuf, "discard_unknown",
Google_Protobuf_discard_unknown, 1);
rb_define_singleton_method(protobuf, "deep_copy",
Google_Protobuf_deep_copy, 1);
rb_define_singleton_method(protobuf, "deep_copy", Google_Protobuf_deep_copy,
1);
}

@ -31,33 +31,33 @@
#ifndef __GOOGLE_PROTOBUF_RUBY_PROTOBUF_H__
#define __GOOGLE_PROTOBUF_RUBY_PROTOBUF_H__
#include <ruby/encoding.h>
#include <ruby/ruby.h>
#include <ruby/vm.h>
#include <ruby/encoding.h>
#include "ruby-upb.h"
#include "defs.h"
#include "ruby-upb.h"
// These operate on a map field (i.e., a repeated field of submessages whose
// submessage type is a map-entry msgdef).
const upb_fielddef* map_field_key(const upb_fielddef* field);
const upb_fielddef* map_field_value(const upb_fielddef* field);
const upb_FieldDef* map_field_key(const upb_FieldDef* field);
const upb_FieldDef* map_field_value(const upb_FieldDef* field);
// -----------------------------------------------------------------------------
// Arena
// -----------------------------------------------------------------------------
// A Ruby object that wraps an underlying upb_arena. Any objects that are
// A Ruby object that wraps an underlying upb_Arena. Any objects that are
// allocated from this arena should reference the Arena in rb_gc_mark(), to
// ensure that the object's underlying memory outlives any Ruby object that can
// reach it.
VALUE Arena_new();
upb_arena *Arena_get(VALUE arena);
upb_Arena* Arena_get(VALUE arena);
// Fuses this arena to another, throwing a Ruby exception if this is not
// possible.
void Arena_fuse(VALUE arena, upb_arena *other);
void Arena_fuse(VALUE arena, upb_Arena* other);
// Pins this Ruby object to the lifetime of this arena, so that as long as the
// arena is alive this object will not be collected.
@ -93,10 +93,11 @@ typedef struct StringBuilder StringBuilder;
StringBuilder* StringBuilder_New();
void StringBuilder_Free(StringBuilder* b);
void StringBuilder_Printf(StringBuilder* b, const char *fmt, ...);
void StringBuilder_Printf(StringBuilder* b, const char* fmt, ...);
VALUE StringBuilder_ToRubyString(StringBuilder* b);
void StringBuilder_PrintMsgval(StringBuilder* b, upb_msgval val, TypeInfo info);
void StringBuilder_PrintMsgval(StringBuilder* b, upb_MessageValue val,
TypeInfo info);
// -----------------------------------------------------------------------------
// Utilities.
@ -105,7 +106,9 @@ void StringBuilder_PrintMsgval(StringBuilder* b, upb_msgval val, TypeInfo info);
extern VALUE cTypeError;
#ifdef NDEBUG
#define PBRUBY_ASSERT(expr) do {} while (false && (expr))
#define PBRUBY_ASSERT(expr) \
do { \
} while (false && (expr))
#else
#define PBRUBY_ASSERT(expr) assert(expr)
#endif

@ -40,10 +40,10 @@
// -----------------------------------------------------------------------------
typedef struct {
const upb_array *array; // Can get as mutable when non-frozen.
const upb_Array* array; // Can get as mutable when non-frozen.
TypeInfo type_info;
VALUE type_class; // To GC-root the msgdef/enumdef in type_info.
VALUE arena; // To GC-root the upb_array.
VALUE arena; // To GC-root the upb_Array.
} RepeatedField;
VALUE cRepeatedField;
@ -55,9 +55,9 @@ static void RepeatedField_mark(void* _self) {
}
const rb_data_type_t RepeatedField_type = {
"Google::Protobuf::RepeatedField",
{ RepeatedField_mark, RUBY_DEFAULT_FREE, NULL },
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
"Google::Protobuf::RepeatedField",
{RepeatedField_mark, RUBY_DEFAULT_FREE, NULL},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
};
static RepeatedField* ruby_to_RepeatedField(VALUE _self) {
@ -66,9 +66,9 @@ static RepeatedField* ruby_to_RepeatedField(VALUE _self) {
return self;
}
static upb_array *RepeatedField_GetMutable(VALUE _self) {
static upb_Array* RepeatedField_GetMutable(VALUE _self) {
rb_check_frozen(_self);
return (upb_array*)ruby_to_RepeatedField(_self)->array;
return (upb_Array*)ruby_to_RepeatedField(_self)->array;
}
VALUE RepeatedField_alloc(VALUE klass) {
@ -79,7 +79,7 @@ VALUE RepeatedField_alloc(VALUE klass) {
return TypedData_Wrap_Struct(klass, &RepeatedField_type, self);
}
VALUE RepeatedField_GetRubyWrapper(upb_array* array, TypeInfo type_info,
VALUE RepeatedField_GetRubyWrapper(upb_Array* array, TypeInfo type_info,
VALUE arena) {
PBRUBY_ASSERT(array);
VALUE val = ObjectCache_Get(array);
@ -92,7 +92,7 @@ VALUE RepeatedField_GetRubyWrapper(upb_array* array, TypeInfo type_info,
self->array = array;
self->arena = arena;
self->type_info = type_info;
if (self->type_info.type == UPB_TYPE_MESSAGE) {
if (self->type_info.type == kUpb_CType_Message) {
self->type_class = Descriptor_DefToClass(type_info.def.msgdef);
}
}
@ -105,24 +105,24 @@ VALUE RepeatedField_GetRubyWrapper(upb_array* array, TypeInfo type_info,
static VALUE RepeatedField_new_this_type(RepeatedField* from) {
VALUE arena_rb = Arena_new();
upb_array *array = upb_array_new(Arena_get(arena_rb), from->type_info.type);
upb_Array* array = upb_Array_New(Arena_get(arena_rb), from->type_info.type);
VALUE ret = RepeatedField_GetRubyWrapper(array, from->type_info, arena_rb);
PBRUBY_ASSERT(ruby_to_RepeatedField(ret)->type_class == from->type_class);
return ret;
}
void RepeatedField_Inspect(StringBuilder* b, const upb_array* array,
void RepeatedField_Inspect(StringBuilder* b, const upb_Array* array,
TypeInfo info) {
bool first = true;
StringBuilder_Printf(b, "[");
size_t n = array ? upb_array_size(array) : 0;
size_t n = array ? upb_Array_Size(array) : 0;
for (size_t i = 0; i < n; i++) {
if (first) {
first = false;
} else {
StringBuilder_Printf(b, ", ");
}
StringBuilder_PrintMsgval(b, upb_array_get(array, i), info);
StringBuilder_PrintMsgval(b, upb_Array_Get(array, i), info);
}
StringBuilder_Printf(b, "]");
}
@ -132,24 +132,24 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
VALUE new_rptfield = RepeatedField_new_this_type(self);
RepeatedField* new_self = ruby_to_RepeatedField(new_rptfield);
VALUE arena_rb = new_self->arena;
upb_array *new_array = RepeatedField_GetMutable(new_rptfield);
upb_arena *arena = Arena_get(arena_rb);
size_t elements = upb_array_size(self->array);
upb_Array* new_array = RepeatedField_GetMutable(new_rptfield);
upb_Arena* arena = Arena_get(arena_rb);
size_t elements = upb_Array_Size(self->array);
upb_array_resize(new_array, elements, arena);
upb_Array_Resize(new_array, elements, arena);
size_t size = upb_array_size(self->array);
size_t size = upb_Array_Size(self->array);
for (size_t i = 0; i < size; i++) {
upb_msgval msgval = upb_array_get(self->array, i);
upb_msgval copy = Msgval_DeepCopy(msgval, self->type_info, arena);
upb_array_set(new_array, i, copy);
upb_MessageValue msgval = upb_Array_Get(self->array, i);
upb_MessageValue copy = Msgval_DeepCopy(msgval, self->type_info, arena);
upb_Array_Set(new_array, i, copy);
}
return new_rptfield;
}
const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef* field,
upb_arena* arena) {
const upb_Array* RepeatedField_GetUpbArray(VALUE val, const upb_FieldDef* field,
upb_Arena* arena) {
RepeatedField* self;
TypeInfo type_info = TypeInfo_get(field);
@ -173,17 +173,17 @@ const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef* field,
static int index_position(VALUE _index, RepeatedField* repeated_field) {
int index = NUM2INT(_index);
if (index < 0) index += upb_array_size(repeated_field->array);
if (index < 0) index += upb_Array_Size(repeated_field->array);
return index;
}
static VALUE RepeatedField_subarray(RepeatedField* self, long beg, long len) {
size_t size = upb_array_size(self->array);
size_t size = upb_Array_Size(self->array);
VALUE ary = rb_ary_new2(size);
long i;
for (i = beg; i < beg + len; i++) {
upb_msgval msgval = upb_array_get(self->array, i);
upb_MessageValue msgval = upb_Array_Get(self->array, i);
VALUE elem = Convert_UpbToRuby(msgval, self->type_info, self->arena);
rb_ary_push(ary, elem);
}
@ -200,18 +200,17 @@ static VALUE RepeatedField_subarray(RepeatedField* self, long beg, long len) {
*/
static VALUE RepeatedField_each(VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
int size = upb_array_size(self->array);
int size = upb_Array_Size(self->array);
int i;
for (i = 0; i < size; i++) {
upb_msgval msgval = upb_array_get(self->array, i);
upb_MessageValue msgval = upb_Array_Get(self->array, i);
VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena);
rb_yield(val);
}
return _self;
}
/*
* call-seq:
* RepeatedField.[](index) => value
@ -220,20 +219,20 @@ static VALUE RepeatedField_each(VALUE _self) {
*/
static VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
long size = upb_array_size(self->array);
long size = upb_Array_Size(self->array);
VALUE arg = argv[0];
long beg, len;
if (argc == 1){
if (argc == 1) {
if (FIXNUM_P(arg)) {
/* standard case */
upb_msgval msgval;
upb_MessageValue msgval;
int index = index_position(argv[0], self);
if (index < 0 || (size_t)index >= upb_array_size(self->array)) {
if (index < 0 || (size_t)index >= upb_Array_Size(self->array)) {
return Qnil;
}
msgval = upb_array_get(self->array, index);
msgval = upb_Array_Get(self->array, index);
return Convert_UpbToRuby(msgval, self->type_info, self->arena);
} else {
/* check if idx is Range */
@ -269,10 +268,10 @@ static VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
*/
static VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
RepeatedField* self = ruby_to_RepeatedField(_self);
int size = upb_array_size(self->array);
upb_array *array = RepeatedField_GetMutable(_self);
upb_arena *arena = Arena_get(self->arena);
upb_msgval msgval = Convert_RubyToUpb(val, "", self->type_info, arena);
int size = upb_Array_Size(self->array);
upb_Array* array = RepeatedField_GetMutable(_self);
upb_Arena* arena = Arena_get(self->arena);
upb_MessageValue msgval = Convert_RubyToUpb(val, "", self->type_info, arena);
int index = index_position(_index, self);
if (index < 0 || index >= (INT_MAX - 1)) {
@ -280,17 +279,17 @@ static VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
}
if (index >= size) {
upb_array_resize(array, index + 1, arena);
upb_msgval fill;
upb_Array_Resize(array, index + 1, arena);
upb_MessageValue fill;
memset(&fill, 0, sizeof(fill));
for (int i = size; i < index; i++) {
// Fill default values.
// TODO(haberman): should this happen at the upb level?
upb_array_set(array, i, fill);
upb_Array_Set(array, i, fill);
}
}
upb_array_set(array, index, msgval);
upb_Array_Set(array, index, msgval);
return Qnil;
}
@ -302,13 +301,14 @@ static VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
*/
static VALUE RepeatedField_push_vararg(int argc, VALUE* argv, VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
upb_arena *arena = Arena_get(self->arena);
upb_array *array = RepeatedField_GetMutable(_self);
upb_Arena* arena = Arena_get(self->arena);
upb_Array* array = RepeatedField_GetMutable(_self);
int i;
for (i = 0; i < argc; i++) {
upb_msgval msgval = Convert_RubyToUpb(argv[i], "", self->type_info, arena);
upb_array_append(array, msgval, arena);
upb_MessageValue msgval =
Convert_RubyToUpb(argv[i], "", self->type_info, arena);
upb_Array_Append(array, msgval, arena);
}
return _self;
@ -322,11 +322,11 @@ static VALUE RepeatedField_push_vararg(int argc, VALUE* argv, VALUE _self) {
*/
static VALUE RepeatedField_push(VALUE _self, VALUE val) {
RepeatedField* self = ruby_to_RepeatedField(_self);
upb_arena *arena = Arena_get(self->arena);
upb_array *array = RepeatedField_GetMutable(_self);
upb_Arena* arena = Arena_get(self->arena);
upb_Array* array = RepeatedField_GetMutable(_self);
upb_msgval msgval = Convert_RubyToUpb(val, "", self->type_info, arena);
upb_array_append(array, msgval, arena);
upb_MessageValue msgval = Convert_RubyToUpb(val, "", self->type_info, arena);
upb_Array_Append(array, msgval, arena);
return _self;
}
@ -336,19 +336,19 @@ static VALUE RepeatedField_push(VALUE _self, VALUE val) {
*/
static VALUE RepeatedField_pop_one(VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
size_t size = upb_array_size(self->array);
upb_array *array = RepeatedField_GetMutable(_self);
upb_msgval last;
size_t size = upb_Array_Size(self->array);
upb_Array* array = RepeatedField_GetMutable(_self);
upb_MessageValue last;
VALUE ret;
if (size == 0) {
return Qnil;
}
last = upb_array_get(self->array, size - 1);
last = upb_Array_Get(self->array, size - 1);
ret = Convert_UpbToRuby(last, self->type_info, self->arena);
upb_array_resize(array, size - 1, Arena_get(self->arena));
upb_Array_Resize(array, size - 1, Arena_get(self->arena));
return ret;
}
@ -360,11 +360,11 @@ static VALUE RepeatedField_pop_one(VALUE _self) {
*/
static VALUE RepeatedField_replace(VALUE _self, VALUE list) {
RepeatedField* self = ruby_to_RepeatedField(_self);
upb_array *array = RepeatedField_GetMutable(_self);
upb_Array* array = RepeatedField_GetMutable(_self);
int i;
Check_Type(list, T_ARRAY);
upb_array_resize(array, 0, Arena_get(self->arena));
upb_Array_Resize(array, 0, Arena_get(self->arena));
for (i = 0; i < RARRAY_LEN(list); i++) {
RepeatedField_push(_self, rb_ary_entry(list, i));
@ -381,8 +381,8 @@ static VALUE RepeatedField_replace(VALUE _self, VALUE list) {
*/
static VALUE RepeatedField_clear(VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
upb_array *array = RepeatedField_GetMutable(_self);
upb_array_resize(array, 0, Arena_get(self->arena));
upb_Array* array = RepeatedField_GetMutable(_self);
upb_Array_Resize(array, 0, Arena_get(self->arena));
return _self;
}
@ -394,7 +394,7 @@ static VALUE RepeatedField_clear(VALUE _self) {
*/
static VALUE RepeatedField_length(VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
return INT2NUM(upb_array_size(self->array));
return INT2NUM(upb_Array_Size(self->array));
}
/*
@ -408,16 +408,16 @@ static VALUE RepeatedField_dup(VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
VALUE new_rptfield = RepeatedField_new_this_type(self);
RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
upb_array *new_array = RepeatedField_GetMutable(new_rptfield);
upb_arena* arena = Arena_get(new_rptfield_self->arena);
int size = upb_array_size(self->array);
upb_Array* new_array = RepeatedField_GetMutable(new_rptfield);
upb_Arena* arena = Arena_get(new_rptfield_self->arena);
int size = upb_Array_Size(self->array);
int i;
Arena_fuse(self->arena, arena);
for (i = 0; i < size; i++) {
upb_msgval msgval = upb_array_get(self->array, i);
upb_array_append(new_array, msgval, arena);
upb_MessageValue msgval = upb_Array_Get(self->array, i);
upb_Array_Append(new_array, msgval, arena);
}
return new_rptfield;
@ -432,12 +432,12 @@ static VALUE RepeatedField_dup(VALUE _self) {
*/
VALUE RepeatedField_to_ary(VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
int size = upb_array_size(self->array);
int size = upb_Array_Size(self->array);
VALUE ary = rb_ary_new2(size);
int i;
for (i = 0; i < size; i++) {
upb_msgval msgval = upb_array_get(self->array, i);
upb_MessageValue msgval = upb_Array_Get(self->array, i);
VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena);
rb_ary_push(ary, val);
}
@ -473,17 +473,17 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
self = ruby_to_RepeatedField(_self);
other = ruby_to_RepeatedField(_other);
size_t n = upb_array_size(self->array);
size_t n = upb_Array_Size(self->array);
if (self->type_info.type != other->type_info.type ||
self->type_class != other->type_class ||
upb_array_size(other->array) != n) {
upb_Array_Size(other->array) != n) {
return Qfalse;
}
for (size_t i = 0; i < n; i++) {
upb_msgval val1 = upb_array_get(self->array, i);
upb_msgval val2 = upb_array_get(other->array, i);
upb_MessageValue val1 = upb_Array_Get(self->array, i);
upb_MessageValue val2 = upb_Array_Get(other->array, i);
if (!Msgval_IsEqual(val1, val2, self->type_info)) {
return Qfalse;
}
@ -517,10 +517,10 @@ static VALUE RepeatedField_freeze(VALUE _self) {
VALUE RepeatedField_hash(VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
uint64_t hash = 0;
size_t n = upb_array_size(self->array);
size_t n = upb_Array_Size(self->array);
for (size_t i = 0; i < n; i++) {
upb_msgval val = upb_array_get(self->array, i);
upb_MessageValue val = upb_Array_Get(self->array, i);
hash = Msgval_GetHash(val, self->type_info, hash);
}
@ -549,10 +549,10 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
RepeatedField* self = ruby_to_RepeatedField(_self);
RepeatedField* list_rptfield = ruby_to_RepeatedField(list);
RepeatedField* dupped = ruby_to_RepeatedField(dupped_);
upb_array *dupped_array = RepeatedField_GetMutable(dupped_);
upb_arena* arena = Arena_get(dupped->arena);
upb_Array* dupped_array = RepeatedField_GetMutable(dupped_);
upb_Arena* arena = Arena_get(dupped->arena);
Arena_fuse(list_rptfield->arena, arena);
int size = upb_array_size(list_rptfield->array);
int size = upb_Array_Size(list_rptfield->array);
int i;
if (self->type_info.type != list_rptfield->type_info.type ||
@ -562,8 +562,8 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
}
for (i = 0; i < size; i++) {
upb_msgval msgval = upb_array_get(list_rptfield->array, i);
upb_array_append(dupped_array, msgval, arena);
upb_MessageValue msgval = upb_Array_Get(list_rptfield->array, i);
upb_Array_Append(dupped_array, msgval, arena);
}
} else {
rb_raise(rb_eArgError, "Unknown type appending to RepeatedField");
@ -601,7 +601,7 @@ VALUE RepeatedField_concat(VALUE _self, VALUE list) {
*/
VALUE RepeatedField_init(int argc, VALUE* argv, VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
upb_arena *arena;
upb_Arena* arena;
VALUE ary = Qnil;
self->arena = Arena_new();
@ -612,7 +612,7 @@ VALUE RepeatedField_init(int argc, VALUE* argv, VALUE _self) {
}
self->type_info = TypeInfo_FromClass(argc, argv, 0, &self->type_class, &ary);
self->array = upb_array_new(arena, self->type_info.type);
self->array = upb_Array_New(arena, self->type_info.type);
ObjectCache_Add(self->array, _self);
if (ary != Qnil) {
@ -627,14 +627,12 @@ VALUE RepeatedField_init(int argc, VALUE* argv, VALUE _self) {
}
void RepeatedField_register(VALUE module) {
VALUE klass = rb_define_class_under(
module, "RepeatedField", rb_cObject);
VALUE klass = rb_define_class_under(module, "RepeatedField", rb_cObject);
rb_define_alloc_func(klass, RepeatedField_alloc);
rb_gc_register_address(&cRepeatedField);
cRepeatedField = klass;
rb_define_method(klass, "initialize",
RepeatedField_init, -1);
rb_define_method(klass, "initialize", RepeatedField_init, -1);
rb_define_method(klass, "each", RepeatedField_each, 0);
rb_define_method(klass, "[]", RepeatedField_index, -1);
rb_define_method(klass, "at", RepeatedField_index, -1);

@ -36,19 +36,19 @@
#include "protobuf.h"
#include "ruby-upb.h"
// Returns a Ruby wrapper object for the given upb_array, which will be created
// Returns a Ruby wrapper object for the given upb_Array, which will be created
// if one does not exist already.
VALUE RepeatedField_GetRubyWrapper(upb_array* msg, TypeInfo type_info,
VALUE RepeatedField_GetRubyWrapper(upb_Array* msg, TypeInfo type_info,
VALUE arena);
// Gets the underlying upb_array for this Ruby RepeatedField object, which must
// Gets the underlying upb_Array for this Ruby RepeatedField object, which must
// have a type that matches |f|. If this is not a repeated field or the type
// doesn't match, raises an exception.
const upb_array* RepeatedField_GetUpbArray(VALUE value, const upb_fielddef* f,
upb_arena* arena);
const upb_Array* RepeatedField_GetUpbArray(VALUE value, const upb_FieldDef* f,
upb_Arena* arena);
// Implements #inspect for this repeated field by appending its contents to |b|.
void RepeatedField_Inspect(StringBuilder* b, const upb_array* array,
void RepeatedField_Inspect(StringBuilder* b, const upb_Array* array,
TypeInfo info);
// Returns a deep copy of this RepeatedField object.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -33,7 +33,8 @@
// On x86-64 Linux with glibc, we link against the 2.2.5 version of memcpy so
// that we avoid depending on the 2.14 version of the symbol. This way,
// distributions that are using pre-2.14 versions of glibc can successfully use
// the gem we distribute (https://github.com/protocolbuffers/protobuf/issues/2783).
// the gem we distribute
// (https://github.com/protocolbuffers/protobuf/issues/2783).
//
// This wrapper is enabled by passing the linker flags -Wl,-wrap,memcpy in
// extconf.rb.
@ -41,11 +42,11 @@
#if defined(__x86_64__) && defined(__GNU_LIBRARY__)
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
void *__wrap_memcpy(void *dest, const void *src, size_t n) {
return memcpy(dest, src, n);
return memcpy(dest, src, n);
}
#else
void *__wrap_memcpy(void *dest, const void *src, size_t n) {
return memmove(dest, src, n);
return memmove(dest, src, n);
}
#endif
#endif

@ -816,11 +816,17 @@ module CommonTests
:optional_enum => :B,
:repeated_string => ["a", "b", "c"],
:repeated_int32 => [42, 43, 44],
:repeated_enum => [:A, :B, :C, 100],
:repeated_enum => [:A, :B, :C],
:repeated_msg => [proto_module::TestMessage2.new(:foo => 1),
proto_module::TestMessage2.new(:foo => 2)])
if proto_module == ::BasicTest
# For proto3 we can add an unknown enum value safely.
m.repeated_enum << 100
end
data = proto_module::TestMessage.encode m
m2 = proto_module::TestMessage.decode data
assert_equal m, m2
data = Google::Protobuf.encode m

@ -0,0 +1,13 @@
cc_library(
name = "utf8_range",
hdrs = ["utf8_range.h"],
srcs = ["utf8_range.c"],
visibility = ["//:__pkg__"],
)
filegroup(
name = "cmake_files",
srcs = glob(["*"]),
visibility = ["//cmake:__pkg__"],
)

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Yibo Cai
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,395 @@
/*
* http://www.unicode.org/versions/Unicode6.0.0/ch03.pdf - page 94
*
* Table 3-7. Well-Formed UTF-8 Byte Sequences
*
* +--------------------+------------+-------------+------------+-------------+
* | Code Points | First Byte | Second Byte | Third Byte | Fourth Byte |
* +--------------------+------------+-------------+------------+-------------+
* | U+0000..U+007F | 00..7F | | | |
* +--------------------+------------+-------------+------------+-------------+
* | U+0080..U+07FF | C2..DF | 80..BF | | |
* +--------------------+------------+-------------+------------+-------------+
* | U+0800..U+0FFF | E0 | A0..BF | 80..BF | |
* +--------------------+------------+-------------+------------+-------------+
* | U+1000..U+CFFF | E1..EC | 80..BF | 80..BF | |
* +--------------------+------------+-------------+------------+-------------+
* | U+D000..U+D7FF | ED | 80..9F | 80..BF | |
* +--------------------+------------+-------------+------------+-------------+
* | U+E000..U+FFFF | EE..EF | 80..BF | 80..BF | |
* +--------------------+------------+-------------+------------+-------------+
* | U+10000..U+3FFFF | F0 | 90..BF | 80..BF | 80..BF |
* +--------------------+------------+-------------+------------+-------------+
* | U+40000..U+FFFFF | F1..F3 | 80..BF | 80..BF | 80..BF |
* +--------------------+------------+-------------+------------+-------------+
* | U+100000..U+10FFFF | F4 | 80..8F | 80..BF | 80..BF |
* +--------------------+------------+-------------+------------+-------------+
*/
/* Return 0 - success, >0 - index(1 based) of first error char */
int utf8_naive(const unsigned char* data, int len) {
int err_pos = 1;
while (len) {
int bytes;
const unsigned char byte1 = data[0];
/* 00..7F */
if (byte1 <= 0x7F) {
bytes = 1;
/* C2..DF, 80..BF */
} else if (len >= 2 && byte1 >= 0xC2 && byte1 <= 0xDF &&
(signed char)data[1] <= (signed char)0xBF) {
bytes = 2;
} else if (len >= 3) {
const unsigned char byte2 = data[1];
/* Is byte2, byte3 between 0x80 ~ 0xBF */
const int byte2_ok = (signed char)byte2 <= (signed char)0xBF;
const int byte3_ok = (signed char)data[2] <= (signed char)0xBF;
if (byte2_ok && byte3_ok &&
/* E0, A0..BF, 80..BF */
((byte1 == 0xE0 && byte2 >= 0xA0) ||
/* E1..EC, 80..BF, 80..BF */
(byte1 >= 0xE1 && byte1 <= 0xEC) ||
/* ED, 80..9F, 80..BF */
(byte1 == 0xED && byte2 <= 0x9F) ||
/* EE..EF, 80..BF, 80..BF */
(byte1 >= 0xEE && byte1 <= 0xEF))) {
bytes = 3;
} else if (len >= 4) {
/* Is byte4 between 0x80 ~ 0xBF */
const int byte4_ok = (signed char)data[3] <= (signed char)0xBF;
if (byte2_ok && byte3_ok && byte4_ok &&
/* F0, 90..BF, 80..BF, 80..BF */
((byte1 == 0xF0 && byte2 >= 0x90) ||
/* F1..F3, 80..BF, 80..BF, 80..BF */
(byte1 >= 0xF1 && byte1 <= 0xF3) ||
/* F4, 80..8F, 80..BF, 80..BF */
(byte1 == 0xF4 && byte2 <= 0x8F))) {
bytes = 4;
} else {
return err_pos;
}
} else {
return err_pos;
}
} else {
return err_pos;
}
len -= bytes;
err_pos += bytes;
data += bytes;
}
return 0;
}
#ifdef __SSE4_1__
#include <stdint.h>
#include <stdio.h>
#include <x86intrin.h>
int utf8_naive(const unsigned char* data, int len);
static const int8_t _first_len_tbl[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3,
};
static const int8_t _first_range_tbl[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8,
};
static const int8_t _range_min_tbl[] = {
0x00, 0x80, 0x80, 0x80, 0xA0, 0x80, 0x90, 0x80,
0xC2, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
};
static const int8_t _range_max_tbl[] = {
0x7F, 0xBF, 0xBF, 0xBF, 0xBF, 0x9F, 0xBF, 0x8F,
0xF4, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
};
static const int8_t _df_ee_tbl[] = {
0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
};
static const int8_t _ef_fe_tbl[] = {
0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
/* Return 0 on success, -1 on error */
int utf8_range2(const unsigned char* data, int len) {
if (len >= 32) {
__m128i prev_input = _mm_set1_epi8(0);
__m128i prev_first_len = _mm_set1_epi8(0);
const __m128i first_len_tbl =
_mm_loadu_si128((const __m128i*)_first_len_tbl);
const __m128i first_range_tbl =
_mm_loadu_si128((const __m128i*)_first_range_tbl);
const __m128i range_min_tbl =
_mm_loadu_si128((const __m128i*)_range_min_tbl);
const __m128i range_max_tbl =
_mm_loadu_si128((const __m128i*)_range_max_tbl);
const __m128i df_ee_tbl = _mm_loadu_si128((const __m128i*)_df_ee_tbl);
const __m128i ef_fe_tbl = _mm_loadu_si128((const __m128i*)_ef_fe_tbl);
__m128i error = _mm_set1_epi8(0);
while (len >= 32) {
/***************************** block 1 ****************************/
const __m128i input_a = _mm_loadu_si128((const __m128i*)data);
__m128i high_nibbles =
_mm_and_si128(_mm_srli_epi16(input_a, 4), _mm_set1_epi8(0x0F));
__m128i first_len_a = _mm_shuffle_epi8(first_len_tbl, high_nibbles);
__m128i range_a = _mm_shuffle_epi8(first_range_tbl, high_nibbles);
range_a = _mm_or_si128(range_a,
_mm_alignr_epi8(first_len_a, prev_first_len, 15));
__m128i tmp;
tmp = _mm_alignr_epi8(first_len_a, prev_first_len, 14);
tmp = _mm_subs_epu8(tmp, _mm_set1_epi8(1));
range_a = _mm_or_si128(range_a, tmp);
tmp = _mm_alignr_epi8(first_len_a, prev_first_len, 13);
tmp = _mm_subs_epu8(tmp, _mm_set1_epi8(2));
range_a = _mm_or_si128(range_a, tmp);
__m128i shift1, pos, range2;
shift1 = _mm_alignr_epi8(input_a, prev_input, 15);
pos = _mm_sub_epi8(shift1, _mm_set1_epi8(0xEF));
tmp = _mm_subs_epu8(pos, _mm_set1_epi8(0xF0));
range2 = _mm_shuffle_epi8(df_ee_tbl, tmp);
tmp = _mm_adds_epu8(pos, _mm_set1_epi8(0x70));
range2 = _mm_add_epi8(range2, _mm_shuffle_epi8(ef_fe_tbl, tmp));
range_a = _mm_add_epi8(range_a, range2);
__m128i minv = _mm_shuffle_epi8(range_min_tbl, range_a);
__m128i maxv = _mm_shuffle_epi8(range_max_tbl, range_a);
tmp = _mm_or_si128(_mm_cmplt_epi8(input_a, minv),
_mm_cmpgt_epi8(input_a, maxv));
error = _mm_or_si128(error, tmp);
/***************************** block 2 ****************************/
const __m128i input_b = _mm_loadu_si128((const __m128i*)(data + 16));
high_nibbles =
_mm_and_si128(_mm_srli_epi16(input_b, 4), _mm_set1_epi8(0x0F));
__m128i first_len_b = _mm_shuffle_epi8(first_len_tbl, high_nibbles);
__m128i range_b = _mm_shuffle_epi8(first_range_tbl, high_nibbles);
range_b =
_mm_or_si128(range_b, _mm_alignr_epi8(first_len_b, first_len_a, 15));
tmp = _mm_alignr_epi8(first_len_b, first_len_a, 14);
tmp = _mm_subs_epu8(tmp, _mm_set1_epi8(1));
range_b = _mm_or_si128(range_b, tmp);
tmp = _mm_alignr_epi8(first_len_b, first_len_a, 13);
tmp = _mm_subs_epu8(tmp, _mm_set1_epi8(2));
range_b = _mm_or_si128(range_b, tmp);
shift1 = _mm_alignr_epi8(input_b, input_a, 15);
pos = _mm_sub_epi8(shift1, _mm_set1_epi8(0xEF));
tmp = _mm_subs_epu8(pos, _mm_set1_epi8(0xF0));
range2 = _mm_shuffle_epi8(df_ee_tbl, tmp);
tmp = _mm_adds_epu8(pos, _mm_set1_epi8(0x70));
range2 = _mm_add_epi8(range2, _mm_shuffle_epi8(ef_fe_tbl, tmp));
range_b = _mm_add_epi8(range_b, range2);
minv = _mm_shuffle_epi8(range_min_tbl, range_b);
maxv = _mm_shuffle_epi8(range_max_tbl, range_b);
tmp = _mm_or_si128(_mm_cmplt_epi8(input_b, minv),
_mm_cmpgt_epi8(input_b, maxv));
error = _mm_or_si128(error, tmp);
/************************ next iteration **************************/
prev_input = input_b;
prev_first_len = first_len_b;
data += 32;
len -= 32;
}
if (!_mm_testz_si128(error, error)) return -1;
int32_t token4 = _mm_extract_epi32(prev_input, 3);
const int8_t* token = (const int8_t*)&token4;
int lookahead = 0;
if (token[3] > (int8_t)0xBF)
lookahead = 1;
else if (token[2] > (int8_t)0xBF)
lookahead = 2;
else if (token[1] > (int8_t)0xBF)
lookahead = 3;
data -= lookahead;
len += lookahead;
}
return utf8_naive(data, len);
}
#endif
#ifdef __ARM_NEON
#include <arm_neon.h>
#include <stdint.h>
#include <stdio.h>
int utf8_naive(const unsigned char* data, int len);
static const uint8_t _first_len_tbl[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3,
};
static const uint8_t _first_range_tbl[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8,
};
static const uint8_t _range_min_tbl[] = {
0x00, 0x80, 0x80, 0x80, 0xA0, 0x80, 0x90, 0x80,
0xC2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
static const uint8_t _range_max_tbl[] = {
0x7F, 0xBF, 0xBF, 0xBF, 0xBF, 0x9F, 0xBF, 0x8F,
0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const uint8_t _range_adjust_tbl[] = {
2, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
};
/* Return 0 on success, -1 on error */
int utf8_range2(const unsigned char* data, int len) {
if (len >= 32) {
uint8x16_t prev_input = vdupq_n_u8(0);
uint8x16_t prev_first_len = vdupq_n_u8(0);
const uint8x16_t first_len_tbl = vld1q_u8(_first_len_tbl);
const uint8x16_t first_range_tbl = vld1q_u8(_first_range_tbl);
const uint8x16_t range_min_tbl = vld1q_u8(_range_min_tbl);
const uint8x16_t range_max_tbl = vld1q_u8(_range_max_tbl);
const uint8x16x2_t range_adjust_tbl = vld2q_u8(_range_adjust_tbl);
const uint8x16_t const_1 = vdupq_n_u8(1);
const uint8x16_t const_2 = vdupq_n_u8(2);
const uint8x16_t const_e0 = vdupq_n_u8(0xE0);
uint8x16_t error1 = vdupq_n_u8(0);
uint8x16_t error2 = vdupq_n_u8(0);
uint8x16_t error3 = vdupq_n_u8(0);
uint8x16_t error4 = vdupq_n_u8(0);
while (len >= 32) {
/******************* two blocks interleaved **********************/
#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 8)
/* gcc doesn't support vldq1_u8_x2 until version 8 */
const uint8x16_t input_a = vld1q_u8(data);
const uint8x16_t input_b = vld1q_u8(data + 16);
#else
/* Forces a double load on Clang */
const uint8x16x2_t input_pair = vld1q_u8_x2(data);
const uint8x16_t input_a = input_pair.val[0];
const uint8x16_t input_b = input_pair.val[1];
#endif
const uint8x16_t high_nibbles_a = vshrq_n_u8(input_a, 4);
const uint8x16_t high_nibbles_b = vshrq_n_u8(input_b, 4);
const uint8x16_t first_len_a = vqtbl1q_u8(first_len_tbl, high_nibbles_a);
const uint8x16_t first_len_b = vqtbl1q_u8(first_len_tbl, high_nibbles_b);
uint8x16_t range_a = vqtbl1q_u8(first_range_tbl, high_nibbles_a);
uint8x16_t range_b = vqtbl1q_u8(first_range_tbl, high_nibbles_b);
range_a = vorrq_u8(range_a, vextq_u8(prev_first_len, first_len_a, 15));
range_b = vorrq_u8(range_b, vextq_u8(first_len_a, first_len_b, 15));
uint8x16_t tmp1_a, tmp2_a, tmp1_b, tmp2_b;
tmp1_a = vextq_u8(prev_first_len, first_len_a, 14);
tmp1_a = vqsubq_u8(tmp1_a, const_1);
range_a = vorrq_u8(range_a, tmp1_a);
tmp1_b = vextq_u8(first_len_a, first_len_b, 14);
tmp1_b = vqsubq_u8(tmp1_b, const_1);
range_b = vorrq_u8(range_b, tmp1_b);
tmp2_a = vextq_u8(prev_first_len, first_len_a, 13);
tmp2_a = vqsubq_u8(tmp2_a, const_2);
range_a = vorrq_u8(range_a, tmp2_a);
tmp2_b = vextq_u8(first_len_a, first_len_b, 13);
tmp2_b = vqsubq_u8(tmp2_b, const_2);
range_b = vorrq_u8(range_b, tmp2_b);
uint8x16_t shift1_a = vextq_u8(prev_input, input_a, 15);
uint8x16_t pos_a = vsubq_u8(shift1_a, const_e0);
range_a = vaddq_u8(range_a, vqtbl2q_u8(range_adjust_tbl, pos_a));
uint8x16_t shift1_b = vextq_u8(input_a, input_b, 15);
uint8x16_t pos_b = vsubq_u8(shift1_b, const_e0);
range_b = vaddq_u8(range_b, vqtbl2q_u8(range_adjust_tbl, pos_b));
uint8x16_t minv_a = vqtbl1q_u8(range_min_tbl, range_a);
uint8x16_t maxv_a = vqtbl1q_u8(range_max_tbl, range_a);
uint8x16_t minv_b = vqtbl1q_u8(range_min_tbl, range_b);
uint8x16_t maxv_b = vqtbl1q_u8(range_max_tbl, range_b);
error1 = vorrq_u8(error1, vcltq_u8(input_a, minv_a));
error2 = vorrq_u8(error2, vcgtq_u8(input_a, maxv_a));
error3 = vorrq_u8(error3, vcltq_u8(input_b, minv_b));
error4 = vorrq_u8(error4, vcgtq_u8(input_b, maxv_b));
/************************ next iteration *************************/
prev_input = input_b;
prev_first_len = first_len_b;
data += 32;
len -= 32;
}
error1 = vorrq_u8(error1, error2);
error1 = vorrq_u8(error1, error3);
error1 = vorrq_u8(error1, error4);
if (vmaxvq_u8(error1)) return -1;
uint32_t token4;
vst1q_lane_u32(&token4, vreinterpretq_u32_u8(prev_input), 3);
const int8_t* token = (const int8_t*)&token4;
int lookahead = 0;
if (token[3] > (int8_t)0xBF)
lookahead = 1;
else if (token[2] > (int8_t)0xBF)
lookahead = 2;
else if (token[1] > (int8_t)0xBF)
lookahead = 3;
data -= lookahead;
len += lookahead;
}
return utf8_naive(data, len);
}
#endif

@ -0,0 +1,9 @@
#if defined(__ARM_NEON) || defined(__SSE4_1__)
int utf8_range2(const unsigned char* data, int len);
#else
int utf8_naive(const unsigned char* data, int len);
static inline int utf8_range2(const unsigned char* data, int len) {
return utf8_naive(data, len);
}
#endif
Loading…
Cancel
Save