Home | History | Annotate | Download | only in protobuf_c
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2014 Google Inc.  All rights reserved.
      3 // https://developers.google.com/protocol-buffers/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 #include "protobuf.h"
     32 
     33 // -----------------------------------------------------------------------------
     34 // Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
     35 // instances.
     36 // -----------------------------------------------------------------------------
     37 
     38 // This is a hash table from def objects (encoded by converting pointers to
     39 // Ruby integers) to MessageDef/EnumDef instances (as Ruby values).
     40 VALUE upb_def_to_ruby_obj_map;
     41 
     42 VALUE cError;
     43 VALUE cParseError;
     44 
     45 void add_def_obj(const void* def, VALUE value) {
     46   rb_hash_aset(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def), value);
     47 }
     48 
     49 VALUE get_def_obj(const void* def) {
     50   return rb_hash_aref(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def));
     51 }
     52 
     53 // -----------------------------------------------------------------------------
     54 // Utilities.
     55 // -----------------------------------------------------------------------------
     56 
     57 // Raises a Ruby error if |status| is not OK, using its error message.
     58 void check_upb_status(const upb_status* status, const char* msg) {
     59   if (!upb_ok(status)) {
     60     rb_raise(rb_eRuntimeError, "%s: %s\n", msg, upb_status_errmsg(status));
     61   }
     62 }
     63 
     64 // String encodings: we look these up once, at load time, and then cache them
     65 // here.
     66 rb_encoding* kRubyStringUtf8Encoding;
     67 rb_encoding* kRubyStringASCIIEncoding;
     68 rb_encoding* kRubyString8bitEncoding;
     69 
     70 // Ruby-interned string: "descriptor". We use this identifier to store an
     71 // instance variable on message classes we create in order to link them back to
     72 // their descriptors.
     73 //
     74 // We intern this once at module load time then use the interned identifier at
     75 // runtime in order to avoid the cost of repeatedly interning in hot paths.
     76 const char* kDescriptorInstanceVar = "descriptor";
     77 ID descriptor_instancevar_interned;
     78 
     79 // -----------------------------------------------------------------------------
     80 // Initialization/entry point.
     81 // -----------------------------------------------------------------------------
     82 
     83 // This must be named "Init_protobuf_c" because the Ruby module is named
     84 // "protobuf_c" -- the VM looks for this symbol in our .so.
     85 void Init_protobuf_c() {
     86   VALUE google = rb_define_module("Google");
     87   VALUE protobuf = rb_define_module_under(google, "Protobuf");
     88   VALUE internal = rb_define_module_under(protobuf, "Internal");
     89 
     90   descriptor_instancevar_interned = rb_intern(kDescriptorInstanceVar);
     91   DescriptorPool_register(protobuf);
     92   Descriptor_register(protobuf);
     93   FieldDescriptor_register(protobuf);
     94   OneofDescriptor_register(protobuf);
     95   EnumDescriptor_register(protobuf);
     96   MessageBuilderContext_register(internal);
     97   OneofBuilderContext_register(internal);
     98   EnumBuilderContext_register(internal);
     99   Builder_register(internal);
    100   RepeatedField_register(protobuf);
    101   Map_register(protobuf);
    102 
    103   cError = rb_const_get(protobuf, rb_intern("Error"));
    104   cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
    105 
    106   rb_define_singleton_method(protobuf, "deep_copy",
    107                              Google_Protobuf_deep_copy, 1);
    108 
    109   kRubyStringUtf8Encoding = rb_utf8_encoding();
    110   kRubyStringASCIIEncoding = rb_usascii_encoding();
    111   kRubyString8bitEncoding = rb_ascii8bit_encoding();
    112 
    113   upb_def_to_ruby_obj_map = rb_hash_new();
    114   rb_gc_register_address(&upb_def_to_ruby_obj_map);
    115 }
    116