From 10265aa56b22ac4f04e7ba08330138e4507534e4 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Fri, 15 Jul 2011 12:05:43 -0700 Subject: Directory restructure. Includes are now via upb/foo.h. Files specific to the protobuf format are now in upb/pb (the core library is concerned with message definitions, handlers, and byte streams, but knows nothing about any particular serializationf format). --- src/descriptor.proto | 533 --------------------------------- src/descriptor_const.h | 349 ---------------------- src/jit_debug_elf_file.s | 7 - src/upb.c | 122 -------- src/upb.h | 238 --------------- src/upb_atomic.h | 177 ----------- src/upb_bytestream.h | 198 ------------- src/upb_decoder.c | 470 ----------------------------- src/upb_decoder.h | 99 ------- src/upb_decoder_x86.dasc | 694 ------------------------------------------- src/upb_def.c | 754 ----------------------------------------------- src/upb_def.h | 465 ----------------------------- src/upb_descriptor.c | 530 --------------------------------- src/upb_descriptor.h | 67 ----- src/upb_encoder.c | 421 -------------------------- src/upb_encoder.h | 58 ---- src/upb_glue.c | 129 -------- src/upb_glue.h | 62 ---- src/upb_handlers.c | 311 ------------------- src/upb_handlers.h | 373 ----------------------- src/upb_msg.c | 349 ---------------------- src/upb_msg.h | 270 ----------------- src/upb_stdio.c | 166 ----------- src/upb_stdio.h | 71 ----- src/upb_strstream.c | 106 ------- src/upb_strstream.h | 72 ----- src/upb_table.c | 574 ------------------------------------ src/upb_table.h | 225 -------------- src/upb_textprinter.c | 200 ------------- src/upb_textprinter.h | 31 -- src/upb_varint.c | 54 ---- src/upb_varint.h | 142 --------- src/upbc.c | 221 -------------- 33 files changed, 8538 deletions(-) delete mode 100644 src/descriptor.proto delete mode 100644 src/descriptor_const.h delete mode 100644 src/jit_debug_elf_file.s delete mode 100644 src/upb.c delete mode 100644 src/upb.h delete mode 100644 src/upb_atomic.h delete mode 100644 src/upb_bytestream.h delete mode 100644 src/upb_decoder.c delete mode 100644 src/upb_decoder.h delete mode 100644 src/upb_decoder_x86.dasc delete mode 100644 src/upb_def.c delete mode 100644 src/upb_def.h delete mode 100644 src/upb_descriptor.c delete mode 100644 src/upb_descriptor.h delete mode 100644 src/upb_encoder.c delete mode 100644 src/upb_encoder.h delete mode 100644 src/upb_glue.c delete mode 100644 src/upb_glue.h delete mode 100644 src/upb_handlers.c delete mode 100644 src/upb_handlers.h delete mode 100644 src/upb_msg.c delete mode 100644 src/upb_msg.h delete mode 100644 src/upb_stdio.c delete mode 100644 src/upb_stdio.h delete mode 100644 src/upb_strstream.c delete mode 100644 src/upb_strstream.h delete mode 100644 src/upb_table.c delete mode 100644 src/upb_table.h delete mode 100644 src/upb_textprinter.c delete mode 100644 src/upb_textprinter.h delete mode 100644 src/upb_varint.c delete mode 100644 src/upb_varint.h delete mode 100644 src/upbc.c (limited to 'src') diff --git a/src/descriptor.proto b/src/descriptor.proto deleted file mode 100644 index 233f879..0000000 --- a/src/descriptor.proto +++ /dev/null @@ -1,533 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. -// -// The messages in this file describe the definitions found in .proto files. -// A valid .proto file can be translated directly to a FileDescriptorProto -// without any other information (e.g. without reading its imports). - - - -package google.protobuf; -option java_package = "com.google.protobuf"; -option java_outer_classname = "DescriptorProtos"; - -// descriptor.proto must be optimized for speed because reflection-based -// algorithms don't work during bootstrapping. -option optimize_for = SPEED; - -// The protocol compiler can output a FileDescriptorSet containing the .proto -// files it parses. -message FileDescriptorSet { - repeated FileDescriptorProto file = 1; -} - -// Describes a complete .proto file. -message FileDescriptorProto { - optional string name = 1; // file name, relative to root of source tree - optional string package = 2; // e.g. "foo", "foo.bar", etc. - - // Names of files imported by this file. - repeated string dependency = 3; - - // All top-level definitions in this file. - repeated DescriptorProto message_type = 4; - repeated EnumDescriptorProto enum_type = 5; - repeated ServiceDescriptorProto service = 6; - repeated FieldDescriptorProto extension = 7; - - optional FileOptions options = 8; - - // This field contains optional information about the original source code. - // You may safely remove this entire field whithout harming runtime - // functionality of the descriptors -- the information is needed only by - // development tools. - optional SourceCodeInfo source_code_info = 9; -} - -// Describes a message type. -message DescriptorProto { - optional string name = 1; - - repeated FieldDescriptorProto field = 2; - repeated FieldDescriptorProto extension = 6; - - repeated DescriptorProto nested_type = 3; - repeated EnumDescriptorProto enum_type = 4; - - message ExtensionRange { - optional int32 start = 1; - optional int32 end = 2; - } - repeated ExtensionRange extension_range = 5; - - optional MessageOptions options = 7; -} - -// Describes a field within a message. -message FieldDescriptorProto { - enum Type { - // 0 is reserved for errors. - // Order is weird for historical reasons. - TYPE_DOUBLE = 1; - TYPE_FLOAT = 2; - TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT64 if negative - // values are likely. - TYPE_UINT64 = 4; - TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT32 if negative - // values are likely. - TYPE_FIXED64 = 6; - TYPE_FIXED32 = 7; - TYPE_BOOL = 8; - TYPE_STRING = 9; - TYPE_GROUP = 10; // Tag-delimited aggregate. - TYPE_MESSAGE = 11; // Length-delimited aggregate. - - // New in version 2. - TYPE_BYTES = 12; - TYPE_UINT32 = 13; - TYPE_ENUM = 14; - TYPE_SFIXED32 = 15; - TYPE_SFIXED64 = 16; - TYPE_SINT32 = 17; // Uses ZigZag encoding. - TYPE_SINT64 = 18; // Uses ZigZag encoding. - }; - - enum Label { - // 0 is reserved for errors - LABEL_OPTIONAL = 1; - LABEL_REQUIRED = 2; - LABEL_REPEATED = 3; - // TODO(sanjay): Should we add LABEL_MAP? - }; - - optional string name = 1; - optional int32 number = 3; - optional Label label = 4; - - // If type_name is set, this need not be set. If both this and type_name - // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. - optional Type type = 5; - - // For message and enum types, this is the name of the type. If the name - // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping - // rules are used to find the type (i.e. first the nested types within this - // message are searched, then within the parent, on up to the root - // namespace). - optional string type_name = 6; - - // For extensions, this is the name of the type being extended. It is - // resolved in the same manner as type_name. - optional string extendee = 2; - - // For numeric types, contains the original text representation of the value. - // For booleans, "true" or "false". - // For strings, contains the default text contents (not escaped in any way). - // For bytes, contains the C escaped value. All bytes >= 128 are escaped. - // TODO(kenton): Base-64 encode? - optional string default_value = 7; - - optional FieldOptions options = 8; -} - -// Describes an enum type. -message EnumDescriptorProto { - optional string name = 1; - - repeated EnumValueDescriptorProto value = 2; - - optional EnumOptions options = 3; -} - -// Describes a value within an enum. -message EnumValueDescriptorProto { - optional string name = 1; - optional int32 number = 2; - - optional EnumValueOptions options = 3; -} - -// Describes a service. -message ServiceDescriptorProto { - optional string name = 1; - repeated MethodDescriptorProto method = 2; - - optional ServiceOptions options = 3; -} - -// Describes a method of a service. -message MethodDescriptorProto { - optional string name = 1; - - // Input and output type names. These are resolved in the same way as - // FieldDescriptorProto.type_name, but must refer to a message type. - optional string input_type = 2; - optional string output_type = 3; - - optional MethodOptions options = 4; -} - -// =================================================================== -// Options - -// Each of the definitions above may have "options" attached. These are -// just annotations which may cause code to be generated slightly differently -// or may contain hints for code that manipulates protocol messages. -// -// Clients may define custom options as extensions of the *Options messages. -// These extensions may not yet be known at parsing time, so the parser cannot -// store the values in them. Instead it stores them in a field in the *Options -// message called uninterpreted_option. This field must have the same name -// across all *Options messages. We then use this field to populate the -// extensions when we build a descriptor, at which point all protos have been -// parsed and so all extensions are known. -// -// Extension numbers for custom options may be chosen as follows: -// * For options which will only be used within a single application or -// organization, or for experimental options, use field numbers 50000 -// through 99999. It is up to you to ensure that you do not use the -// same number for multiple options. -// * For options which will be published and used publicly by multiple -// independent entities, e-mail kenton@google.com to reserve extension -// numbers. Simply tell me how many you need and I'll send you back a -// set of numbers to use -- there's no need to explain how you intend to -// use them. If this turns out to be popular, a web service will be set up -// to automatically assign option numbers. - - -message FileOptions { - - // Sets the Java package where classes generated from this .proto will be - // placed. By default, the proto package is used, but this is often - // inappropriate because proto packages do not normally start with backwards - // domain names. - optional string java_package = 1; - - - // If set, all the classes from the .proto file are wrapped in a single - // outer class with the given name. This applies to both Proto1 - // (equivalent to the old "--one_java_file" option) and Proto2 (where - // a .proto always translates to a single class, but you may want to - // explicitly choose the class name). - optional string java_outer_classname = 8; - - // If set true, then the Java code generator will generate a separate .java - // file for each top-level message, enum, and service defined in the .proto - // file. Thus, these types will *not* be nested inside the outer class - // named by java_outer_classname. However, the outer class will still be - // generated to contain the file's getDescriptor() method as well as any - // top-level extensions defined in the file. - optional bool java_multiple_files = 10 [default=false]; - - // If set true, then the Java code generator will generate equals() and - // hashCode() methods for all messages defined in the .proto file. This is - // purely a speed optimization, as the AbstractMessage base class includes - // reflection-based implementations of these methods. - optional bool java_generate_equals_and_hash = 20 [default=false]; - - // Generated classes can be optimized for speed or code size. - enum OptimizeMode { - SPEED = 1; // Generate complete code for parsing, serialization, - // etc. - CODE_SIZE = 2; // Use ReflectionOps to implement these methods. - LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. - } - optional OptimizeMode optimize_for = 9 [default=SPEED]; - - - - - // Should generic services be generated in each language? "Generic" services - // are not specific to any particular RPC system. They are generated by the - // main code generators in each language (without additional plugins). - // Generic services were the only kind of service generation supported by - // early versions of proto2. - // - // Generic services are now considered deprecated in favor of using plugins - // that generate code specific to your particular RPC system. Therefore, - // these default to false. Old code which depends on generic services should - // explicitly set them to true. - optional bool cc_generic_services = 16 [default=false]; - optional bool java_generic_services = 17 [default=false]; - optional bool py_generic_services = 18 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MessageOptions { - // Set true to use the old proto1 MessageSet wire format for extensions. - // This is provided for backwards-compatibility with the MessageSet wire - // format. You should not use this for any other reason: It's less - // efficient, has fewer features, and is more complicated. - // - // The message must be defined exactly as follows: - // message Foo { - // option message_set_wire_format = true; - // extensions 4 to max; - // } - // Note that the message cannot have any defined fields; MessageSets only - // have extensions. - // - // All extensions of your type must be singular messages; e.g. they cannot - // be int32s, enums, or repeated messages. - // - // Because this is an option, the above two restrictions are not enforced by - // the protocol compiler. - optional bool message_set_wire_format = 1 [default=false]; - - // Disables the generation of the standard "descriptor()" accessor, which can - // conflict with a field of the same name. This is meant to make migration - // from proto1 easier; new code should avoid fields named "descriptor". - optional bool no_standard_descriptor_accessor = 2 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message FieldOptions { - // The ctype option instructs the C++ code generator to use a different - // representation of the field than it normally would. See the specific - // options below. This option is not yet implemented in the open source - // release -- sorry, we'll try to include it in a future version! - optional CType ctype = 1 [default = STRING]; - enum CType { - // Default mode. - STRING = 0; - - CORD = 1; - - STRING_PIECE = 2; - } - // The packed option can be enabled for repeated primitive fields to enable - // a more efficient representation on the wire. Rather than repeatedly - // writing the tag and type for each element, the entire array is encoded as - // a single length-delimited blob. - optional bool packed = 2; - - - // Is this field deprecated? - // Depending on the target platform, this can emit Deprecated annotations - // for accessors, or it will be completely ignored; in the very least, this - // is a formalization for deprecating fields. - optional bool deprecated = 3 [default=false]; - - // EXPERIMENTAL. DO NOT USE. - // For "map" fields, the name of the field in the enclosed type that - // is the key for this map. For example, suppose we have: - // message Item { - // required string name = 1; - // required string value = 2; - // } - // message Config { - // repeated Item items = 1 [experimental_map_key="name"]; - // } - // In this situation, the map key for Item will be set to "name". - // TODO: Fully-implement this, then remove the "experimental_" prefix. - optional string experimental_map_key = 9; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumOptions { - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumValueOptions { - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message ServiceOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MethodOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -// A message representing a option the parser does not recognize. This only -// appears in options protos created by the compiler::Parser class. -// DescriptorPool resolves these when building Descriptor objects. Therefore, -// options protos in descriptor objects (e.g. returned by Descriptor::options(), -// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions -// in them. -message UninterpretedOption { - // The name of the uninterpreted option. Each string represents a segment in - // a dot-separated name. is_extension is true iff a segment represents an - // extension (denoted with parentheses in options specs in .proto files). - // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents - // "foo.(bar.baz).qux". - message NamePart { - required string name_part = 1; - required bool is_extension = 2; - } - repeated NamePart name = 2; - - // The value of the uninterpreted option, in whatever type the tokenizer - // identified it as during parsing. Exactly one of these should be set. - optional string identifier_value = 3; - optional uint64 positive_int_value = 4; - optional int64 negative_int_value = 5; - optional double double_value = 6; - optional bytes string_value = 7; - optional string aggregate_value = 8; -} - -// =================================================================== -// Optional source code info - -// Encapsulates information about the original source file from which a -// FileDescriptorProto was generated. -message SourceCodeInfo { - // A Location identifies a piece of source code in a .proto file which - // corresponds to a particular definition. This information is intended - // to be useful to IDEs, code indexers, documentation generators, and similar - // tools. - // - // For example, say we have a file like: - // message Foo { - // optional string foo = 1; - // } - // Let's look at just the field definition: - // optional string foo = 1; - // ^ ^^ ^^ ^ ^^^ - // a bc de f ghi - // We have the following locations: - // span path represents - // [a,i) [ 4, 0, 2, 0 ] The whole field definition. - // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). - // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). - // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). - // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). - // - // Notes: - // - A location may refer to a repeated field itself (i.e. not to any - // particular index within it). This is used whenever a set of elements are - // logically enclosed in a single code segment. For example, an entire - // extend block (possibly containing multiple extension definitions) will - // have an outer location whose path refers to the "extensions" repeated - // field without an index. - // - Multiple locations may have the same path. This happens when a single - // logical declaration is spread out across multiple places. The most - // obvious example is the "extend" block again -- there may be multiple - // extend blocks in the same scope, each of which will have the same path. - // - A location's span is not always a subset of its parent's span. For - // example, the "extendee" of an extension declaration appears at the - // beginning of the "extend" block and is shared by all extensions within - // the block. - // - Just because a location's span is a subset of some other location's span - // does not mean that it is a descendent. For example, a "group" defines - // both a type and a field in a single declaration. Thus, the locations - // corresponding to the type and field and their components will overlap. - // - Code which tries to interpret locations should probably be designed to - // ignore those that it doesn't understand, as more types of locations could - // be recorded in the future. - repeated Location location = 1; - message Location { - // Identifies which part of the FileDescriptorProto was defined at this - // location. - // - // Each element is a field number or an index. They form a path from - // the root FileDescriptorProto to the place where the definition. For - // example, this path: - // [ 4, 3, 2, 7, 1 ] - // refers to: - // file.message_type(3) // 4, 3 - // .field(7) // 2, 7 - // .name() // 1 - // This is because FileDescriptorProto.message_type has field number 4: - // repeated DescriptorProto message_type = 4; - // and DescriptorProto.field has field number 2: - // repeated FieldDescriptorProto field = 2; - // and FieldDescriptorProto.name has field number 1: - // optional string name = 1; - // - // Thus, the above path gives the location of a field name. If we removed - // the last element: - // [ 4, 3, 2, 7 ] - // this path refers to the whole field declaration (from the beginning - // of the label to the terminating semicolon). - repeated int32 path = 1 [packed=true]; - - // Always has exactly three or four elements: start line, start column, - // end line (optional, otherwise assumed same as start line), end column. - // These are packed into a single field for efficiency. Note that line - // and column numbers are zero-based -- typically you will want to add - // 1 to each before displaying to a user. - repeated int32 span = 2 [packed=true]; - - // TODO(kenton): Record comments appearing before and after the - // declaration. - } -} diff --git a/src/descriptor_const.h b/src/descriptor_const.h deleted file mode 100644 index 228c95a..0000000 --- a/src/descriptor_const.h +++ /dev/null @@ -1,349 +0,0 @@ -/* This file was generated by upbc (the upb compiler). Do not edit. */ - -#ifndef SRC_DESCRIPTOR_CONST_C -#define SRC_DESCRIPTOR_CONST_C - -#ifdef __cplusplus -extern "C" { -#endif - -/* Enums. */ - -typedef enum google_protobuf_FieldOptions_CType { - GOOGLE_PROTOBUF_FIELDOPTIONS_STRING = 0, - GOOGLE_PROTOBUF_FIELDOPTIONS_STRING_PIECE = 2, - GOOGLE_PROTOBUF_FIELDOPTIONS_CORD = 1 -} google_protobuf_FieldOptions_CType; - -typedef enum google_protobuf_FieldDescriptorProto_Type { - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE = 1, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT = 2, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64 = 3, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64 = 4, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 = 5, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64 = 6, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32 = 7, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL = 8, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING = 9, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP = 10, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE = 11, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES = 12, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM = 14, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32 = 15, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64 = 16, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32 = 17, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64 = 18 -} google_protobuf_FieldDescriptorProto_Type; - -typedef enum google_protobuf_FieldDescriptorProto_Label { - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_OPTIONAL = 1, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REQUIRED = 2, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED = 3 -} google_protobuf_FieldDescriptorProto_Label; - -typedef enum google_protobuf_FileOptions_OptimizeMode { - GOOGLE_PROTOBUF_FILEOPTIONS_SPEED = 1, - GOOGLE_PROTOBUF_FILEOPTIONS_CODE_SIZE = 2, - GOOGLE_PROTOBUF_FILEOPTIONS_LITE_RUNTIME = 3 -} google_protobuf_FileOptions_OptimizeMode; - -/* Constants for field names and numbers. */ - -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDNUM 1 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDNAME "file" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDNUM 1 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDNAME "name" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDNUM 2 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDNAME "field" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDNUM 3 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDNAME "nested_type" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDNUM 4 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDNAME "enum_type" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE__FIELDNUM 5 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE__FIELDNAME "extension_range" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION__FIELDNUM 6 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION__FIELDNAME "extension" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS__FIELDNUM 7 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS__FIELDNAME "options" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH__FIELDNUM 1 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH__FIELDNAME "path" -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH__FIELDTYPE 5 - -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN__FIELDNUM 2 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN__FIELDNAME "span" -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN__FIELDTYPE 5 - -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME__FIELDNUM 2 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME__FIELDNAME "name" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE__FIELDNUM 3 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE__FIELDNAME "identifier_value" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE__FIELDNUM 4 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE__FIELDNAME "positive_int_value" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE__FIELDTYPE 4 - -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE__FIELDNUM 5 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE__FIELDNAME "negative_int_value" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE__FIELDTYPE 3 - -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE__FIELDNUM 6 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE__FIELDNAME "double_value" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE__FIELDTYPE 1 - -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE__FIELDNUM 7 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE__FIELDNAME "string_value" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE__FIELDTYPE 12 - -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE__FIELDNUM 8 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE__FIELDNAME "aggregate_value" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME__FIELDNUM 1 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME__FIELDNAME "name" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDNUM 2 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDNAME "package" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY__FIELDNUM 3 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY__FIELDNAME "dependency" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDNUM 4 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDNAME "message_type" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDNUM 5 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDNAME "enum_type" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE__FIELDNUM 6 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE__FIELDNAME "service" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION__FIELDNUM 7 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION__FIELDNAME "extension" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS__FIELDNUM 8 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS__FIELDNAME "options" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO__FIELDNUM 9 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO__FIELDNAME "source_code_info" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME__FIELDNUM 1 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME__FIELDNAME "name" -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE__FIELDNUM 2 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE__FIELDNAME "input_type" -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE__FIELDNUM 3 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE__FIELDNAME "output_type" -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS__FIELDNUM 4 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS__FIELDNAME "options" -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDNUM 1 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDNAME "name" -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDNUM 2 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDNAME "value" -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS__FIELDNUM 3 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS__FIELDNAME "options" -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDNUM 1 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDNAME "name" -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDNUM 2 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDNAME "number" -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDTYPE 5 - -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS__FIELDNUM 3 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS__FIELDNAME "options" -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME__FIELDNUM 1 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME__FIELDNAME "name" -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD__FIELDNUM 2 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD__FIELDNAME "method" -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS__FIELDNUM 3 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS__FIELDNAME "options" -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART__FIELDNUM 1 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART__FIELDNAME "name_part" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION__FIELDNUM 2 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION__FIELDNAME "is_extension" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION__FIELDTYPE 8 - -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION__FIELDNUM 1 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION__FIELDNAME "location" -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START__FIELDNUM 1 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START__FIELDNAME "start" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START__FIELDTYPE 5 - -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END__FIELDNUM 2 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END__FIELDNAME "end" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END__FIELDTYPE 5 - -#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE__FIELDNUM 1 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE__FIELDNAME "ctype" -#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE__FIELDTYPE 14 - -#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED__FIELDNUM 2 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED__FIELDNAME "packed" -#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED__FIELDTYPE 8 - -#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED__FIELDNUM 3 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED__FIELDNAME "deprecated" -#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED__FIELDTYPE 8 - -#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY__FIELDNUM 9 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY__FIELDNAME "experimental_map_key" -#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE__FIELDNUM 1 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE__FIELDNAME "java_package" -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME__FIELDNUM 8 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME__FIELDNAME "java_outer_classname" -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR__FIELDNUM 9 -#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR__FIELDNAME "optimize_for" -#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR__FIELDTYPE 14 - -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES__FIELDNUM 10 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES__FIELDNAME "java_multiple_files" -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES__FIELDTYPE 8 - -#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES__FIELDNUM 16 -#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES__FIELDNAME "cc_generic_services" -#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES__FIELDTYPE 8 - -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES__FIELDNUM 17 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES__FIELDNAME "java_generic_services" -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES__FIELDTYPE 8 - -#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES__FIELDNUM 18 -#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES__FIELDNAME "py_generic_services" -#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES__FIELDTYPE 8 - -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH__FIELDNUM 20 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH__FIELDNAME "java_generate_equals_and_hash" -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH__FIELDTYPE 8 - -#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 -#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT__FIELDNUM 1 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT__FIELDNAME "message_set_wire_format" -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT__FIELDTYPE 8 - -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR__FIELDNUM 2 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR__FIELDNAME "no_standard_descriptor_accessor" -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR__FIELDTYPE 8 - -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 -#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDNUM 1 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDNAME "name" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE__FIELDNUM 2 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE__FIELDNAME "extendee" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDNUM 3 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDNAME "number" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDTYPE 5 - -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDNUM 4 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDNAME "label" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDTYPE 14 - -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDNUM 5 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDNAME "type" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDTYPE 14 - -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDNUM 6 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDNAME "type_name" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDNUM 7 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDNAME "default_value" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDTYPE 9 - -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS__FIELDNUM 8 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS__FIELDNAME "options" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 -#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 - -#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 -#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* SRC_DESCRIPTOR_CONST_C */ diff --git a/src/jit_debug_elf_file.s b/src/jit_debug_elf_file.s deleted file mode 100644 index 0b74630..0000000 --- a/src/jit_debug_elf_file.s +++ /dev/null @@ -1,7 +0,0 @@ - .file "JIT mcode" - .text -upb_jit_compiled_decoder: - .globl upb_jit_compiled_decoder - .size upb_jit_compiled_decoder, 0x321 - .type upb_jit_compiled_decoder STT_FUNC - .space 0x321 diff --git a/src/upb.c b/src/upb.c deleted file mode 100644 index 0f3ea18..0000000 --- a/src/upb.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ - -#include -#include -#include -#include -#include -#include "descriptor_const.h" -#include "upb.h" -#include "upb_bytestream.h" - -#define alignof(t) offsetof(struct { char c; t x; }, x) -#define TYPE_INFO(wire_type, ctype, inmemory_type) \ - {alignof(ctype), sizeof(ctype), wire_type, UPB_TYPE(inmemory_type), #ctype}, - -const upb_type_info upb_types[] = { - TYPE_INFO(UPB_WIRE_TYPE_END_GROUP, void*, MESSAGE) // ENDGROUP (fake) - TYPE_INFO(UPB_WIRE_TYPE_64BIT, double, DOUBLE) // DOUBLE - TYPE_INFO(UPB_WIRE_TYPE_32BIT, float, FLOAT) // FLOAT - TYPE_INFO(UPB_WIRE_TYPE_VARINT, int64_t, INT64) // INT64 - TYPE_INFO(UPB_WIRE_TYPE_VARINT, uint64_t, UINT64) // UINT64 - TYPE_INFO(UPB_WIRE_TYPE_VARINT, int32_t, INT32) // INT32 - TYPE_INFO(UPB_WIRE_TYPE_64BIT, uint64_t, UINT64) // FIXED64 - TYPE_INFO(UPB_WIRE_TYPE_32BIT, uint32_t, UINT32) // FIXED32 - TYPE_INFO(UPB_WIRE_TYPE_VARINT, bool, BOOL) // BOOL - TYPE_INFO(UPB_WIRE_TYPE_DELIMITED, void*, STRING) // STRING - TYPE_INFO(UPB_WIRE_TYPE_START_GROUP, void*, MESSAGE) // GROUP - TYPE_INFO(UPB_WIRE_TYPE_DELIMITED, void*, MESSAGE) // MESSAGE - TYPE_INFO(UPB_WIRE_TYPE_DELIMITED, void*, STRING) // BYTES - TYPE_INFO(UPB_WIRE_TYPE_VARINT, uint32_t, UINT32) // UINT32 - TYPE_INFO(UPB_WIRE_TYPE_VARINT, uint32_t, INT32) // ENUM - TYPE_INFO(UPB_WIRE_TYPE_32BIT, int32_t, INT32) // SFIXED32 - TYPE_INFO(UPB_WIRE_TYPE_64BIT, int64_t, INT64) // SFIXED64 - TYPE_INFO(UPB_WIRE_TYPE_VARINT, int32_t, INT32) // SINT32 - TYPE_INFO(UPB_WIRE_TYPE_VARINT, int64_t, INT64) // SINT64 - TYPE_INFO(UPB_WIRE_TYPE_END_GROUP, void*, INT64) // SINT64 -}; - -#ifdef NDEBUG -upb_value UPB_NO_VALUE = {{0}}; -#else -upb_value UPB_NO_VALUE = {{0}, -1}; -#endif - -void upb_status_init(upb_status *status) { - status->buf = NULL; - upb_status_clear(status); -} - -void upb_status_uninit(upb_status *status) { - free(status->buf); -} - -void upb_status_setf(upb_status *s, enum upb_status_code code, - const char *msg, ...) { - s->code = code; - va_list args; - va_start(args, msg); - upb_vrprintf(&s->buf, &s->bufsize, 0, msg, args); - va_end(args); - s->str = s->buf; -} - -void upb_status_copy(upb_status *to, upb_status *from) { - to->code = from->code; - if (from->str) { - if (to->bufsize < from->bufsize) { - to->bufsize = from->bufsize; - to->buf = realloc(to->buf, to->bufsize); - to->str = to->buf; - } - memcpy(to->str, from->str, from->bufsize); - } else { - to->str = NULL; - } -} - -void upb_status_clear(upb_status *status) { - status->code = UPB_OK; - status->str = NULL; -} - -void upb_status_print(upb_status *status, FILE *f) { - if(status->str) { - fprintf(f, "code: %d, msg: %s\n", status->code, status->str); - } else { - fprintf(f, "code: %d, no msg\n", status->code); - } -} - -void upb_status_fromerrno(upb_status *status) { - upb_status_setf(status, UPB_ERROR, "%s", strerror(errno)); -} - -int upb_vrprintf(char **buf, size_t *size, size_t ofs, - const char *fmt, va_list args) { - // Try once without reallocating. We have to va_copy because we might have - // to call vsnprintf again. - uint32_t len = *size - ofs; - va_list args_copy; - va_copy(args_copy, args); - uint32_t true_len = vsnprintf(*buf + ofs, len, fmt, args_copy); - va_end(args_copy); - - // Resize to be the correct size. - if (true_len >= len) { - // Need to print again, because some characters were truncated. vsnprintf - // will not write the entire string unless you give it space to store the - // NULL terminator also. - while (*size < (ofs + true_len + 1)) *size = UPB_MAX(*size * 2, 2); - char *newbuf = realloc(*buf, *size); - if (!newbuf) return -1; - vsnprintf(newbuf + ofs, true_len + 1, fmt, args); - *buf = newbuf; - } - return true_len; -} diff --git a/src/upb.h b/src/upb.h deleted file mode 100644 index b15340e..0000000 --- a/src/upb.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * This file contains shared definitions that are widely used across upb. - */ - -#ifndef UPB_H_ -#define UPB_H_ - -#include -#include -#include // only for size_t. -#include -#include "descriptor_const.h" -#include "upb_atomic.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// inline if possible, emit standalone code if required. -#ifndef INLINE -#define INLINE static inline -#endif - -#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) -#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) -#define UPB_INDEX(base, i, m) (void*)((char*)(base) + ((i)*(m))) - -INLINE void nop_printf(const char *fmt, ...) { (void)fmt; } - -#ifdef NDEBUG -#define DEBUGPRINTF nop_printf -#else -#define DEBUGPRINTF printf -#endif - -// Rounds val up to the next multiple of align. -INLINE size_t upb_align_up(size_t val, size_t align) { - return val % align == 0 ? val : val + align - (val % align); -} - -// The maximum that any submessages can be nested. Matches proto2's limit. -// At the moment this specifies the size of several statically-sized arrays -// and therefore setting it high will cause more memory to be used. Will -// be replaced by a runtime-configurable limit and dynamically-resizing arrays. -// TODO: make this a runtime-settable property of upb_handlers. -#define UPB_MAX_NESTING 64 - -// The maximum number of fields that any one .proto type can have. Note that -// this is very different than the max field number. It is hard to imagine a -// scenario where more than 2k fields (each with its own name and field number) -// makes sense. The .proto file to describe it would be 2000 lines long and -// contain 2000 unique names. -// -// With this limit we can store a has-bit offset in 8 bits (2**8 * 8 = 2048) -// and we can store a value offset in 16 bits, since the maximum message -// size is 16,640 bytes (2**8 has-bits + 2048 * 8-byte value). Note that -// strings and arrays are not counted in this, only the *pointer* to them is. -// An individual string or array is unaffected by this 16k byte limit. -#define UPB_MAX_FIELDS (2048) - -// Nested type names are separated by periods. -#define UPB_SYMBOL_SEPARATOR '.' - -// The longest chain that mutually-recursive types are allowed to form. For -// example, this is a type cycle of length 2: -// message A { -// B b = 1; -// } -// message B { -// A a = 1; -// } -#define UPB_MAX_TYPE_CYCLE_LEN 16 - -// The maximum depth that the type graph can have. Note that this setting does -// not automatically constrain UPB_MAX_NESTING, because type cycles allow for -// unlimited nesting if we do not limit it. Many algorithms in upb call -// recursive functions that traverse the type graph, so we must limit this to -// avoid blowing the C stack. -#define UPB_MAX_TYPE_DEPTH 64 - - -/* Fundamental types and type constants. **************************************/ - -// A list of types as they are encoded on-the-wire. -enum upb_wire_type { - UPB_WIRE_TYPE_VARINT = 0, - UPB_WIRE_TYPE_64BIT = 1, - UPB_WIRE_TYPE_DELIMITED = 2, - UPB_WIRE_TYPE_START_GROUP = 3, - UPB_WIRE_TYPE_END_GROUP = 4, - UPB_WIRE_TYPE_32BIT = 5, -}; - -// Type of a field as defined in a .proto file. eg. string, int32, etc. The -// integers that represent this are defined by descriptor.proto. Note that -// descriptor.proto reserves "0" for errors, and we use it to represent -// exceptional circumstances. -typedef uint8_t upb_fieldtype_t; - -// For referencing the type constants tersely. -#define UPB_TYPE(type) GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ ## type -#define UPB_LABEL(type) GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_ ## type - -// Info for a given field type. -typedef struct { - uint8_t align; - uint8_t size; - uint8_t native_wire_type; - uint8_t inmemory_type; // For example, INT32, SINT32, and SFIXED32 -> INT32 - char *ctype; -} upb_type_info; - -// A static array of info about all of the field types, indexed by type number. -extern const upb_type_info upb_types[]; - - -/* upb_value ******************************************************************/ - -struct _upb_strref; -struct _upb_fielddef; - -// Special constants for the upb_value.type field. These must not conflict -// with any members of FieldDescriptorProto.Type. -#define UPB_TYPE_ENDGROUP 0 -#define UPB_VALUETYPE_FIELDDEF 32 -#define UPB_VALUETYPE_PTR 33 - -// A single .proto value. The owner must have an out-of-band way of knowing -// the type, so that it knows which union member to use. -typedef struct { - union { - uint64_t uint64; - double _double; - float _float; - int32_t int32; - int64_t int64; - uint32_t uint32; - bool _bool; - struct _upb_strref *strref; - struct _upb_fielddef *fielddef; - void *_void; - } val; - -#ifndef NDEBUG - // In debug mode we carry the value type around also so we can check accesses - // to be sure the right member is being read. - char type; -#endif -} upb_value; - -#ifdef NDEBUG -#define SET_TYPE(dest, val) -#else -#define SET_TYPE(dest, val) dest = val -#endif - -#define UPB_VALUE_ACCESSORS(name, membername, ctype, proto_type) \ - INLINE ctype upb_value_get ## name(upb_value val) { \ - assert(val.type == proto_type); \ - return val.val.membername; \ - } \ - INLINE void upb_value_set ## name(upb_value *val, ctype cval) { \ - SET_TYPE(val->type, proto_type); \ - val->val.membername = cval; \ - } -UPB_VALUE_ACCESSORS(double, _double, double, UPB_TYPE(DOUBLE)); -UPB_VALUE_ACCESSORS(float, _float, float, UPB_TYPE(FLOAT)); -UPB_VALUE_ACCESSORS(int32, int32, int32_t, UPB_TYPE(INT32)); -UPB_VALUE_ACCESSORS(int64, int64, int64_t, UPB_TYPE(INT64)); -UPB_VALUE_ACCESSORS(uint32, uint32, uint32_t, UPB_TYPE(UINT32)); -UPB_VALUE_ACCESSORS(uint64, uint64, uint64_t, UPB_TYPE(UINT64)); -UPB_VALUE_ACCESSORS(bool, _bool, bool, UPB_TYPE(BOOL)); -UPB_VALUE_ACCESSORS(strref, strref, struct _upb_strref*, UPB_TYPE(STRING)); -UPB_VALUE_ACCESSORS(fielddef, fielddef, struct _upb_fielddef*, UPB_VALUETYPE_FIELDDEF); -UPB_VALUE_ACCESSORS(ptr, _void, void*, UPB_VALUETYPE_PTR); - -extern upb_value UPB_NO_VALUE; - - -/* upb_status *****************************************************************/ - -// Status codes used as a return value. Codes >0 are not fatal and can be -// resumed. -enum upb_status_code { - // The operation completed successfully. - UPB_OK = 0, - - // The bytesrc is at EOF and all data was read successfully. - UPB_EOF = 1, - - // A read or write from a streaming src/sink could not be completed right now. - UPB_TRYAGAIN = 2, - - // An unrecoverable error occurred. - UPB_ERROR = -1, -}; - -// TODO: consider adding error space and code, to let ie. errno be stored -// as a proper code, or application-specific error codes. -typedef struct { - char code; - char *str; // NULL when no message is present. NULL-terminated. - char *buf; // Owned by the status. - size_t bufsize; -} upb_status; - -#define UPB_STATUS_INIT {UPB_OK, NULL, NULL, 0} - -void upb_status_init(upb_status *status); -void upb_status_uninit(upb_status *status); - -INLINE bool upb_ok(upb_status *status) { return status->code == UPB_OK; } -INLINE bool upb_iseof(upb_status *status) { return status->code == UPB_EOF; } - -void upb_status_fromerrno(upb_status *status); -void upb_status_print(upb_status *status, FILE *f); -void upb_status_clear(upb_status *status); -void upb_status_setf(upb_status *status, enum upb_status_code code, - const char *fmt, ...); -void upb_status_copy(upb_status *to, upb_status *from); - -// Like vaprintf, but uses *buf (which can be NULL) as a starting point and -// reallocates it only if the new value will not fit. "size" is updated to -// reflect the allocated size of the buffer. Returns false on memory alloc -// failure. -int upb_vrprintf(char **buf, size_t *size, size_t ofs, - const char *fmt, va_list args); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_H_ */ diff --git a/src/upb_atomic.h b/src/upb_atomic.h deleted file mode 100644 index 53501b5..0000000 --- a/src/upb_atomic.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * Only a very small part of upb is thread-safe. Notably, individual - * messages, arrays, and strings are *not* thread safe for mutating. - * However, we do make message *metadata* such as upb_msgdef and - * upb_context thread-safe, and their ownership is tracked via atomic - * refcounting. This header implements the small number of atomic - * primitives required to support this. The primitives we implement - * are: - * - * - a reader/writer lock (wrappers around platform-provided mutexes). - * - an atomic refcount. - */ - -#ifndef UPB_ATOMIC_H_ -#define UPB_ATOMIC_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* inline if possible, emit standalone code if required. */ -#ifndef INLINE -#define INLINE static inline -#endif - -// Until this stuff is actually working, make thread-unsafe the default. -#define UPB_THREAD_UNSAFE - -#ifdef UPB_THREAD_UNSAFE - -/* Non-thread-safe implementations. ******************************************/ - -typedef struct { - int v; -} upb_atomic_t; - -#define UPB_ATOMIC_INIT(x) {x} - -INLINE void upb_atomic_init(upb_atomic_t *a, int val) { a->v = val; } -INLINE bool upb_atomic_ref(upb_atomic_t *a) { return a->v++ == 0; } -INLINE bool upb_atomic_unref(upb_atomic_t *a) { return --a->v == 0; } -INLINE int upb_atomic_read(upb_atomic_t *a) { return a->v; } -INLINE bool upb_atomic_add(upb_atomic_t *a, int val) { - a->v += val; - return a->v == 0; -} - -#endif - -/* Atomic refcount ************************************************************/ - -#ifdef UPB_THREAD_UNSAFE - -/* Already defined above. */ - -#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || __GNUC__ > 4 - -/* GCC includes atomic primitives. */ - -typedef struct { - volatile int v; -} upb_atomic_t; - -INLINE void upb_atomic_init(upb_atomic_t *a, int val) { - a->v = val; - __sync_synchronize(); /* Ensure the initialized value is visible. */ -} - -INLINE bool upb_atomic_ref(upb_atomic_t *a) { - return __sync_fetch_and_add(&a->v, 1) == 0; -} - -INLINE bool upb_atomic_add(upb_atomic_t *a, int n) { - return __sync_add_and_fetch(&a->v, n) == 0; -} - -INLINE bool upb_atomic_unref(upb_atomic_t *a) { - return __sync_sub_and_fetch(&a->v, 1) == 0; -} - -INLINE bool upb_atomic_read(upb_atomic_t *a) { - return __sync_fetch_and_add(&a->v, 0); -} - -#elif defined(WIN32) - -/* Windows defines atomic increment/decrement. */ -#include - -typedef struct { - volatile LONG val; -} upb_atomic_t; - -INLINE void upb_atomic_init(upb_atomic_t *a, int val) { - InterlockedExchange(&a->val, val); -} - -INLINE bool upb_atomic_ref(upb_atomic_t *a) { - return InterlockedIncrement(&a->val) == 1; -} - -INLINE bool upb_atomic_unref(upb_atomic_t *a) { - return InterlockedDecrement(&a->val) == 0; -} - -#else -#error Atomic primitives not defined for your platform/CPU. \ - Implement them or compile with UPB_THREAD_UNSAFE. -#endif - -INLINE bool upb_atomic_only(upb_atomic_t *a) { - return upb_atomic_read(a) == 1; -} - -/* Reader/Writer lock. ********************************************************/ - -#ifdef UPB_THREAD_UNSAFE - -typedef struct { -} upb_rwlock_t; - -INLINE void upb_rwlock_init(upb_rwlock_t *l) { (void)l; } -INLINE void upb_rwlock_destroy(upb_rwlock_t *l) { (void)l; } -INLINE void upb_rwlock_rdlock(upb_rwlock_t *l) { (void)l; } -INLINE void upb_rwlock_wrlock(upb_rwlock_t *l) { (void)l; } -INLINE void upb_rwlock_unlock(upb_rwlock_t *l) { (void)l; } - -#elif defined(UPB_USE_PTHREADS) - -#include - -typedef struct { - pthread_rwlock_t lock; -} upb_rwlock_t; - -INLINE void upb_rwlock_init(upb_rwlock_t *l) { - /* TODO: check return value. */ - pthread_rwlock_init(&l->lock, NULL); -} - -INLINE void upb_rwlock_destroy(upb_rwlock_t *l) { - /* TODO: check return value. */ - pthread_rwlock_destroy(&l->lock); -} - -INLINE void upb_rwlock_rdlock(upb_rwlock_t *l) { - /* TODO: check return value. */ - pthread_rwlock_rdlock(&l->lock); -} - -INLINE void upb_rwlock_wrlock(upb_rwlock_t *l) { - /* TODO: check return value. */ - pthread_rwlock_wrlock(&l->lock); -} - -INLINE void upb_rwlock_unlock(upb_rwlock_t *l) { - /* TODO: check return value. */ - pthread_rwlock_unlock(&l->lock); -} - -#else -#error Reader/writer lock is not defined for your platform/CPU. \ - Implement it or compile with UPB_THREAD_UNSAFE. -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_ATOMIC_H_ */ diff --git a/src/upb_bytestream.h b/src/upb_bytestream.h deleted file mode 100644 index 836abb0..0000000 --- a/src/upb_bytestream.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * This file contains upb_bytesrc and upb_bytesink, which are abstractions of - * stdio (fread()/fwrite()/etc) that provide useful buffering/sharing - * semantics. They are virtual base classes so concrete implementations - * can get the data from a fd, a string, a cord, etc. - * - * Byte streams are NOT thread-safe! (Like f{read,write}_unlocked()) - */ - -#ifndef UPB_BYTESTREAM_H -#define UPB_BYTESTREAM_H - -#include -#include -#include -#include "upb.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* upb_bytesrc ****************************************************************/ - -// A upb_bytesrc allows the consumer of a stream of bytes to obtain buffers as -// they become available, and to preserve some trailing amount of data. -typedef size_t upb_bytesrc_fetch_func(void*, uint64_t, upb_status*); -typedef void upb_bytesrc_read_func(void*, uint64_t, size_t, char*); -typedef const char *upb_bytesrc_getptr_func(void*, uint64_t, size_t*); -typedef void upb_bytesrc_refregion_func(void*, uint64_t, size_t); -typedef void upb_bytesrc_ref_func(void*); -typedef struct _upb_bytesrc_vtbl { - upb_bytesrc_fetch_func *fetch; - upb_bytesrc_read_func *read; - upb_bytesrc_getptr_func *getptr; - upb_bytesrc_refregion_func *refregion; - upb_bytesrc_refregion_func *unrefregion; - upb_bytesrc_ref_func *ref; - upb_bytesrc_ref_func *unref; -} upb_bytesrc_vtbl; - -typedef struct { - upb_bytesrc_vtbl *vtbl; -} upb_bytesrc; - -INLINE void upb_bytesrc_init(upb_bytesrc *src, upb_bytesrc_vtbl *vtbl) { - src->vtbl = vtbl; -} - -// Fetches at least minlen bytes starting at ofs, returning the actual number -// of bytes fetched (or 0 on error: see "s" for details). Gives caller a ref -// on the fetched region. It is safe to re-fetch existing regions but only if -// they are ref'd. "ofs" may not greater than the end of the region that was -// previously fetched. -INLINE size_t upb_bytesrc_fetch(upb_bytesrc *src, uint64_t ofs, upb_status *s) { - return src->vtbl->fetch(src, ofs, s); -} - -// Copies "len" bytes of data from offset src_ofs to "dst", which must be at -// least "len" bytes long. The caller must own a ref on the given region. -INLINE void upb_bytesrc_read(upb_bytesrc *src, uint64_t src_ofs, size_t len, - char *dst) { - src->vtbl->read(src, src_ofs, len, dst); -} - -// Returns a pointer to the bytesrc's internal buffer, returning how much data -// was actually returned (which may be less than "len" if the given region is -// not contiguous). The caller must own refs on the entire region from [ofs, -// ofs+len]. The returned buffer is valid for as long as the region remains -// ref'd. -// -// TODO: is "len" really required here? -INLINE const char *upb_bytesrc_getptr(upb_bytesrc *src, uint64_t ofs, - size_t *len) { - return src->vtbl->getptr(src, ofs, len); -} - -// Gives the caller a ref on the given region. The caller must know that the -// given region is already ref'd. -INLINE void upb_bytesrc_refregion(upb_bytesrc *src, uint64_t ofs, size_t len) { - src->vtbl->refregion(src, ofs, len); -} - -// Releases a ref on the given region, which the caller must have previously -// ref'd. -INLINE void upb_bytesrc_unrefregion(upb_bytesrc *src, uint64_t ofs, size_t len) { - src->vtbl->unrefregion(src, ofs, len); -} - -// Attempts to ref the bytesrc itself, returning false if this bytesrc is -// not ref-able. -INLINE bool upb_bytesrc_tryref(upb_bytesrc *src) { - if (src->vtbl->ref) { - src->vtbl->ref(src); - return true; - } else { - return false; - } -} - -// Unref's the bytesrc itself. May only be called when upb_bytesrc_tryref() -// has previously returned true. -INLINE void upb_bytesrc_unref(upb_bytesrc *src) { - assert(src->vtbl->unref); - src->vtbl->unref(src); -} - -/* upb_strref *****************************************************************/ - -// The structure we pass for a string. -typedef struct _upb_strref { - // Pointer to the string data. NULL if the string spans multiple input - // buffers (in which case upb_bytesrc_getptr() must be called to obtain - // the actual pointers). - const char *ptr; - - // Bytesrc from which this string data comes. This is only guaranteed to be - // alive from inside the callback; however if the handler knows more about - // its type and how to prolong its life, it may do so. - upb_bytesrc *bytesrc; - - // Offset in the bytesrc that represents the beginning of this string. - uint32_t stream_offset; - - // Length of the string. - uint32_t len; - - // Possibly add optional members here like start_line, start_column, etc. -} upb_strref; - -// Copies the contents of the strref into a newly-allocated, NULL-terminated -// string. -INLINE char *upb_strref_dup(struct _upb_strref *r) { - char *ret = (char*)malloc(r->len + 1); - upb_bytesrc_read(r->bytesrc, r->stream_offset, r->len, ret); - ret[r->len] = '\0'; - return ret; -} - - -/* upb_bytesink ***************************************************************/ - -typedef bool upb_bytesink_write_func(void*, const char*, size_t, upb_status*); -typedef int32_t upb_bytesink_vprintf_func( - void*, upb_status*, const char *fmt, va_list args); - -typedef struct { - upb_bytesink_write_func *write; - upb_bytesink_vprintf_func *vprintf; -} upb_bytesink_vtbl; - -typedef struct { - upb_bytesink_vtbl *vtbl; -} upb_bytesink; - -INLINE void upb_bytesink_init(upb_bytesink *sink, upb_bytesink_vtbl *vtbl) { - sink->vtbl = vtbl; -} - -INLINE bool upb_bytesink_write(upb_bytesink *sink, const char *buf, size_t len, - upb_status *s) { - return sink->vtbl->write(sink, buf, len, s); -} - -INLINE bool upb_bytesink_writestr(upb_bytesink *sink, const char *str, - upb_status *s) { - return upb_bytesink_write(sink, str, strlen(str), s); -} - -// Returns the number of bytes written or -1 on error. -INLINE int32_t upb_bytesink_printf(upb_bytesink *sink, upb_status *status, - const char *fmt, ...) { - va_list args; - va_start(args, fmt); - uint32_t ret = sink->vtbl->vprintf(sink, status, fmt, args); - va_end(args); - return ret; -} - -// OPT: add getappendbuf() -// OPT: add writefrombytesrc() -// TODO: add flush() - - -/* upb_cbuf *******************************************************************/ - -// A circular buffer implementation for bytesrcs that do internal buffering. - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/src/upb_decoder.c b/src/upb_decoder.c deleted file mode 100644 index fed48af..0000000 --- a/src/upb_decoder.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2008-2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ - -#include -#include -#include -#include "bswap.h" -#include "upb_bytestream.h" -#include "upb_decoder.h" -#include "upb_varint.h" -#include "upb_msg.h" - -// Used for frames that have no specific end offset: groups, repeated primitive -// fields inside groups, and the top-level message. -#define UPB_NONDELIMITED UINT32_MAX - -#ifdef UPB_USE_JIT_X64 -#define Dst_DECL upb_decoder *d -#define Dst_REF (d->dynasm) -#define Dst (d) -#include "dynasm/dasm_proto.h" -#include "upb_decoder_x86.h" -#endif - -// It's unfortunate that we have to micro-manage the compiler this way, -// especially since this tuning is necessarily specific to one hardware -// configuration. But emperically on a Core i7, performance increases 30-50% -// with these annotations. Every instance where these appear, gcc 4.2.1 made -// the wrong decision and degraded performance in benchmarks. -#define FORCEINLINE static __attribute__((always_inline)) -#define NOINLINE static __attribute__((noinline)) - -static void upb_decoder_exit(upb_decoder *d) { siglongjmp(d->exitjmp, 1); } -static void upb_decoder_exit2(void *_d) { - upb_decoder *d = _d; - upb_decoder_exit(d); -} -static void upb_decoder_abort(upb_decoder *d, const char *msg) { - upb_status_setf(d->status, UPB_ERROR, msg); - upb_decoder_exit(d); -} - -/* Decoding/Buffering of wire types *******************************************/ - -static size_t upb_decoder_bufleft(upb_decoder *d) { return d->end - d->ptr; } -static void upb_decoder_advance(upb_decoder *d, size_t len) { - assert((size_t)(d->end - d->ptr) >= len); - d->ptr += len; -} - -size_t upb_decoder_offset(upb_decoder *d) { - size_t offset = d->bufstart_ofs; - if (d->ptr) offset += (d->ptr - d->buf); - return offset; -} - -static void upb_decoder_setmsgend(upb_decoder *d) { - upb_dispatcher_frame *f = d->dispatcher.top; - size_t delimlen = f->end_ofs - d->bufstart_ofs; - size_t buflen = d->end - d->buf; - if (f->end_ofs != UINT64_MAX && delimlen <= buflen) { - d->delim_end = (uintptr_t)(d->buf + delimlen); - } else { - // Buffers must not run up against the end of memory. - assert((uintptr_t)d->end < UINTPTR_MAX); - d->delim_end = UINTPTR_MAX; - } -} - -// Pulls the next buffer from the bytesrc. Should be called only when the -// current buffer is completely empty. -static bool upb_trypullbuf(upb_decoder *d) { - assert(upb_decoder_bufleft(d) == 0); - if (d->bufend_ofs == d->refend_ofs) { - d->refend_ofs += upb_bytesrc_fetch(d->bytesrc, d->refend_ofs, d->status); - if (!upb_ok(d->status)) { - d->ptr = NULL; - d->end = NULL; - if (upb_iseof(d->status)) return false; - upb_decoder_exit(d); - } - } - d->bufstart_ofs = d->bufend_ofs; - size_t len; - d->buf = upb_bytesrc_getptr(d->bytesrc, d->bufstart_ofs, &len); - assert(len > 0); - d->bufend_ofs = d->bufstart_ofs + len; - d->ptr = d->buf; - d->end = d->buf + len; -#ifdef UPB_USE_JIT_X64 - d->jit_end = d->end - 20; -#endif - upb_decoder_setmsgend(d); - return true; -} - -static void upb_pullbuf(upb_decoder *d) { - if (!upb_trypullbuf(d)) upb_decoder_abort(d, "Unexpected EOF"); -} - -void upb_decoder_commit(upb_decoder *d) { - d->completed_ptr = d->ptr; - if (d->refstart_ofs < d->bufstart_ofs) { - // Drop our ref on the previous buf's region. - upb_bytesrc_refregion(d->bytesrc, d->bufstart_ofs, d->refend_ofs); - upb_bytesrc_unrefregion(d->bytesrc, d->refstart_ofs, d->refend_ofs); - d->refstart_ofs = d->bufstart_ofs; - } -} - -NOINLINE uint64_t upb_decode_varint_slow(upb_decoder *d) { - uint8_t byte = 0x80; - uint64_t u64 = 0; - int bitpos; - const char *ptr = d->ptr; - for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) { - if (upb_decoder_bufleft(d) == 0) { - upb_pullbuf(d); - ptr = d->ptr; - } - u64 |= ((uint64_t)(byte = *ptr++) & 0x7F) << bitpos; - } - if(bitpos == 70 && (byte & 0x80)) upb_decoder_abort(d, "Unterminated varint"); - return u64; -} - -// For tags and delimited lengths, which must be <=32bit and are usually small. -FORCEINLINE uint32_t upb_decode_varint32(upb_decoder *d) { - const char *p = d->ptr; - uint32_t ret; - uint64_t u64; - // Nearly all will be either 1 byte (1-16) or 2 bytes (17-2048). - if (upb_decoder_bufleft(d) < 2) goto slow; // unlikely. - ret = *p & 0x7f; - if ((*(p++) & 0x80) == 0) goto done; // predictable if fields are in order - ret |= (*p & 0x7f) << 7; - if ((*(p++) & 0x80) == 0) goto done; // likely -slow: - u64 = upb_decode_varint_slow(d); - if (u64 > 0xffffffff) upb_decoder_abort(d, "Unterminated 32-bit varint"); - ret = (uint32_t)u64; - p = d->ptr; // Turn the next line into a nop. -done: - upb_decoder_advance(d, p - d->ptr); - return ret; -} - -FORCEINLINE bool upb_trydecode_varint32(upb_decoder *d, uint32_t *val) { - if (upb_decoder_bufleft(d) == 0) { - // Check for our two normal end-of-message conditions. - if (d->bufend_ofs == d->end_ofs) return false; - if (!upb_trypullbuf(d)) return false; - } - *val = upb_decode_varint32(d); - return true; -} - -FORCEINLINE uint64_t upb_decode_varint(upb_decoder *d) { - if (upb_decoder_bufleft(d) >= 10) { - // Fast case. - upb_decoderet r = upb_vdecode_fast(d->ptr); - if (r.p == NULL) upb_decoder_abort(d, "Unterminated varint"); - upb_decoder_advance(d, r.p - d->ptr); - return r.val; - } else if (upb_decoder_bufleft(d) > 0) { - // Intermediate case -- worth it? - char tmpbuf[10]; - memset(tmpbuf, 0x80, 10); - memcpy(tmpbuf, d->ptr, upb_decoder_bufleft(d)); - upb_decoderet r = upb_vdecode_fast(tmpbuf); - if (r.p != NULL) { - upb_decoder_advance(d, r.p - tmpbuf); - return r.val; - } - } - // Slow case -- varint spans buffer seam. - return upb_decode_varint_slow(d); -} - -FORCEINLINE void upb_decode_fixed(upb_decoder *d, char *buf, size_t bytes) { - if (upb_decoder_bufleft(d) >= bytes) { - // Fast case. - memcpy(buf, d->ptr, bytes); - upb_decoder_advance(d, bytes); - } else { - // Slow case. - size_t read = 0; - while (read < bytes) { - size_t avail = upb_decoder_bufleft(d); - memcpy(buf + read, d->ptr, avail); - upb_decoder_advance(d, avail); - read += avail; - } - } -} - -FORCEINLINE uint32_t upb_decode_fixed32(upb_decoder *d) { - uint32_t u32; - upb_decode_fixed(d, (char*)&u32, sizeof(uint32_t)); - return le32toh(u32); -} -FORCEINLINE uint64_t upb_decode_fixed64(upb_decoder *d) { - uint64_t u64; - upb_decode_fixed(d, (char*)&u64, sizeof(uint64_t)); - return le64toh(u64); -} - -INLINE upb_strref *upb_decode_string(upb_decoder *d) { - uint32_t strlen = upb_decode_varint32(d); - d->strref.stream_offset = upb_decoder_offset(d); - d->strref.len = strlen; - if (upb_decoder_bufleft(d) == 0) upb_pullbuf(d); - if (upb_decoder_bufleft(d) >= strlen) { - // Fast case. - d->strref.ptr = d->ptr; - upb_decoder_advance(d, strlen); - } else { - // Slow case. - while (1) { - size_t consume = UPB_MIN(upb_decoder_bufleft(d), strlen); - upb_decoder_advance(d, consume); - strlen -= consume; - if (strlen == 0) break; - upb_pullbuf(d); - } - } - return &d->strref; -} - -INLINE void upb_push(upb_decoder *d, upb_fhandlers *f, uint32_t end) { - upb_dispatch_startsubmsg(&d->dispatcher, f)->end_ofs = end; - upb_decoder_setmsgend(d); -} - - -/* Decoding of .proto types ***************************************************/ - -// Technically, we are losing data if we see a 32-bit varint that is not -// properly sign-extended. We could detect this and error about the data loss, -// but proto2 does not do this, so we pass. - -#define T(type, wt, valtype, convfunc) \ - INLINE void upb_decode_ ## type(upb_decoder *d, upb_fhandlers *f) { \ - upb_value val; \ - upb_value_set ## valtype(&val, (convfunc)(upb_decode_ ## wt(d))); \ - upb_dispatch_value(&d->dispatcher, f, val); \ - } \ - -static double upb_asdouble(uint64_t n) { double d; memcpy(&d, &n, 8); return d; } -static float upb_asfloat(uint32_t n) { float f; memcpy(&f, &n, 4); return f; } -static int32_t upb_zzdec_32(uint32_t n) { return (n >> 1) ^ -(int32_t)(n & 1); } -static int64_t upb_zzdec_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); } - -T(INT32, varint, int32, int32_t) -T(INT64, varint, int64, int64_t) -T(UINT32, varint, uint32, uint32_t) -T(UINT64, varint, uint64, uint64_t) -T(FIXED32, fixed32, uint32, uint32_t) -T(FIXED64, fixed64, uint64, uint64_t) -T(SFIXED32, fixed32, int32, int32_t) -T(SFIXED64, fixed64, int64, int64_t) -T(BOOL, varint, bool, bool) -T(ENUM, varint, int32, int32_t) -T(DOUBLE, fixed64, double, upb_asdouble) -T(FLOAT, fixed32, float, upb_asfloat) -T(SINT32, varint, int32, upb_zzdec_32) -T(SINT64, varint, int64, upb_zzdec_64) -T(STRING, string, strref, upb_strref*) - -static void upb_decode_GROUP(upb_decoder *d, upb_fhandlers *f) { - upb_push(d, f, UPB_NONDELIMITED); -} -static void upb_endgroup(upb_decoder *d, upb_fhandlers *f) { - (void)f; - upb_dispatch_endsubmsg(&d->dispatcher); - upb_decoder_setmsgend(d); -} -static void upb_decode_MESSAGE(upb_decoder *d, upb_fhandlers *f) { - upb_push(d, f, upb_decode_varint32(d) + (d->ptr - d->buf)); -} - - -/* The main decoding loop *****************************************************/ - -static void upb_decoder_checkdelim(upb_decoder *d) { - while ((uintptr_t)d->ptr >= d->delim_end) { - if ((uintptr_t)d->ptr > d->delim_end) - upb_decoder_abort(d, "Bad submessage end"); - - if (d->dispatcher.top->is_sequence) { - upb_dispatch_endseq(&d->dispatcher); - } else { - upb_dispatch_endsubmsg(&d->dispatcher); - } - upb_decoder_setmsgend(d); - } -} - -static void upb_decoder_enterjit(upb_decoder *d) { - (void)d; -#ifdef UPB_USE_JIT_X64 - if (d->jit_code && d->dispatcher.top == d->dispatcher.stack && d->ptr < d->jit_end) { - // Decodes as many fields as possible, updating d->ptr appropriately, - // before falling through to the slow(er) path. - void (*upb_jit_decode)(upb_decoder *d) = (void*)d->jit_code; - upb_jit_decode(d); - } -#endif -} - -INLINE upb_fhandlers *upb_decode_tag(upb_decoder *d) { - while (1) { - uint32_t tag; - if (!upb_trydecode_varint32(d, &tag)) return NULL; - upb_fhandlers *f = upb_dispatcher_lookup(&d->dispatcher, tag); - - // There are no explicit "startseq" or "endseq" markers in protobuf - // streams, so we have to infer them by noticing when a repeated field - // starts or ends. - if (d->dispatcher.top->is_sequence && d->dispatcher.top->f != f) { - upb_dispatch_endseq(&d->dispatcher); - upb_decoder_setmsgend(d); - } - if (f && f->repeated && d->dispatcher.top->f != f) { - // TODO: support packed. - assert(upb_issubmsgtype(f->type) || upb_isstringtype(f->type) || - (tag & 0x7) != UPB_WIRE_TYPE_DELIMITED); - uint32_t end = d->dispatcher.top->end_ofs; - upb_dispatch_startseq(&d->dispatcher, f)->end_ofs = end; - upb_decoder_setmsgend(d); - } - if (f) return f; - - // Unknown field. - switch (tag & 0x7) { - case UPB_WIRE_TYPE_VARINT: upb_decode_varint(d); break; - case UPB_WIRE_TYPE_32BIT: upb_decoder_advance(d, 4); break; - case UPB_WIRE_TYPE_64BIT: upb_decoder_advance(d, 8); break; - case UPB_WIRE_TYPE_DELIMITED: - upb_decoder_advance(d, upb_decode_varint32(d)); break; - default: - upb_decoder_abort(d, "Invavlid wire type"); - } - // TODO: deliver to unknown field callback. - upb_decoder_commit(d); - upb_decoder_checkdelim(d); - } -} - -void upb_decoder_onexit(upb_decoder *d) { - if (d->dispatcher.top->is_sequence) upb_dispatch_endseq(&d->dispatcher); - if (d->status->code == UPB_EOF && upb_dispatcher_stackempty(&d->dispatcher)) { - // Normal end-of-file. - upb_status_clear(d->status); - upb_dispatch_endmsg(&d->dispatcher, d->status); - } else { - if (d->status->code == UPB_EOF) - upb_status_setf(d->status, UPB_ERROR, "Input ended mid-submessage."); - } -} - -void upb_decoder_decode(upb_decoder *d, upb_status *status) { - if (sigsetjmp(d->exitjmp, 0)) { - upb_decoder_onexit(d); - return; - } - d->status = status; - upb_dispatch_startmsg(&d->dispatcher); - while(1) { // Main loop: executed once per tag/field pair. - upb_decoder_checkdelim(d); - upb_decoder_enterjit(d); - // if (!d->dispatcher.top->is_packed) - upb_fhandlers *f = upb_decode_tag(d); - if (!f) upb_decoder_exit2(d); - f->decode(d, f); - upb_decoder_commit(d); - } -} - -static void upb_decoder_skip(void *_d, upb_dispatcher_frame *top, - upb_dispatcher_frame *bottom) { - (void)top; - (void)bottom; - (void)_d; -#if 0 - upb_decoder *d = _d; - // TODO - if (bottom->end_offset == UPB_NONDELIMITED) { - // TODO: support skipping groups. - abort(); - } - d->ptr = d->buf.ptr + bottom->end_offset; -#endif -} - -void upb_decoder_initforhandlers(upb_decoder *d, upb_handlers *handlers) { - upb_dispatcher_init( - &d->dispatcher, handlers, upb_decoder_skip, upb_decoder_exit2, d); -#ifdef UPB_USE_JIT_X64 - d->jit_code = NULL; - if (d->dispatcher.handlers->should_jit) upb_decoder_makejit(d); -#endif - // Set function pointers for each field's decode function. - for (int i = 0; i < handlers->msgs_len; i++) { - upb_mhandlers *m = handlers->msgs[i]; - for(upb_inttable_iter i = upb_inttable_begin(&m->fieldtab); !upb_inttable_done(i); - i = upb_inttable_next(&m->fieldtab, i)) { - upb_fhandlers *f = upb_inttable_iter_value(i); - switch (f->type) { - case UPB_TYPE(INT32): f->decode = &upb_decode_INT32; break; - case UPB_TYPE(INT64): f->decode = &upb_decode_INT64; break; - case UPB_TYPE(UINT32): f->decode = &upb_decode_UINT32; break; - case UPB_TYPE(UINT64): f->decode = &upb_decode_UINT64; break; - case UPB_TYPE(FIXED32): f->decode = &upb_decode_FIXED32; break; - case UPB_TYPE(FIXED64): f->decode = &upb_decode_FIXED64; break; - case UPB_TYPE(SFIXED32): f->decode = &upb_decode_SFIXED32; break; - case UPB_TYPE(SFIXED64): f->decode = &upb_decode_SFIXED64; break; - case UPB_TYPE(BOOL): f->decode = &upb_decode_BOOL; break; - case UPB_TYPE(ENUM): f->decode = &upb_decode_ENUM; break; - case UPB_TYPE(DOUBLE): f->decode = &upb_decode_DOUBLE; break; - case UPB_TYPE(FLOAT): f->decode = &upb_decode_FLOAT; break; - case UPB_TYPE(SINT32): f->decode = &upb_decode_SINT32; break; - case UPB_TYPE(SINT64): f->decode = &upb_decode_SINT64; break; - case UPB_TYPE(STRING): f->decode = &upb_decode_STRING; break; - case UPB_TYPE(BYTES): f->decode = &upb_decode_STRING; break; - case UPB_TYPE(GROUP): f->decode = &upb_decode_GROUP; break; - case UPB_TYPE(MESSAGE): f->decode = &upb_decode_MESSAGE; break; - case UPB_TYPE_ENDGROUP: f->decode = &upb_endgroup; break; - } - } - } -} - -void upb_decoder_initformsgdef(upb_decoder *d, upb_msgdef *m) { - upb_handlers *h = upb_handlers_new(); - upb_accessors_reghandlers(h, m); - upb_decoder_initforhandlers(d, h); - upb_handlers_unref(h); -} - -void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc, uint64_t start_ofs, - uint64_t end_ofs, void *closure) { - upb_dispatcher_frame *f = upb_dispatcher_reset(&d->dispatcher, closure); - f->end_ofs = end_ofs; - d->end_ofs = end_ofs; - d->refstart_ofs = start_ofs; - d->refend_ofs = start_ofs; - d->bufstart_ofs = start_ofs; - d->bufend_ofs = start_ofs; - d->bytesrc = bytesrc; - d->buf = NULL; - d->ptr = NULL; - d->end = NULL; // Force a buffer pull. -#ifdef UPB_USE_JIT_X64 - d->jit_end = NULL; -#endif - d->delim_end = UINTPTR_MAX; // But don't let end-of-message get triggered. - d->strref.bytesrc = bytesrc; -} - -void upb_decoder_uninit(upb_decoder *d) { -#ifdef UPB_USE_JIT_X64 - if (d->dispatcher.handlers->should_jit) upb_decoder_freejit(d); -#endif - upb_dispatcher_uninit(&d->dispatcher); -} diff --git a/src/upb_decoder.h b/src/upb_decoder.h deleted file mode 100644 index 7a813bf..0000000 --- a/src/upb_decoder.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009-2010 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * upb_decoder implements a high performance, streaming decoder for protobuf - * data that works by implementing upb_src and getting its data from a - * upb_bytesrc. - * - * The decoder does not currently support non-blocking I/O, in the sense that - * if the bytesrc returns UPB_STATUS_TRYAGAIN it is not possible to resume the - * decoder when data becomes available again. Support for this could be added, - * but it would add complexity and perhaps cost efficiency also. - */ - -#ifndef UPB_DECODER_H_ -#define UPB_DECODER_H_ - -#include -#include -#include -#include "upb_handlers.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* upb_decoder *****************************************************************/ - -struct dasm_State; - -typedef struct _upb_decoder { - upb_bytesrc *bytesrc; // Source of our serialized data. - upb_dispatcher dispatcher; // Dispatcher to which we push parsed data. - upb_status *status; // Where we will store any errors that occur. - upb_strref strref; // For passing string data to callbacks. - - // Offsets for the region we currently have ref'd. - uint64_t refstart_ofs, refend_ofs; - - // Current buffer and its stream offset. - const char *buf, *ptr, *end; - uint64_t bufstart_ofs, bufend_ofs; - - // Stream offset for the end of the top-level message, if any. - uint64_t end_ofs; - - // Buf offset as of which we've delivered calbacks; needed for rollback on - // UPB_TRYAGAIN (or in the future, UPB_SUSPEND). - const char *completed_ptr; - - // End of the delimited region, relative to ptr, or UINTPTR_MAX if not in - // this buf. - uintptr_t delim_end; - -#ifdef UPB_USE_JIT_X64 - // For JIT, which doesn't do bounds checks in the middle of parsing a field. - const char *jit_end, *effective_end; // == MIN(jit_end, submsg_end) - - // JIT-generated machine code (else NULL). - char *jit_code; - size_t jit_size; - char *debug_info; - - struct dasm_State *dynasm; -#endif - - sigjmp_buf exitjmp; -} upb_decoder; - -// Initializes/uninitializes a decoder for calling into the given handlers -// or to write into the given msgdef, given its accessors). Takes a ref -// on the handlers or msgdef. -void upb_decoder_initforhandlers(upb_decoder *d, upb_handlers *h); - -// Equivalent to: -// upb_accessors_reghandlers(m, h); -// upb_decoder_initforhandlers(d, h); -// except possibly more efficient, by using cached state in the msgdef. -void upb_decoder_initformsgdef(upb_decoder *d, upb_msgdef *m); -void upb_decoder_uninit(upb_decoder *d); - -// Resets the internal state of an already-allocated decoder. This puts it in a -// state where it has not seen any data, and expects the next data to be from -// the beginning of a new protobuf. Parsers must be reset before they can be -// used. A decoder can be reset multiple times. -// -// Pass UINT64_MAX for end_ofs to indicate a non-delimited top-level message. -void upb_decoder_reset(upb_decoder *d, upb_bytesrc *src, uint64_t start_ofs, - uint64_t end_ofs, void *closure); - -void upb_decoder_decode(upb_decoder *d, upb_status *status); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_DECODER_H_ */ diff --git a/src/upb_decoder_x86.dasc b/src/upb_decoder_x86.dasc deleted file mode 100644 index 800b099..0000000 --- a/src/upb_decoder_x86.dasc +++ /dev/null @@ -1,694 +0,0 @@ -|// -|// upb - a minimalist implementation of protocol buffers. -|// -|// Copyright (c) 2011 Google Inc. See LICENSE for details. -|// Author: Josh Haberman -|// -|// JIT compiler for upb_decoder on x86. Given a upb_handlers object, -|// generates code specialized to parsing the specific message and -|// calling specific handlers. - -#define UPB_NONE -1 -#define UPB_MULTIPLE -2 -#define UPB_TOPLEVEL_ONE -3 - -#include -#include "dynasm/dasm_proto.h" -#include "dynasm/dasm_x86.h" - -#ifndef MAP_ANONYMOUS -# define MAP_ANONYMOUS MAP_ANON -#endif - -// We map into the low 32 bits when we can, but if this is not available -// (like on OS X) we take what we can get. It's not required for correctness, -// it's just a performance thing that makes it more likely that our jumps -// can be rel32 (i.e. within 32-bits of our pc) instead of the longer -// sequence required for other jumps (see callp). -#ifndef MAP_32BIT -#define MAP_32BIT 0 -#endif - -// To debug JIT-ted code with GDB we need to tell GDB about the JIT-ted code -// at runtime. GDB 7.x+ has defined an interface for doing this, and these -// structure/function defintions are copied out of gdb/jit.h -// -// We need to give GDB an ELF file at runtime describing the symbols we have -// generated. To avoid implementing the ELF format, we generate an ELF file -// at compile-time and compile it in as a character string. We can replace -// a few key constants (address of JIT-ted function and its size) by looking -// for a few magic numbers and doing a dumb string replacement. - -#ifndef __APPLE__ -#include "jit_debug_elf_file.h" - -typedef enum -{ - GDB_JIT_NOACTION = 0, - GDB_JIT_REGISTER, - GDB_JIT_UNREGISTER -} jit_actions_t; - -typedef struct gdb_jit_entry { - struct gdb_jit_entry *next_entry; - struct gdb_jit_entry *prev_entry; - const char *symfile_addr; - uint64_t symfile_size; -} gdb_jit_entry; - -typedef struct { - uint32_t version; - uint32_t action_flag; - gdb_jit_entry *relevant_entry; - gdb_jit_entry *first_entry; -} gdb_jit_descriptor; - -gdb_jit_descriptor __jit_debug_descriptor = {1, GDB_JIT_NOACTION, NULL, NULL}; - -void __attribute__((noinline)) __jit_debug_register_code() { __asm__ __volatile__(""); } - -void upb_reg_jit_gdb(upb_decoder *d) { - // Create debug info. - size_t elf_len = src_jit_debug_elf_file_o_len; - d->debug_info = malloc(elf_len); - memcpy(d->debug_info, src_jit_debug_elf_file_o, elf_len); - uint64_t *p = (void*)d->debug_info; - for (; (void*)(p+1) <= (void*)d->debug_info + elf_len; ++p) { - if (*p == 0x12345678) { *p = (uintptr_t)d->jit_code; } - if (*p == 0x321) { *p = d->jit_size; } - } - - // Register the JIT-ted code with GDB. - gdb_jit_entry *e = malloc(sizeof(gdb_jit_entry)); - e->next_entry = __jit_debug_descriptor.first_entry; - e->prev_entry = NULL; - if (e->next_entry) e->next_entry->prev_entry = e; - e->symfile_addr = d->debug_info; - e->symfile_size = elf_len; - __jit_debug_descriptor.first_entry = e; - __jit_debug_descriptor.relevant_entry = e; - __jit_debug_descriptor.action_flag = GDB_JIT_REGISTER; - __jit_debug_register_code(); -} - -#else - -void upb_reg_jit_gdb(upb_decoder *d) { - (void)d; -} - -#endif - -|.arch x64 -|.actionlist upb_jit_actionlist -|.globals UPB_JIT_GLOBAL_ -|.globalnames upb_jit_globalnames -| -|// Calling conventions. -|.define ARG1_64, rdi -|.define ARG2_8, sil -|.define ARG2_32, esi -|.define ARG2_64, rsi -|.define ARG3_8, dl -|.define ARG3_32, edx -|.define ARG3_64, rdx -| -|// Register allocation / type map. -|// ALL of the code in this file uses these register allocations. -|// When we "call" within this file, we do not use regular calling -|// conventions, but of course when calling to user callbacks we must. -|.define PTR, rbx -|.define CLOSURE, r12 -|.type FRAME, upb_dispatcher_frame, r13 -|.type STRREF, upb_strref, r14 -|.type DECODER, upb_decoder, r15 -| -|.macro callp, addr -|| if ((uintptr_t)addr < 0xffffffff) { - | call &addr -|| } else { - | mov64 rax, (uintptr_t)addr - | call rax -|| } -|.endmacro -| -|// Checks PTR for end-of-buffer. -|.macro check_eob, m -| cmp PTR, DECODER->effective_end -|| if (m->is_group) { - | jae ->exit_jit -|| } else { - | jae =>m->jit_endofbuf_pclabel -|| } -|.endmacro -| -|// Decodes varint from [PTR + offset] -> ARG3. -|// Saves new pointer as rax. -|.macro decode_loaded_varint, offset -| // Check for <=2 bytes inline, otherwise jump to 2-10 byte decoder. -| lea rax, [PTR + offset + 1] -| mov ARG3_32, ecx -| and ARG3_32, 0x7f -| test cl, cl -| jns >9 -| lea rax, [PTR + offset + 2] -| movzx esi, ch -| and esi, 0x7f -| shl esi, 7 -| or ARG3_32, esi -| test cx, cx -| jns >9 -| mov ARG1_64, rax -| mov ARG2_32, ARG3_32 -| callp upb_vdecode_max8_fast -| test rax, rax -| jz ->exit_jit // >10-byte varint. -|9: -|.endmacro -| -|.macro decode_varint, offset -| mov ecx, dword [PTR + offset] -| decode_loaded_varint offset -| mov PTR, rax -|.endmacro -| -|// Decode the tag -> edx. -|// Could specialize this by avoiding the value masking: could just key the -|// table on the raw (length-masked) varint to save 3-4 cycles of latency. -|// Currently only support tables where all entries are in the array part. -|.macro dyndispatch, m -| decode_loaded_varint, 0 -| mov ecx, edx -| shr ecx, 3 -| and edx, 0x7 -| cmp ecx, m->max_field_number // Bounds-check the field. -| ja ->exit_jit // In the future; could be unknown label -|| if ((uintptr_t)m->tablearray < 0xffffffff) { -| mov rax, qword [rcx*8 + m->tablearray] // TODO: support hybrid array/hash tables. -|| } else { -| mov64 rax, (uintptr_t)m->tablearray -| mov rax, qword [rax + rcx*8] -|| } -| jmp rax // Dispatch: unpredictable jump. -|.endmacro -| -|// Push a stack frame (not the CPU stack, the upb_decoder stack). -|.macro pushframe, f, closure_, end_offset_, is_sequence_ -| lea rax, [FRAME + sizeof(upb_dispatcher_frame)] // rax for shorter addressing. -| cmp rax, qword DECODER->dispatcher.limit -| jae ->exit_jit // Frame stack overflow. -| mov qword FRAME:rax->f, f -| mov qword FRAME:rax->closure, closure_ -| mov dword FRAME:rax->end_ofs, end_offset_ -| mov byte FRAME:rax->is_sequence, is_sequence_ -| mov CLOSURE, rdx -| mov DECODER->dispatcher.top, rax -| mov FRAME, rax -|.endmacro -| -|.macro popframe -| sub FRAME, sizeof(upb_dispatcher_frame) -| mov DECODER->dispatcher.top, FRAME -| setmsgend m -| mov CLOSURE, FRAME->closure -|.endmacro -| -|.macro setmsgend, m -| mov rsi, DECODER->jit_end -|| if (m->is_group) { -| mov64 rax, 0xffffffffffffffff -| mov qword DECODER->delim_end, rax -| mov DECODER->effective_end, rsi -|| } else { -| // Could store a correctly-biased version in the frame, at the cost of -| // a larger stack. -| mov eax, dword FRAME->end_ofs -| add rax, qword DECODER->buf -| mov DECODER->delim_end, rax // delim_end = d->buf + f->end_ofs -| cmp rax, rsi -| jb >8 -| mov rax, rsi // effective_end = min(d->delim_end, d->jit_end) -|8: -| mov DECODER->effective_end, rax -|| } -|.endmacro -| -|// rax contains the tag, compare it against "tag", but since it is a varint -|// we must only compare as many bytes as actually have data. -|.macro checktag, tag -|| switch (upb_value_size(tag)) { -|| case 1: -| cmp cl, tag -|| break; -|| case 2: -| cmp cx, tag -|| break; -|| case 3: -| and ecx, 0xffffff // 3 bytes -| cmp rcx, tag -|| case 4: -| cmp ecx, tag -|| break; -|| case 5: -| mov64 rdx, 0xffffffffff // 5 bytes -| and rcx, rdx -| cmp rcx, tag -|| break; -|| default: abort(); -|| } -|.endmacro -| -|// TODO: optimize for 0 (xor) and 32-bits. -|.macro loadfval, f -|| if (f->fval.val.uint64 == 0) { -| xor ARG2_32, ARG2_32 -|| } else if (f->fval.val.uint64 < 0xffffffff) { -| mov ARG2_32, f->fval.val.uint64 -|| } else { -| mov64 ARG2_64, f->fval.val.uint64 -|| } -|.endmacro - -#include -#include "upb_varint.h" - -// PTR should point to the beginning of the tag. -static void upb_decoder_jit_field(upb_decoder *d, uint32_t tag, uint32_t next_tag, - upb_mhandlers *m, - upb_fhandlers *f, upb_fhandlers *next_f) { - int tag_size = upb_value_size(tag); - - // PC-label for the dispatch table. - // We check the wire type (which must be loaded in edx) because the - // table is keyed on field number, not type. - |=>f->jit_pclabel: - | cmp edx, (tag & 0x7) - | jne ->exit_jit // In the future: could be an unknown field or packed. - |=>f->jit_pclabel_notypecheck: - if (f->repeated) { - if (f->startseq) { - | mov ARG1_64, CLOSURE - | loadfval f - | callp f->startseq - } else { - | mov rdx, CLOSURE - } - | mov esi, FRAME->end_ofs - | pushframe f, rdx, esi, true - } - - |1: // Label for repeating this field. - - // Decode the value into arg 3 for the callback. - switch (f->type) { - case UPB_TYPE(DOUBLE): - case UPB_TYPE(FIXED64): - case UPB_TYPE(SFIXED64): - | mov ARG3_64, qword [PTR + tag_size] - | add PTR, 8 + tag_size - break; - - case UPB_TYPE(FLOAT): - case UPB_TYPE(FIXED32): - case UPB_TYPE(SFIXED32): - | mov ARG3_32, dword [PTR + tag_size] - | add PTR, 4 + tag_size - break; - - case UPB_TYPE(BOOL): - // Can't assume it's one byte long, because bool must be wire-compatible - // with all of the varint integer types. - | decode_varint tag_size - | test ARG3_64, ARG3_64 - | setne ARG3_8 // Other bytes left with val, should be ok. - break; - - case UPB_TYPE(INT64): - case UPB_TYPE(UINT64): - case UPB_TYPE(INT32): - case UPB_TYPE(UINT32): - case UPB_TYPE(ENUM): - | decode_varint tag_size - break; - - case UPB_TYPE(SINT64): - // 64-bit zig-zag decoding. - | decode_varint tag_size - | mov rax, ARG3_64 - | shr ARG3_64, 1 - | and rax, 1 - | neg rax - | xor ARG3_64, rax - break; - - case UPB_TYPE(SINT32): - // 32-bit zig-zag decoding. - | decode_varint tag_size - | mov eax, ARG3_32 - | shr ARG3_32, 1 - | and eax, 1 - | neg eax - | xor ARG3_32, eax - break; - - case UPB_TYPE(STRING): - case UPB_TYPE(BYTES): - // We only handle the case where the entire string is in our current - // buf, which sidesteps any security problems. The C path has more - // robust checks. - | decode_varint tag_size - | mov STRREF->len, ARG3_32 - | mov STRREF->ptr, PTR - | mov rax, PTR - | sub rax, DECODER->buf - | add eax, DECODER->bufstart_ofs // = d->ptr - d->buf + d->bufstart_ofs - | mov STRREF->stream_offset, eax - | add PTR, ARG3_64 - | mov ARG3_64, STRREF - | cmp PTR, DECODER->effective_end - | ja ->exit_jit // Can't deliver, whole string not in buf. - break; - - case UPB_TYPE_ENDGROUP: // A pseudo-type. - | add PTR, tag_size - | mov DECODER->ptr, PTR - | jmp =>m->jit_endofmsg_pclabel - return; - - // Will dispatch callbacks and call submessage in a second. - case UPB_TYPE(MESSAGE): - | decode_varint tag_size - break; - case UPB_TYPE(GROUP): - | add PTR, tag_size - break; - - default: abort(); - } - // Commit our work by advancing ptr. - // (If in the future we wanted to support a UPB_SUSPEND_AGAIN that - // suspends the decoder and redelivers the value later, we would - // need to adjust this to happen perhaps after the callback ran). - | mov DECODER->ptr, PTR - - // Load closure and fval into arg registers. - | mov ARG1_64, CLOSURE - | loadfval f - - // Call callbacks. - if (upb_issubmsgtype(f->type)) { - // Call startsubmsg handler (if any). - if (f->startsubmsg) { - // upb_sflow_t startsubmsg(void *closure, upb_value fval) - | mov r12d, ARG3_32 - | callp f->startsubmsg - } else { - | mov rdx, CLOSURE - | mov r12d, ARG3_32 - } - if (f->type == UPB_TYPE(MESSAGE)) { - | mov rsi, PTR - | sub rsi, DECODER->buf - | add esi, r12d // = (d->ptr - d->buf) + delim_len - } else { - assert(f->type == UPB_TYPE(GROUP)); - | mov esi, UPB_NONDELIMITED - } - | pushframe f, rdx, esi, false - - upb_mhandlers *sub_m = upb_fhandlers_getsubmsg(f); - if (sub_m->jit_parent_field_done_pclabel != UPB_MULTIPLE) { - | jmp =>sub_m->jit_startmsg_pclabel; - } else { - | call =>sub_m->jit_startmsg_pclabel; - } - - |=>f->jit_submsg_done_pclabel: - | popframe - - // Call endsubmsg handler (if any). - if (f->endsubmsg) { - // upb_flow_t endsubmsg(void *closure, upb_value fval); - | mov ARG1_64, CLOSURE - | loadfval f - | callp f->endsubmsg - } - } else { - | callp f->value - } - // TODO: Handle UPB_SKIPSUBMSG, UPB_BREAK - - // Epilogue: load next tag, check for repeated field. - | check_eob m - | mov rcx, qword [PTR] - if (f->repeated) { - | checktag tag - | je <1 - | popframe - if (f->endseq) { - | mov ARG1_64, CLOSURE - | loadfval f - | callp f->endseq - } - } - if (next_tag != 0) { - | checktag next_tag - | je =>next_f->jit_pclabel_notypecheck - } - - // Fall back to dynamic dispatch. Replicate the dispatch - // here so we can learn what fields generally follow others. - | dyndispatch m - |1: -} - -static int upb_compare_uint32(const void *a, const void *b) { - // TODO: always put ENDGROUP at the end. - return *(uint32_t*)a - *(uint32_t*)b; -} - -static void upb_decoder_jit_msg(upb_decoder *d, upb_mhandlers *m) { - |=>m->jit_startmsg_pclabel: - // Call startmsg handler (if any): - if (m->startmsg) { - // upb_flow_t startmsg(void *closure); - | mov ARG1_64, FRAME->closure - | callp m->startmsg - // TODO: Handle UPB_SKIPSUBMSG, UPB_BREAK - } - - | setmsgend m - | check_eob m - | mov ecx, dword [PTR] - | dyndispatch m - - // --------- New code section (does not fall through) ------------------------ - - // Emit code for parsing each field (dynamic dispatch contains pointers to - // all of these). - - // Create an ordering over the fields (inttable ordering is undefined). - int num_keys = upb_inttable_count(&m->fieldtab); - uint32_t *keys = malloc(num_keys * sizeof(*keys)); - int idx = 0; - for(upb_inttable_iter i = upb_inttable_begin(&m->fieldtab); !upb_inttable_done(i); - i = upb_inttable_next(&m->fieldtab, i)) { - keys[idx++] = upb_inttable_iter_key(i); - } - qsort(keys, num_keys, sizeof(uint32_t), &upb_compare_uint32); - - upb_fhandlers *last_f = NULL; - uint32_t last_tag = 0; - for(int i = 0; i < num_keys; i++) { - uint32_t key = keys[i]; - upb_fhandlers *f = upb_inttable_lookup(&m->fieldtab, key); - uint32_t tag = upb_vencode32(key); - if (last_f) upb_decoder_jit_field(d, last_tag, tag, m, last_f, f); - last_tag = tag; - last_f = f; - } - upb_decoder_jit_field(d, last_tag, 0, m, last_f, NULL); - - free(keys); - - // --------- New code section (does not fall through) ------------------------ - - // End-of-buf / end-of-message. - if (!m->is_group) { - // This case doesn't exist for groups, because there eob really means - // eob, so that case just exits the jit directly. - |=>m->jit_endofbuf_pclabel: - | cmp PTR, DECODER->delim_end - | jb ->exit_jit // We are at eob, but not end-of-submsg. - } - - |=>m->jit_endofmsg_pclabel: - // We are at end-of-submsg: call endmsg handler (if any): - if (m->endmsg) { - // void endmsg(void *closure, upb_status *status) { - | mov ARG1_64, FRAME->closure - | lea ARG2_64, DECODER->dispatcher.status - | callp m->endmsg - } - - if (m->jit_parent_field_done_pclabel == UPB_MULTIPLE) { - | ret - } else if (m->jit_parent_field_done_pclabel == UPB_TOPLEVEL_ONE) { - | jmp ->exit_jit - } else { - | jmp =>m->jit_parent_field_done_pclabel - } - -} - -static const char *dbgfmt = - "JIT encountered unknown field! wt=%d, fn=%d\n"; - -static void upb_decoder_jit(upb_decoder *d) { - | push rbp - | mov rbp, rsp - | push r15 - | push r14 - | push r13 - | push r12 - | push rbx - | mov DECODER, ARG1_64 - | mov FRAME, DECODER:ARG1_64->dispatcher.top - | lea STRREF, DECODER:ARG1_64->strref - | mov CLOSURE, FRAME->closure - | mov PTR, DECODER->ptr - - upb_handlers *h = d->dispatcher.handlers; - if (h->msgs[0]->jit_parent_field_done_pclabel == UPB_MULTIPLE) { - | call =>h->msgs[0]->jit_startmsg_pclabel - | jmp ->exit_jit - } - - // TODO: push return addresses for re-entry (will be necessary for multiple - // buffer support). - for (int i = 0; i < h->msgs_len; i++) upb_decoder_jit_msg(d, h->msgs[i]); - - |->exit_jit: - | pop rbx - | pop r12 - | pop r13 - | pop r14 - | pop r15 - | leave - | ret - |=>0: - | mov rdi, stderr - | mov rsi, dbgfmt - | callp fprintf - | callp abort -} - -void upb_decoder_jit_assignfieldlabs(upb_fhandlers *f, - uint32_t *pclabel_count) { - f->jit_pclabel = (*pclabel_count)++; - f->jit_pclabel_notypecheck = (*pclabel_count)++; - f->jit_submsg_done_pclabel = (*pclabel_count)++; -} - -void upb_decoder_jit_assignmsglabs(upb_mhandlers *m, uint32_t *pclabel_count) { - m->jit_startmsg_pclabel = (*pclabel_count)++; - m->jit_endofbuf_pclabel = (*pclabel_count)++; - m->jit_endofmsg_pclabel = (*pclabel_count)++; - m->jit_unknownfield_pclabel = (*pclabel_count)++; - m->jit_parent_field_done_pclabel = UPB_NONE; - m->max_field_number = 0; - upb_inttable_iter i; - for(i = upb_inttable_begin(&m->fieldtab); !upb_inttable_done(i); - i = upb_inttable_next(&m->fieldtab, i)) { - uint32_t key = upb_inttable_iter_key(i); - m->max_field_number = UPB_MAX(m->max_field_number, key); - upb_fhandlers *f = upb_inttable_iter_value(i); - upb_decoder_jit_assignfieldlabs(f, pclabel_count); - } - // XXX: Won't work for large field numbers; will need to use a upb_table. - m->tablearray = malloc((m->max_field_number + 1) * sizeof(void*)); -} - -// Second pass: for messages that have only one parent, link them to the field -// from which they are called. -void upb_decoder_jit_assignmsglabs2(upb_mhandlers *m) { - upb_inttable_iter i; - for(i = upb_inttable_begin(&m->fieldtab); !upb_inttable_done(i); - i = upb_inttable_next(&m->fieldtab, i)) { - upb_fhandlers *f = upb_inttable_iter_value(i); - if (upb_issubmsgtype(f->type)) { - upb_mhandlers *sub_m = upb_fhandlers_getsubmsg(f); - if (sub_m->jit_parent_field_done_pclabel == UPB_NONE) { - sub_m->jit_parent_field_done_pclabel = f->jit_submsg_done_pclabel; - } else { - sub_m->jit_parent_field_done_pclabel = UPB_MULTIPLE; - } - } - } -} - -void upb_decoder_makejit(upb_decoder *d) { - d->debug_info = NULL; - - // Assign pclabels. - uint32_t pclabel_count = 1; - upb_handlers *h = d->dispatcher.handlers; - for (int i = 0; i < h->msgs_len; i++) - upb_decoder_jit_assignmsglabs(h->msgs[i], &pclabel_count); - for (int i = 0; i < h->msgs_len; i++) - upb_decoder_jit_assignmsglabs2(h->msgs[i]); - - if (h->msgs[0]->jit_parent_field_done_pclabel == UPB_NONE) { - h->msgs[0]->jit_parent_field_done_pclabel = UPB_TOPLEVEL_ONE; - } - - void **globals = malloc(UPB_JIT_GLOBAL__MAX * sizeof(*globals)); - dasm_init(d, 1); - dasm_setupglobal(d, globals, UPB_JIT_GLOBAL__MAX); - dasm_growpc(d, pclabel_count); - dasm_setup(d, upb_jit_actionlist); - - upb_decoder_jit(d); - - dasm_link(d, &d->jit_size); - - d->jit_code = mmap(NULL, d->jit_size, PROT_READ | PROT_WRITE, - MAP_32BIT | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); - - upb_reg_jit_gdb(d); - - dasm_encode(d, d->jit_code); - - // Create dispatch tables. - for (int i = 0; i < h->msgs_len; i++) { - upb_mhandlers *m = h->msgs[i]; - for (uint32_t j = 0; j <= m->max_field_number; j++) { - upb_fhandlers *f = NULL; - for (int k = 0; k < 8; k++) { - f = upb_inttable_lookup(&m->fieldtab, (j << 3) | k); - if (f) break; - } - if (f) { - m->tablearray[j] = d->jit_code + dasm_getpclabel(d, f->jit_pclabel); - } else { - // Don't handle unknown fields yet. - m->tablearray[j] = d->jit_code + dasm_getpclabel(d, 0); - } - } - } - - dasm_free(d); - free(globals); - - mprotect(d->jit_code, d->jit_size, PROT_EXEC | PROT_READ); - - FILE *f = fopen("/tmp/machine-code", "wb"); - fwrite(d->jit_code, d->jit_size, 1, f); - fclose(f); -} - -void upb_decoder_freejit(upb_decoder *d) { - munmap(d->jit_code, d->jit_size); - free(d->debug_info); - // TODO: unregister -} diff --git a/src/upb_def.c b/src/upb_def.c deleted file mode 100644 index 4cd80b1..0000000 --- a/src/upb_def.c +++ /dev/null @@ -1,754 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2008-2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ - -#include -#include -#include -#include "upb_def.h" - -#define alignof(t) offsetof(struct { char c; t x; }, x) - -void upb_deflist_init(upb_deflist *l) { - l->size = 8; - l->defs = malloc(l->size * sizeof(void*)); - l->len = 0; -} - -void upb_deflist_uninit(upb_deflist *l) { - for(uint32_t i = 0; i < l->len; i++) upb_def_unref(l->defs[i]); - free(l->defs); -} - -void upb_deflist_push(upb_deflist *l, upb_def *d) { - if(l->len == l->size) { - l->size *= 2; - l->defs = realloc(l->defs, l->size * sizeof(void*)); - } - l->defs[l->len++] = d; -} - - -/* upb_def ********************************************************************/ - -static void upb_msgdef_free(upb_msgdef *m); -static void upb_enumdef_free(upb_enumdef *e); -static void upb_unresolveddef_free(struct _upb_unresolveddef *u); - -#ifndef NDEBUG -static bool upb_def_ismutable(upb_def *def) { return def->symtab == NULL; } -#endif - -static void upb_def_free(upb_def *def) { - switch (def->type) { - case UPB_DEF_MSG: upb_msgdef_free(upb_downcast_msgdef(def)); break; - case UPB_DEF_ENUM: upb_enumdef_free(upb_downcast_enumdef(def)); break; - case UPB_DEF_UNRESOLVED: - upb_unresolveddef_free(upb_downcast_unresolveddef(def)); break; - default: - assert(false); - } -} - -upb_def *upb_def_dup(upb_def *def) { - switch (def->type) { - case UPB_DEF_MSG: return UPB_UPCAST(upb_msgdef_dup(upb_downcast_msgdef(def))); - case UPB_DEF_ENUM: return UPB_UPCAST(upb_enumdef_dup(upb_downcast_enumdef(def))); - default: assert(false); return NULL; - } -} - -// Prior to being in a symtab, the def's refcount controls the lifetime of the -// def itself. If the refcount falls to zero, the def is deleted. Once the -// def belongs to a symtab, the def is owned by the symtab and its refcount -// determines whether the def owns a ref on the symtab or not. -void upb_def_ref(upb_def *def) { - if (upb_atomic_ref(&def->refcount) && def->symtab) - upb_symtab_ref(def->symtab); -} - -static void upb_def_movetosymtab(upb_def *d, upb_symtab *s) { - assert(upb_atomic_read(&d->refcount) > 0); - d->symtab = s; - if (!upb_atomic_unref(&d->refcount)) upb_symtab_ref(s); - upb_msgdef *m = upb_dyncast_msgdef(d); - if (m) upb_inttable_compact(&m->itof); -} - -void upb_def_unref(upb_def *def) { - if (!def) return; - if (upb_atomic_unref(&def->refcount)) { - if (def->symtab) { - upb_symtab_unref(def->symtab); - // Def might be deleted now. - } else { - upb_def_free(def); - } - } -} - -static void upb_def_init(upb_def *def, upb_deftype_t type) { - def->type = type; - def->fqname = NULL; - def->symtab = NULL; - upb_atomic_init(&def->refcount, 1); -} - -static void upb_def_uninit(upb_def *def) { - //fprintf(stderr, "Freeing def: %p\n", def); - free(def->fqname); -} - - -/* upb_unresolveddef **********************************************************/ - -// Unresolved defs are used as temporary placeholders for a def whose name has -// not been resolved yet. During the name resolution step, all unresolved defs -// are replaced with pointers to the actual def being referenced. -typedef struct _upb_unresolveddef { - upb_def base; - - // The target type name. This may or may not be fully qualified. It is - // tempting to want to use base.fqname for this, but that will be qualified - // which is inappropriate for a name we still have to resolve. - char *name; -} upb_unresolveddef; - -// Is passed a ref on the string. -static upb_unresolveddef *upb_unresolveddef_new(const char *str) { - upb_unresolveddef *def = malloc(sizeof(*def)); - upb_def_init(&def->base, UPB_DEF_UNRESOLVED); - def->name = strdup(str); - return def; -} - -static void upb_unresolveddef_free(struct _upb_unresolveddef *def) { - free(def->name); - upb_def_uninit(&def->base); - free(def); -} - - -/* upb_enumdef ****************************************************************/ - -upb_enumdef *upb_enumdef_new() { - upb_enumdef *e = malloc(sizeof(*e)); - upb_def_init(&e->base, UPB_DEF_ENUM); - upb_strtable_init(&e->ntoi, 0, sizeof(upb_ntoi_ent)); - upb_inttable_init(&e->iton, 0, sizeof(upb_iton_ent)); - return e; -} - -static void upb_enumdef_free(upb_enumdef *e) { - upb_enum_iter i; - for(i = upb_enum_begin(e); !upb_enum_done(i); i = upb_enum_next(e, i)) { - // Frees the ref taken when the string was parsed. - free(upb_enum_iter_name(i)); - } - upb_strtable_free(&e->ntoi); - upb_inttable_free(&e->iton); - upb_def_uninit(&e->base); - free(e); -} - -upb_enumdef *upb_enumdef_dup(upb_enumdef *e) { - upb_enumdef *new_e = upb_enumdef_new(); - upb_enum_iter i; - for(i = upb_enum_begin(e); !upb_enum_done(i); i = upb_enum_next(e, i)) { - assert(upb_enumdef_addval(new_e, upb_enum_iter_name(i), - upb_enum_iter_number(i))); - } - return new_e; -} - -bool upb_enumdef_addval(upb_enumdef *e, char *name, int32_t num) { - if (upb_enumdef_iton(e, num) || upb_enumdef_ntoi(e, name, NULL)) - return false; - upb_strtable_insert(&e->ntoi, name, &num); - upb_inttable_insert(&e->iton, num, strdup(name)); - return true; -} - -void upb_enumdef_setdefault(upb_enumdef *e, int32_t val) { - assert(upb_def_ismutable(UPB_UPCAST(e))); - e->defaultval = val; -} - -upb_enum_iter upb_enum_begin(upb_enumdef *e) { - // We could iterate over either table here; the choice is arbitrary. - return upb_inttable_begin(&e->iton); -} - -upb_enum_iter upb_enum_next(upb_enumdef *e, upb_enum_iter iter) { - return upb_inttable_next(&e->iton, iter); -} - -const char *upb_enumdef_iton(upb_enumdef *def, int32_t num) { - upb_iton_ent *e = upb_inttable_fastlookup(&def->iton, num, sizeof(*e)); - return e ? e->str : NULL; -} - -bool upb_enumdef_ntoil(upb_enumdef *def, char *name, size_t len, int32_t *num) { - upb_ntoi_ent *e = upb_strtable_lookupl(&def->ntoi, name, len); - if (!e) return false; - if (num) *num = e->value; - return true; -} - -bool upb_enumdef_ntoi(upb_enumdef *e, char *name, int32_t *num) { - return upb_enumdef_ntoil(e, name, strlen(name), num); -} - - -/* upb_fielddef ***************************************************************/ - -upb_fielddef *upb_fielddef_new() { - upb_fielddef *f = malloc(sizeof(*f)); - f->msgdef = NULL; - f->def = NULL; - upb_atomic_init(&f->refcount, 1); - f->finalized = false; - f->type = 0; - f->label = UPB_LABEL(OPTIONAL); - f->hasbit = 0; - f->offset = 0; - f->number = 0; // not a valid field number. - f->name = NULL; - f->accessor = NULL; - upb_value_setfielddef(&f->fval, f); - return f; -} - -static void upb_fielddef_free(upb_fielddef *f) { - if (upb_isstring(f)) { - free(upb_value_getptr(f->defaultval)); - } - free(f->name); - free(f); -} - -void upb_fielddef_ref(upb_fielddef *f) { - // TODO. - (void)f; -} - -void upb_fielddef_unref(upb_fielddef *f) { - // TODO. - (void)f; - if (!f) return; - if (upb_atomic_unref(&f->refcount)) { - if (f->msgdef) { - upb_msgdef_unref(f->msgdef); - // fielddef might be deleted now. - } else { - upb_fielddef_free(f); - } - } -} - -upb_fielddef *upb_fielddef_dup(upb_fielddef *f) { - upb_fielddef *newf = upb_fielddef_new(); - newf->msgdef = f->msgdef; - newf->type = f->type; - newf->label = f->label; - newf->number = f->number; - newf->name = f->name; - upb_fielddef_settypename(newf, f->def->fqname); - return f; -} - -static bool upb_fielddef_resolve(upb_fielddef *f, upb_def *def, upb_status *s) { - assert(upb_dyncast_unresolveddef(f->def)); - upb_def_unref(f->def); - f->def = def; - if (f->type == UPB_TYPE(ENUM)) { - // Resolve the enum's default from a string to an integer. - char *str = upb_value_getptr(f->defaultval); - assert(str); // Should point to either a real default or the empty string. - upb_enumdef *e = upb_downcast_enumdef(f->def); - int32_t val = 0; - if (str[0] == '\0') { - upb_value_setint32(&f->defaultval, e->defaultval); - } else { - bool success = upb_enumdef_ntoi(e, str, &val); - free(str); - if (!success) { - upb_status_setf(s, UPB_ERROR, "Default enum value (%s) is not a " - "member of the enum", str); - return false; - } - upb_value_setint32(&f->defaultval, val); - } - } - return true; -} - -void upb_fielddef_setnumber(upb_fielddef *f, int32_t number) { - assert(f->msgdef == NULL); - f->number = number; -} - -void upb_fielddef_setname(upb_fielddef *f, const char *name) { - assert(f->msgdef == NULL); - f->name = strdup(name); -} - -void upb_fielddef_settype(upb_fielddef *f, uint8_t type) { - assert(!f->finalized); - f->type = type; -} - -void upb_fielddef_setlabel(upb_fielddef *f, uint8_t label) { - assert(!f->finalized); - f->label = label; -} -void upb_fielddef_setdefault(upb_fielddef *f, upb_value value) { - assert(!f->finalized); - // TODO: string ownership? - f->defaultval = value; -} - -void upb_fielddef_setfval(upb_fielddef *f, upb_value fval) { - assert(!f->finalized); - // TODO: string ownership? - f->fval = fval; -} - -void upb_fielddef_setaccessor(upb_fielddef *f, struct _upb_accessor_vtbl *vtbl) { - assert(!f->finalized); - f->accessor = vtbl; -} - -void upb_fielddef_settypename(upb_fielddef *f, const char *name) { - upb_def_unref(f->def); - f->def = UPB_UPCAST(upb_unresolveddef_new(name)); -} - -// Returns an ordering of fields based on: -// 1. value size (small to large). -// 2. field number. -static int upb_fielddef_cmpval(const void *_f1, const void *_f2) { - upb_fielddef *f1 = *(void**)_f1; - upb_fielddef *f2 = *(void**)_f2; - size_t size1 = upb_types[f1->type].size; - size_t size2 = upb_types[f2->type].size; - if (size1 != size2) return size1 - size2; - // Otherwise return in number order. - return f1->number - f2->number; -} - -// Returns an ordering of all fields based on: -// 1. required/optional (required fields first). -// 2. field number -static int upb_fielddef_cmphasbit(const void *_f1, const void *_f2) { - upb_fielddef *f1 = *(void**)_f1; - upb_fielddef *f2 = *(void**)_f2; - size_t req1 = f1->label == UPB_LABEL(REQUIRED); - size_t req2 = f2->label == UPB_LABEL(REQUIRED); - if (req1 != req2) return req1 - req2; - // Otherwise return in number order. - return f1->number - f2->number; -} - - -/* upb_msgdef *****************************************************************/ - -upb_msgdef *upb_msgdef_new() { - upb_msgdef *m = malloc(sizeof(*m)); - upb_def_init(&m->base, UPB_DEF_MSG); - upb_inttable_init(&m->itof, 4, sizeof(upb_itof_ent)); - upb_strtable_init(&m->ntof, 4, sizeof(upb_ntof_ent)); - m->size = 0; - m->hasbit_bytes = 0; - m->extension_start = 0; - m->extension_end = 0; - return m; -} - -static void upb_msgdef_free(upb_msgdef *m) { - upb_msg_iter i; - for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) - upb_fielddef_free(upb_msg_iter_field(i)); - upb_strtable_free(&m->ntof); - upb_inttable_free(&m->itof); - upb_def_uninit(&m->base); - free(m); -} - -upb_msgdef *upb_msgdef_dup(upb_msgdef *m) { - upb_msgdef *newm = upb_msgdef_new(); - newm->size = m->size; - newm->hasbit_bytes = m->hasbit_bytes; - newm->extension_start = m->extension_start; - newm->extension_end = m->extension_end; - upb_msg_iter i; - for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) - upb_msgdef_addfield(newm, upb_fielddef_dup(upb_msg_iter_field(i))); - return newm; -} - -void upb_msgdef_setsize(upb_msgdef *m, uint16_t size) { - assert(upb_def_ismutable(UPB_UPCAST(m))); - m->size = size; -} - -void upb_msgdef_sethasbit_bytes(upb_msgdef *m, uint16_t bytes) { - assert(upb_def_ismutable(UPB_UPCAST(m))); - m->hasbit_bytes = bytes; -} - -void upb_msgdef_setextension_start(upb_msgdef *m, uint32_t start) { - assert(upb_def_ismutable(UPB_UPCAST(m))); - m->extension_start = start; -} - -void upb_msgdef_setextension_end(upb_msgdef *m, uint32_t end) { - assert(upb_def_ismutable(UPB_UPCAST(m))); - m->extension_end = end; -} - -bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f) { - assert(upb_atomic_read(&f->refcount) > 0); - if (!upb_atomic_unref(&f->refcount)) upb_msgdef_ref(m); - if (upb_msgdef_itof(m, f->number) || upb_msgdef_ntof(m, f->name)) { - upb_fielddef_unref(f); - return false; - } - assert(f->msgdef == NULL); - f->msgdef = m; - upb_itof_ent itof_ent = {0, f}; - upb_inttable_insert(&m->itof, f->number, &itof_ent); - upb_strtable_insert(&m->ntof, f->name, &f); - return true; -} - -static int upb_div_round_up(int numerator, int denominator) { - /* cf. http://stackoverflow.com/questions/17944/how-to-round-up-the-result-of-integer-division */ - return numerator > 0 ? (numerator - 1) / denominator + 1 : 0; -} - -void upb_msgdef_layout(upb_msgdef *m) { - // Create an ordering over the fields, but only include fields with accessors. - upb_fielddef **sorted_fields = - malloc(sizeof(upb_fielddef*) * upb_msgdef_numfields(m)); - int n = 0; - upb_msg_iter i; - for (i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) { - upb_fielddef *f = upb_msg_iter_field(i); - if (f->accessor) sorted_fields[n++] = f; - } - - m->hasbit_bytes = upb_div_round_up(n, 8); - m->size = m->hasbit_bytes; // + header_size? - - // Assign hasbits. - qsort(sorted_fields, n, sizeof(*sorted_fields), upb_fielddef_cmphasbit); - for (int i = 0; i < n; i++) { - upb_fielddef *f = sorted_fields[i]; - f->hasbit = i; - } - - // Assign value offsets. - qsort(sorted_fields, n, sizeof(*sorted_fields), upb_fielddef_cmpval); - size_t max_align = 0; - for (int i = 0; i < n; i++) { - upb_fielddef *f = sorted_fields[i]; - const upb_type_info *type_info = &upb_types[f->type]; - size_t size = type_info->size; - size_t align = type_info->align; - if (upb_isseq(f)) { - size = sizeof(void*); - align = alignof(void*); - } - - // General alignment rules are: each member must be at an address that is a - // multiple of that type's alignment. Also, the size of the structure as a - // whole must be a multiple of the greatest alignment of any member. - f->offset = upb_align_up(m->size, align); - m->size = f->offset + size; - max_align = UPB_MAX(max_align, align); - } - if (max_align > 0) m->size = upb_align_up(m->size, max_align); - - free(sorted_fields); -} - -upb_msg_iter upb_msg_begin(upb_msgdef *m) { - return upb_inttable_begin(&m->itof); -} - -upb_msg_iter upb_msg_next(upb_msgdef *m, upb_msg_iter iter) { - return upb_inttable_next(&m->itof, iter); -} - - -/* upb_symtabtxn **************************************************************/ - -typedef struct { - upb_def *def; -} upb_symtab_ent; - -void upb_symtabtxn_init(upb_symtabtxn *t) { - upb_strtable_init(&t->deftab, 16, sizeof(upb_symtab_ent)); -} - -void upb_symtabtxn_uninit(upb_symtabtxn *txn) { - upb_strtable *t = &txn->deftab; - upb_strtable_iter i; - for(upb_strtable_begin(&i, t); !upb_strtable_done(&i); upb_strtable_next(&i)) { - const upb_symtab_ent *e = upb_strtable_iter_value(&i); - free(e->def); - } - upb_strtable_free(t); -} - -bool upb_symtabtxn_add(upb_symtabtxn *t, upb_def *def) { - // TODO: check if already present. - upb_symtab_ent e = {def}; - //fprintf(stderr, "txn Inserting: %p, ent: %p\n", e.def, &e); - upb_strtable_insert(&t->deftab, def->fqname, &e); - return true; -} - -#if 0 -err: - // We need to free all defs from "tmptab." - upb_rwlock_unlock(&s->lock); - for(upb_symtab_ent *e = upb_strtable_begin(&tmptab); e; - e = upb_strtable_next(&tmptab, &e->e)) { - upb_def_unref(e->def); - } - upb_strtable_free(&tmptab); - return false; -#endif - -// Given a symbol and the base symbol inside which it is defined, find the -// symbol's definition in t. -static upb_symtab_ent *upb_resolve(upb_strtable *t, - const char *base, const char *sym) { - if(strlen(sym) == 0) return NULL; - if(sym[0] == UPB_SYMBOL_SEPARATOR) { - // Symbols starting with '.' are absolute, so we do a single lookup. - // Slice to omit the leading '.' - return upb_strtable_lookup(t, sym + 1); - } else { - // Remove components from base until we find an entry or run out. - // TODO: This branch is totally broken, but currently not used. - (void)base; - assert(false); - return NULL; - } -} - -void upb_symtabtxn_begin(upb_symtabtxn_iter *i, upb_symtabtxn *t) { - upb_strtable_begin(i, &t->deftab); -} -void upb_symtabtxn_next(upb_symtabtxn_iter *i) { upb_strtable_next(i); } -bool upb_symtabtxn_done(upb_symtabtxn_iter *i) { return upb_strtable_done(i); } -upb_def *upb_symtabtxn_iter_def(upb_symtabtxn_iter *i) { - const upb_symtab_ent *e = upb_strtable_iter_value(i); - return e->def; -} - - -/* upb_symtab public interface ************************************************/ - -static void _upb_symtab_free(upb_strtable *t) { - upb_strtable_iter i; - upb_strtable_begin(&i, t); - for (; !upb_strtable_done(&i); upb_strtable_next(&i)) { - const upb_symtab_ent *e = upb_strtable_iter_value(&i); - assert(upb_atomic_read(&e->def->refcount) == 0); - upb_def_free(e->def); - } - upb_strtable_free(t); -} - -static void upb_symtab_free(upb_symtab *s) { - _upb_symtab_free(&s->symtab); - for (uint32_t i = 0; i < s->olddefs.len; i++) { - upb_def *d = s->olddefs.defs[i]; - assert(upb_atomic_read(&d->refcount) == 0); - upb_def_free(d); - } - upb_rwlock_destroy(&s->lock); - upb_deflist_uninit(&s->olddefs); - free(s); -} - -void upb_symtab_unref(upb_symtab *s) { - if(s && upb_atomic_unref(&s->refcount)) { - upb_symtab_free(s); - } -} - -upb_symtab *upb_symtab_new() { - upb_symtab *s = malloc(sizeof(*s)); - upb_atomic_init(&s->refcount, 1); - upb_rwlock_init(&s->lock); - upb_strtable_init(&s->symtab, 16, sizeof(upb_symtab_ent)); - upb_deflist_init(&s->olddefs); - return s; -} - -upb_def **upb_symtab_getdefs(upb_symtab *s, int *count, upb_deftype_t type) { - upb_rwlock_rdlock(&s->lock); - int total = upb_strtable_count(&s->symtab); - // We may only use part of this, depending on how many symbols are of the - // correct type. - upb_def **defs = malloc(sizeof(*defs) * total); - upb_strtable_iter iter; - upb_strtable_begin(&iter, &s->symtab); - int i = 0; - for(; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { - const upb_symtab_ent *e = upb_strtable_iter_value(&iter); - upb_def *def = e->def; - assert(def); - if(type == UPB_DEF_ANY || def->type == type) - defs[i++] = def; - } - upb_rwlock_unlock(&s->lock); - *count = i; - for(i = 0; i < *count; i++) upb_def_ref(defs[i]); - return defs; -} - -upb_def *upb_symtab_lookup(upb_symtab *s, const char *sym) { - upb_rwlock_rdlock(&s->lock); - upb_symtab_ent *e = upb_strtable_lookup(&s->symtab, sym); - upb_def *ret = NULL; - if(e) { - ret = e->def; - upb_def_ref(ret); - } - upb_rwlock_unlock(&s->lock); - return ret; -} - -upb_def *upb_symtab_resolve(upb_symtab *s, const char *base, const char *sym) { - upb_rwlock_rdlock(&s->lock); - upb_symtab_ent *e = upb_resolve(&s->symtab, base, sym); - upb_def *ret = NULL; - if(e) { - ret = e->def; - upb_def_ref(ret); - } - upb_rwlock_unlock(&s->lock); - return ret; -} - -bool upb_symtab_dfs(upb_def *def, upb_def **open_defs, int n, - upb_symtabtxn *txn) { - // This linear search makes the DFS O(n^2) in the length of the paths. - // Could make this O(n) with a hash table, but n is small. - for (int i = 0; i < n; i++) { - if (def == open_defs[i]) return false; - } - - bool needcopy = false; - upb_msgdef *m = upb_dyncast_msgdef(def); - if (m) { - upb_msg_iter i; - open_defs[n++] = def; - for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) { - upb_fielddef *f = upb_msg_iter_field(i); - if (!upb_hasdef(f)) continue; - needcopy |= upb_symtab_dfs(f->def, open_defs, n, txn); - } - } - - bool replacing = (upb_strtable_lookup(&txn->deftab, m->base.fqname) != NULL); - if (needcopy && !replacing) { - upb_symtab_ent e = {upb_def_dup(def)}; - //fprintf(stderr, "Replacing def: %p\n", e.def); - upb_strtable_insert(&txn->deftab, def->fqname, &e); - replacing = true; - } - return replacing; -} - -bool upb_symtab_commit(upb_symtab *s, upb_symtabtxn *txn, upb_status *status) { - upb_rwlock_wrlock(&s->lock); - - // All existing defs that can reach defs that are being replaced must - // themselves be replaced with versions that will point to the new defs. - // Do a DFS -- any path that finds a new def must replace all ancestors. - upb_strtable *symtab = &s->symtab; - upb_strtable_iter i; - upb_strtable_begin(&i, symtab); - for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { - upb_def *open_defs[UPB_MAX_TYPE_DEPTH]; - const upb_symtab_ent *e = upb_strtable_iter_value(&i); - upb_symtab_dfs(e->def, open_defs, 0, txn); - } - - // Resolve all refs. - upb_strtable *txntab = &txn->deftab; - upb_strtable_begin(&i, txntab); - for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { - const upb_symtab_ent *e = upb_strtable_iter_value(&i); - upb_msgdef *m = upb_dyncast_msgdef(e->def); - if(!m) continue; - // Type names are resolved relative to the message in which they appear. - const char *base = m->base.fqname; - - upb_msg_iter j; - for(j = upb_msg_begin(m); !upb_msg_done(j); j = upb_msg_next(m, j)) { - upb_fielddef *f = upb_msg_iter_field(j); - if(!upb_hasdef(f)) continue; // No resolving necessary. - const char *name = upb_downcast_unresolveddef(f->def)->name; - - // Resolve from either the txntab (pending adds) or symtab (existing - // defs). If both exist, prefer the pending add, because it will be - // overwriting the existing def. - upb_symtab_ent *found; - if(!(found = upb_resolve(txntab, base, name)) && - !(found = upb_resolve(symtab, base, name))) { - upb_status_setf(status, UPB_ERROR, "could not resolve symbol '%s' " - "in context '%s'", name, base); - return false; - } - - // Check the type of the found def. - upb_fieldtype_t expected = upb_issubmsg(f) ? UPB_DEF_MSG : UPB_DEF_ENUM; - //fprintf(stderr, "found: %p\n", found); - //fprintf(stderr, "found->def: %p\n", found->def); - //fprintf(stderr, "found->def->type: %d\n", found->def->type); - if(found->def->type != expected) { - upb_status_setf(status, UPB_ERROR, "Unexpected type"); - return false; - } - if (!upb_fielddef_resolve(f, found->def, status)) return false; - } - } - - // The defs in the transaction have been vetted, and can be moved to the - // symtab without causing errors. - upb_strtable_begin(&i, txntab); - for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { - const upb_symtab_ent *tmptab_e = upb_strtable_iter_value(&i); - upb_def_movetosymtab(tmptab_e->def, s); - upb_symtab_ent *symtab_e = - upb_strtable_lookup(&s->symtab, tmptab_e->def->fqname); - if(symtab_e) { - upb_deflist_push(&s->olddefs, symtab_e->def); - symtab_e->def = tmptab_e->def; - } else { - //fprintf(stderr, "Inserting def: %p\n", tmptab_e->def); - upb_strtable_insert(&s->symtab, tmptab_e->def->fqname, tmptab_e); - } - } - - upb_strtable_clear(txntab); - upb_rwlock_unlock(&s->lock); - upb_symtab_gc(s); - return true; -} - -void upb_symtab_gc(upb_symtab *s) { - (void)s; - // TODO. -} diff --git a/src/upb_def.h b/src/upb_def.h deleted file mode 100644 index 34f5009..0000000 --- a/src/upb_def.h +++ /dev/null @@ -1,465 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009-2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * Provides a mechanism for creating and linking proto definitions. - * These form the protobuf schema, and are used extensively throughout upb: - * - upb_msgdef: describes a "message" construct. - * - upb_fielddef: describes a message field. - * - upb_enumdef: describes an enum. - * (TODO: definitions of services). - * - * These defs are mutable (and not thread-safe) when first created. - * Once they are added to a defbuilder (and later its symtab) they become - * immutable. - */ - -#ifndef UPB_DEF_H_ -#define UPB_DEF_H_ - -#include "upb_atomic.h" -#include "upb_table.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct _upb_symtab; -typedef struct _upb_symtab upb_symtab; - -// All the different kind of defs we support. These correspond 1:1 with -// declarations in a .proto file. -typedef enum { - UPB_DEF_MSG = 1, - UPB_DEF_ENUM, - UPB_DEF_SERVICE, // Not yet implemented. - - UPB_DEF_ANY = -1, // Wildcard for upb_symtab_get*() - UPB_DEF_UNRESOLVED = 99, // Internal-only. -} upb_deftype_t; - - -/* upb_def: base class for defs **********************************************/ - -typedef struct { - char *fqname; // Fully qualified. - upb_symtab *symtab; // Def is mutable iff symtab == NULL. - upb_atomic_t refcount; // Owns a ref on symtab iff (symtab && refcount > 0). - upb_deftype_t type; -} upb_def; - -// Call to ref/unref a def. Can be used at any time, but is not thread-safe -// until the def is in a symtab. While a def is in a symtab, everything -// reachable from that def (the symtab and all defs in the symtab) are -// guaranteed to be alive. -void upb_def_ref(upb_def *def); -void upb_def_unref(upb_def *def); -upb_def *upb_def_dup(upb_def *def); - -#define UPB_UPCAST(ptr) (&(ptr)->base) - - -/* upb_fielddef ***************************************************************/ - -// A upb_fielddef describes a single field in a message. It isn't a full def -// in the sense that it derives from upb_def. It cannot stand on its own; it -// must be part of a upb_msgdef. It is also reference-counted. -typedef struct _upb_fielddef { - struct _upb_msgdef *msgdef; - upb_def *def; // if upb_hasdef(f) - upb_atomic_t refcount; - bool finalized; - - // The following fields may be modified until the def is finalized. - uint8_t type; // Use UPB_TYPE() constants. - uint8_t label; // Use UPB_LABEL() constants. - int16_t hasbit; - uint16_t offset; - int32_t number; - char *name; - upb_value defaultval; // Only meaningful for non-repeated scalars and strings. - upb_value fval; - struct _upb_accessor_vtbl *accessor; -} upb_fielddef; - -upb_fielddef *upb_fielddef_new(); -void upb_fielddef_ref(upb_fielddef *f); -void upb_fielddef_unref(upb_fielddef *f); -upb_fielddef *upb_fielddef_dup(upb_fielddef *f); - -// Read accessors. May be called any time. -INLINE uint8_t upb_fielddef_type(upb_fielddef *f) { return f->type; } -INLINE uint8_t upb_fielddef_label(upb_fielddef *f) { return f->label; } -INLINE int32_t upb_fielddef_number(upb_fielddef *f) { return f->number; } -INLINE char *upb_fielddef_name(upb_fielddef *f) { return f->name; } -INLINE upb_value upb_fielddef_default(upb_fielddef *f) { return f->defaultval; } -INLINE upb_value upb_fielddef_fval(upb_fielddef *f) { return f->fval; } -INLINE bool upb_fielddef_finalized(upb_fielddef *f) { return f->finalized; } -INLINE struct _upb_msgdef *upb_fielddef_msgdef(upb_fielddef *f) { - return f->msgdef; -} -INLINE struct _upb_accessor_vtbl *upb_fielddef_accessor(upb_fielddef *f) { - return f->accessor; -} - -// Only meaningful once the def is in a symtab (returns NULL otherwise, or for -// a fielddef where !upb_hassubdef(f)). -upb_def *upb_fielddef_subdef(upb_fielddef *f); - -// NULL until the fielddef has been added to a msgdef. - -// Write accessors. "Number" and "name" must be set before the fielddef is -// added to a msgdef. For the moment we do not allow these to be set once -// the fielddef is added to a msgdef -- this could be relaxed in the future. -void upb_fielddef_setnumber(upb_fielddef *f, int32_t number); -void upb_fielddef_setname(upb_fielddef *f, const char *name); - -// These writers may be called at any time prior to being put in a symtab. -void upb_fielddef_settype(upb_fielddef *f, uint8_t type); -void upb_fielddef_setlabel(upb_fielddef *f, uint8_t label); -void upb_fielddef_setdefault(upb_fielddef *f, upb_value value); -void upb_fielddef_setfval(upb_fielddef *f, upb_value fval); -void upb_fielddef_setaccessor(upb_fielddef *f, struct _upb_accessor_vtbl *vtbl); -// The name of the message or enum this field is referring to. Must be found -// at name resolution time (when the symtabtxn is committed to the symtab). -void upb_fielddef_settypename(upb_fielddef *f, const char *name); - -// A variety of tests about the type of a field. -INLINE bool upb_issubmsgtype(upb_fieldtype_t type) { - return type == UPB_TYPE(GROUP) || type == UPB_TYPE(MESSAGE); -} -INLINE bool upb_isstringtype(upb_fieldtype_t type) { - return type == UPB_TYPE(STRING) || type == UPB_TYPE(BYTES); -} -INLINE bool upb_isprimitivetype(upb_fieldtype_t type) { - return !upb_issubmsgtype(type) && !upb_isstringtype(type); -} -INLINE bool upb_issubmsg(upb_fielddef *f) { return upb_issubmsgtype(f->type); } -INLINE bool upb_isstring(upb_fielddef *f) { return upb_isstringtype(f->type); } -INLINE bool upb_isseq(upb_fielddef *f) { return f->label == UPB_LABEL(REPEATED); } - -// Does the type of this field imply that it should contain an associated def? -INLINE bool upb_hasdef(upb_fielddef *f) { - return upb_issubmsg(f) || f->type == UPB_TYPE(ENUM); -} - - -/* upb_msgdef *****************************************************************/ - -// Structure that describes a single .proto message type. -typedef struct _upb_msgdef { - upb_def base; - - // Tables for looking up fields by number and name. - upb_inttable itof; // int to field - upb_strtable ntof; // name to field - - // The following fields may be modified until finalized. - uint16_t size; - uint8_t hasbit_bytes; - // The range of tag numbers used to store extensions. - uint32_t extension_start; - uint32_t extension_end; -} upb_msgdef; - -// Hash table entries for looking up fields by name or number. -typedef struct { - bool junk; - upb_fielddef *f; -} upb_itof_ent; -typedef struct { - upb_strtable_entry e; - upb_fielddef *f; -} upb_ntof_ent; - -upb_msgdef *upb_msgdef_new(); -INLINE void upb_msgdef_unref(upb_msgdef *md) { upb_def_unref(UPB_UPCAST(md)); } -INLINE void upb_msgdef_ref(upb_msgdef *md) { upb_def_ref(UPB_UPCAST(md)); } - -// Returns a new msgdef that is a copy of the given msgdef (and a copy of all -// the fields) but with any references to submessages broken and replaced with -// just the name of the submessage. This can be put back into another symtab -// and the names will be re-resolved in the new context. -upb_msgdef *upb_msgdef_dup(upb_msgdef *m); - -// Read accessors. May be called at any time. -INLINE uint16_t upb_msgdef_size(upb_msgdef *m) { return m->size; } -INLINE uint8_t upb_msgdef_hasbit_bytes(upb_msgdef *m) { - return m->hasbit_bytes; -} -INLINE uint32_t upb_msgdef_extension_start(upb_msgdef *m) { - return m->extension_start; -} -INLINE uint32_t upb_msgdef_extension_end(upb_msgdef *m) { - return m->extension_end; -} - -// Write accessors. May only be called before the msgdef is in a symtab. -void upb_msgdef_setsize(upb_msgdef *m, uint16_t size); -void upb_msgdef_sethasbit_bytes(upb_msgdef *m, uint16_t bytes); -void upb_msgdef_setextension_start(upb_msgdef *m, uint32_t start); -void upb_msgdef_setextension_end(upb_msgdef *m, uint32_t end); - -// Adds a fielddef to a msgdef, and passes a ref on the field to the msgdef. -// May only be done before the msgdef is in a symtab. The fielddef's name and -// number must be set, and the message may not already contain any field with -// this name or number -- if it does, the fielddef is unref'd and false is -// returned. The fielddef may not already belong to another message. -bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f); - -// Sets the layout of all fields according to default rules: -// 1. Hasbits for required fields come first, then optional fields. -// 2. Values are laid out in a way that respects alignment rules. -// 3. The order is chosen to minimize memory usage. -// This should only be called once all fielddefs have been added. -// TODO: will likely want the ability to exclude strings/submessages/arrays. -// TODO: will likely want the ability to define a header size. -void upb_msgdef_layout(upb_msgdef *m); - -// Looks up a field by name or number. While these are written to be as fast -// as possible, it will still be faster to cache the results of this lookup if -// possible. These return NULL if no such field is found. -INLINE upb_fielddef *upb_msgdef_itof(upb_msgdef *m, uint32_t i) { - upb_itof_ent *e = (upb_itof_ent*) - upb_inttable_fastlookup(&m->itof, i, sizeof(upb_itof_ent)); - return e ? e->f : NULL; -} - -INLINE upb_fielddef *upb_msgdef_ntof(upb_msgdef *m, char *name) { - upb_ntof_ent *e = (upb_ntof_ent*)upb_strtable_lookup(&m->ntof, name); - return e ? e->f : NULL; -} - -INLINE int upb_msgdef_numfields(upb_msgdef *m) { - return upb_strtable_count(&m->ntof); -} - -// Iteration over fields. The order is undefined. -// Iterators are invalidated when a field is added or removed. -// upb_msg_iter i; -// for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) { -// upb_fielddef *f = upb_msg_iter_field(i); -// // ... -// } -typedef upb_inttable_iter upb_msg_iter; - -upb_msg_iter upb_msg_begin(upb_msgdef *m); -upb_msg_iter upb_msg_next(upb_msgdef *m, upb_msg_iter iter); -INLINE bool upb_msg_done(upb_msg_iter iter) { return upb_inttable_done(iter); } - -// Iterator accessor. -INLINE upb_fielddef *upb_msg_iter_field(upb_msg_iter iter) { - upb_itof_ent *ent = (upb_itof_ent*)upb_inttable_iter_value(iter); - return ent->f; -} - - -/* upb_enumdef ****************************************************************/ - -typedef struct _upb_enumdef { - upb_def base; - upb_strtable ntoi; - upb_inttable iton; - int32_t defaultval; -} upb_enumdef; - -typedef struct { - upb_strtable_entry e; - uint32_t value; -} upb_ntoi_ent; - -typedef struct { - bool junk; - char *str; -} upb_iton_ent; - -upb_enumdef *upb_enumdef_new(); -INLINE void upb_enumdef_ref(upb_enumdef *e) { upb_def_ref(UPB_UPCAST(e)); } -INLINE void upb_enumdef_unref(upb_enumdef *e) { upb_def_unref(UPB_UPCAST(e)); } -upb_enumdef *upb_enumdef_dup(upb_enumdef *e); - -INLINE int32_t upb_enumdef_default(upb_enumdef *e) { return e->defaultval; } - -// May only be set before the enumdef is in a symtab. -void upb_enumdef_setdefault(upb_enumdef *e, int32_t val); - -// Adds a value to the enumdef. Requires that no existing val has this -// name or number (returns false and does not add if there is). May only -// be called before the enumdef is in a symtab. -bool upb_enumdef_addval(upb_enumdef *e, char *name, int32_t num); - -// Lookups from name to integer and vice-versa. -bool upb_enumdef_ntoil(upb_enumdef *e, char *name, size_t len, int32_t *num); -bool upb_enumdef_ntoi(upb_enumdef *e, char *name, int32_t *num); -// Caller does not own the returned string. -const char *upb_enumdef_iton(upb_enumdef *e, int32_t num); - -// Iteration over name/value pairs. The order is undefined. -// Adding an enum val invalidates any iterators. -// upb_enum_iter i; -// for(i = upb_enum_begin(e); !upb_enum_done(i); i = upb_enum_next(e, i)) { -// // ... -// } -typedef upb_inttable_iter upb_enum_iter; - -upb_enum_iter upb_enum_begin(upb_enumdef *e); -upb_enum_iter upb_enum_next(upb_enumdef *e, upb_enum_iter iter); -INLINE bool upb_enum_done(upb_enum_iter iter) { return upb_inttable_done(iter); } - -// Iterator accessors. -INLINE char *upb_enum_iter_name(upb_enum_iter iter) { - upb_iton_ent *e = (upb_iton_ent*)upb_inttable_iter_value(iter); - return e->str; -} -INLINE int32_t upb_enum_iter_number(upb_enum_iter iter) { - return upb_inttable_iter_key(iter); -} - - -/* upb_symtabtxn **************************************************************/ - -// A symbol table transaction is a map of defs that can be added to a symtab -// in one single atomic operation that either succeeds or fails. Mutable defs -// can be added to this map (and perhaps removed, in the future). -// -// A symtabtxn is not thread-safe. - -typedef struct { - upb_strtable deftab; -} upb_symtabtxn; - -void upb_symtabtxn_init(upb_symtabtxn *t); -void upb_symtabtxn_uninit(upb_symtabtxn *t); - -// Adds a def to the symtab. Caller passes a ref on the def to the symtabtxn. -// The def's name must be set and there must not be any existing defs in the -// symtabtxn with this name, otherwise false will be returned and no operation -// will be performed (and the ref on the def will be released). -bool upb_symtabtxn_add(upb_symtabtxn *t, upb_def *def); - -// Gets the def (if any) that is associated with this name in the symtab. -// Caller does *not* inherit a ref on the def. -upb_def *upb_symtabtxn_get(upb_symtabtxn *t, char *name); - -// Iterate over the defs that are part of the transaction. -// The order is undefined. -// The iterator is invalidated by upb_symtabtxn_add(). -// upb_symtabtxn_iter i; -// for(i = upb_symtabtxn_begin(t); !upb_symtabtxn_done(t); -// i = upb_symtabtxn_next(t, i)) { -// upb_def *def = upb_symtabtxn_iter_def(i); -// } -typedef upb_strtable_iter upb_symtabtxn_iter; - -void upb_symtabtxn_begin(upb_symtabtxn_iter* i, upb_symtabtxn *t); -void upb_symtabtxn_next(upb_symtabtxn_iter *i); -bool upb_symtabtxn_done(upb_symtabtxn_iter *i); -upb_def *upb_symtabtxn_iter_def(upb_symtabtxn_iter *iter); - - -/* upb_symtab *****************************************************************/ - -// A SymbolTable is where upb_defs live. It is empty when first constructed. -// Clients add definitions to the symtab (or replace existing definitions) by -// using a upb_symtab_commit() or calling upb_symtab_add(). - -// upb_deflist: A little dynamic array for storing a growing list of upb_defs. -typedef struct { - upb_def **defs; - uint32_t len; - uint32_t size; -} upb_deflist; - -void upb_deflist_init(upb_deflist *l); -void upb_deflist_uninit(upb_deflist *l); -void upb_deflist_push(upb_deflist *l, upb_def *d); - -struct _upb_symtab { - upb_atomic_t refcount; - upb_rwlock_t lock; // Protects all members except the refcount. - upb_strtable symtab; // The symbol table. - upb_deflist olddefs; -}; - -upb_symtab *upb_symtab_new(void); -INLINE void upb_symtab_ref(upb_symtab *s) { upb_atomic_ref(&s->refcount); } -void upb_symtab_unref(upb_symtab *s); - -// Resolves the given symbol using the rules described in descriptor.proto, -// namely: -// -// If the name starts with a '.', it is fully-qualified. Otherwise, C++-like -// scoping rules are used to find the type (i.e. first the nested types -// within this message are searched, then within the parent, on up to the -// root namespace). -// -// If a def is found, the caller owns one ref on the returned def. Otherwise -// returns NULL. -// TODO: make return const -upb_def *upb_symtab_resolve(upb_symtab *s, const char *base, const char *sym); - -// Find an entry in the symbol table with this exact name. If a def is found, -// the caller owns one ref on the returned def. Otherwise returns NULL. -// TODO: make return const -upb_def *upb_symtab_lookup(upb_symtab *s, const char *sym); - -// Gets an array of pointers to all currently active defs in this symtab. The -// caller owns the returned array (which is of length *count) as well as a ref -// to each symbol inside. If type is UPB_DEF_ANY then defs of all types are -// returned, otherwise only defs of the required type are returned. -// TODO: make return const -upb_def **upb_symtab_getdefs(upb_symtab *s, int *n, upb_deftype_t type); - -// Adds a single upb_def into the symtab. A ref on the def is passed to the -// symtab. If any references cannot be resolved, false is returned and the -// symtab is unchanged. The error (if any) is saved to status if non-NULL. -bool upb_symtab_add(upb_symtab *s, upb_def *d, upb_status *status); - -// Adds the set of defs contained in the transaction to the symtab, clearing -// the txn. The entire operation either succeeds or fails. If the operation -// fails, the symtab is unchanged, false is returned, and status indicates -// the error. -bool upb_symtab_commit(upb_symtab *s, upb_symtabtxn *t, upb_status *status); - -// Frees defs that are no longer active in the symtab and are no longer -// reachable. Such defs are not freed when they are replaced in the symtab -// if they are still reachable from defs that are still referenced. -void upb_symtab_gc(upb_symtab *s); - - -/* upb_def casts **************************************************************/ - -// Dynamic casts, for determining if a def is of a particular type at runtime. -#define UPB_DYNAMIC_CAST_DEF(lower, upper) \ - struct _upb_ ## lower; /* Forward-declare. */ \ - INLINE struct _upb_ ## lower *upb_dyncast_ ## lower(upb_def *def) { \ - if(def->type != UPB_DEF_ ## upper) return NULL; \ - return (struct _upb_ ## lower*)def; \ - } -UPB_DYNAMIC_CAST_DEF(msgdef, MSG); -UPB_DYNAMIC_CAST_DEF(enumdef, ENUM); -UPB_DYNAMIC_CAST_DEF(svcdef, SERVICE); -UPB_DYNAMIC_CAST_DEF(unresolveddef, UNRESOLVED); -#undef UPB_DYNAMIC_CAST_DEF - -// Downcasts, for when some wants to assert that a def is of a particular type. -// These are only checked if we are building debug. -#define UPB_DOWNCAST_DEF(lower, upper) \ - struct _upb_ ## lower; /* Forward-declare. */ \ - INLINE struct _upb_ ## lower *upb_downcast_ ## lower(upb_def *def) { \ - assert(def->type == UPB_DEF_ ## upper); \ - return (struct _upb_ ## lower*)def; \ - } -UPB_DOWNCAST_DEF(msgdef, MSG); -UPB_DOWNCAST_DEF(enumdef, ENUM); -UPB_DOWNCAST_DEF(svcdef, SERVICE); -UPB_DOWNCAST_DEF(unresolveddef, UNRESOLVED); -#undef UPB_DOWNCAST_DEF - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_DEF_H_ */ diff --git a/src/upb_descriptor.c b/src/upb_descriptor.c deleted file mode 100644 index f70f1ba..0000000 --- a/src/upb_descriptor.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2008-2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ - -#include "upb_descriptor.h" - -#include -#include -#include "upb_def.h" - -// Returns a newly allocated string that joins input strings together, for example: -// join("Foo.Bar", "Baz") -> "Foo.Bar.Baz" -// join("", "Baz") -> "Baz" -// Caller owns a ref on the returned string. */ -static char *upb_join(char *base, char *name) { - if (!base || strlen(base) == 0) { - return strdup(name); - } else { - char *ret = malloc(strlen(base) + strlen(name) + 2); - ret[0] = '\0'; - strcat(ret, base); - strcat(ret, "."); - strcat(ret, name); - return ret; - } -} - -/* upb_descreader ************************************************************/ - -// A upb_descreader builds a list of defs by handling a parse of a protobuf in -// the format defined in descriptor.proto. The output of a upb_descreader is -// a upb_symtabtxn. - -static upb_def *upb_deflist_last(upb_deflist *l) { - return l->defs[l->len-1]; -} - -// Qualify the defname for all defs starting with offset "start" with "str". -static void upb_deflist_qualify(upb_deflist *l, char *str, int32_t start) { - for(uint32_t i = start; i < l->len; i++) { - upb_def *def = l->defs[i]; - char *name = def->fqname; - def->fqname = upb_join(str, name); - free(name); - } -} - -// Forward declares for top-level file descriptors. -static upb_mhandlers *upb_msgdef_register_DescriptorProto(upb_handlers *h); -static upb_mhandlers * upb_enumdef_register_EnumDescriptorProto(upb_handlers *h); - -void upb_descreader_init(upb_descreader *r, upb_symtabtxn *txn) { - upb_deflist_init(&r->defs); - upb_status_init(&r->status); - r->txn = txn; - r->stack_len = 0; - r->name = NULL; - r->default_string = NULL; -} - -void upb_descreader_uninit(upb_descreader *r) { - free(r->name); - upb_status_uninit(&r->status); - upb_deflist_uninit(&r->defs); - free(r->default_string); - while (r->stack_len > 0) { - upb_descreader_frame *f = &r->stack[--r->stack_len]; - free(f->name); - } -} - -static upb_msgdef *upb_descreader_top(upb_descreader *r) { - if (r->stack_len <= 1) return NULL; - int index = r->stack[r->stack_len-1].start - 1; - assert(index >= 0); - return upb_downcast_msgdef(r->defs.defs[index]); -} - -static upb_def *upb_descreader_last(upb_descreader *r) { - return upb_deflist_last(&r->defs); -} - -// Start/end handlers for FileDescriptorProto and DescriptorProto (the two -// entities that have names and can contain sub-definitions. -void upb_descreader_startcontainer(upb_descreader *r) { - upb_descreader_frame *f = &r->stack[r->stack_len++]; - f->start = r->defs.len; - f->name = NULL; -} - -void upb_descreader_endcontainer(upb_descreader *r) { - upb_descreader_frame *f = &r->stack[--r->stack_len]; - upb_deflist_qualify(&r->defs, f->name, f->start); - free(f->name); - f->name = NULL; -} - -void upb_descreader_setscopename(upb_descreader *r, char *str) { - upb_descreader_frame *f = &r->stack[r->stack_len-1]; - free(f->name); - f->name = str; -} - -// Handlers for google.protobuf.FileDescriptorProto. -static upb_flow_t upb_descreader_FileDescriptorProto_startmsg(void *_r) { - upb_descreader *r = _r; - upb_descreader_startcontainer(r); - return UPB_CONTINUE; -} - -static void upb_descreader_FileDescriptorProto_endmsg(void *_r, - upb_status *status) { - (void)status; - upb_descreader *r = _r; - upb_descreader_endcontainer(r); -} - -static upb_flow_t upb_descreader_FileDescriptorProto_package(void *_r, - upb_value fval, - upb_value val) { - (void)fval; - upb_descreader *r = _r; - upb_descreader_setscopename(r, upb_strref_dup(upb_value_getstrref(val))); - return UPB_CONTINUE; -} - -static upb_mhandlers *upb_descreader_register_FileDescriptorProto( - upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_descreader_FileDescriptorProto_startmsg); - upb_mhandlers_setendmsg(m, &upb_descreader_FileDescriptorProto_endmsg); - -#define FNUM(field) GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ ## field ## __FIELDNUM -#define FTYPE(field) GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ ## field ## __FIELDTYPE - upb_fhandlers *f = - upb_mhandlers_newfhandlers(m, FNUM(PACKAGE), FTYPE(PACKAGE), false); - upb_fhandlers_setvalue(f, &upb_descreader_FileDescriptorProto_package); - - upb_mhandlers_newfhandlers_subm(m, FNUM(MESSAGE_TYPE), FTYPE(MESSAGE_TYPE), true, - upb_msgdef_register_DescriptorProto(h)); - upb_mhandlers_newfhandlers_subm(m, FNUM(ENUM_TYPE), FTYPE(ENUM_TYPE), true, - upb_enumdef_register_EnumDescriptorProto(h)); - // TODO: services, extensions - return m; -} -#undef FNUM -#undef FTYPE - -// Handlers for google.protobuf.FileDescriptorSet. -static void upb_descreader_FileDescriptorSet_onendmsg(void *_r, - upb_status *status) { - // Move all defs (which are now guaranteed to be fully-qualified) to the txn. - upb_descreader *r = _r; - if (upb_ok(status)) { - for (unsigned int i = 0; i < r->defs.len; i++) { - // TODO: check return for duplicate def. - upb_symtabtxn_add(r->txn, r->defs.defs[i]); - } - r->defs.len = 0; - } -} - -static upb_mhandlers *upb_descreader_register_FileDescriptorSet(upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setendmsg(m, upb_descreader_FileDescriptorSet_onendmsg); - -#define FNUM(field) GOOGLE_PROTOBUF_FILEDESCRIPTORSET_ ## field ## __FIELDNUM -#define FTYPE(field) GOOGLE_PROTOBUF_FILEDESCRIPTORSET_ ## field ## __FIELDTYPE - upb_mhandlers_newfhandlers_subm(m, FNUM(FILE), FTYPE(FILE), true, - upb_descreader_register_FileDescriptorProto(h)); - return m; -} -#undef FNUM -#undef FTYPE - -upb_mhandlers *upb_descreader_reghandlers(upb_handlers *h) { - h->should_jit = false; - return upb_descreader_register_FileDescriptorSet(h); -} - -// google.protobuf.EnumValueDescriptorProto. -static upb_flow_t upb_enumdef_EnumValueDescriptorProto_startmsg(void *_r) { - upb_descreader *r = _r; - r->saw_number = false; - r->saw_name = false; - return UPB_CONTINUE; -} - -static upb_flow_t upb_enumdef_EnumValueDescriptorProto_name(void *_r, - upb_value fval, - upb_value val) { - (void)fval; - upb_descreader *r = _r; - free(r->name); - r->name = upb_strref_dup(upb_value_getstrref(val)); - r->saw_name = true; - return UPB_CONTINUE; -} - -static upb_flow_t upb_enumdef_EnumValueDescriptorProto_number(void *_r, - upb_value fval, - upb_value val) { - (void)fval; - upb_descreader *r = _r; - r->number = upb_value_getint32(val); - r->saw_number = true; - return UPB_CONTINUE; -} - -static void upb_enumdef_EnumValueDescriptorProto_endmsg(void *_r, - upb_status *status) { - upb_descreader *r = _r; - if(!r->saw_number || !r->saw_name) { - upb_status_setf(status, UPB_ERROR, "Enum value missing name or number."); - return; - } - upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r)); - if (upb_inttable_count(&e->iton) == 0) { - // The default value of an enum (in the absence of an explicit default) is - // its first listed value. - upb_enumdef_setdefault(e, r->number); - } - upb_enumdef_addval(e, r->name, r->number); - free(r->name); - r->name = NULL; -} - -static upb_mhandlers *upb_enumdef_register_EnumValueDescriptorProto( - upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_enumdef_EnumValueDescriptorProto_startmsg); - upb_mhandlers_setendmsg(m, &upb_enumdef_EnumValueDescriptorProto_endmsg); - -#define FNUM(f) GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_ ## f ## __FIELDNUM -#define FTYPE(f) GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_ ## f ## __FIELDTYPE - upb_fhandlers *f; - f = upb_mhandlers_newfhandlers(m, FNUM(NAME), FTYPE(NAME), false); - upb_fhandlers_setvalue(f, &upb_enumdef_EnumValueDescriptorProto_name); - - f = upb_mhandlers_newfhandlers(m, FNUM(NUMBER), FTYPE(NUMBER), false); - upb_fhandlers_setvalue(f, &upb_enumdef_EnumValueDescriptorProto_number); - return m; -} -#undef FNUM -#undef FTYPE - -// google.protobuf.EnumDescriptorProto. -static upb_flow_t upb_enumdef_EnumDescriptorProto_startmsg(void *_r) { - upb_descreader *r = _r; - upb_deflist_push(&r->defs, UPB_UPCAST(upb_enumdef_new())); - return UPB_CONTINUE; -} - -static void upb_enumdef_EnumDescriptorProto_endmsg(void *_r, upb_status *status) { - upb_descreader *r = _r; - upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r)); - if (upb_descreader_last((upb_descreader*)_r)->fqname == NULL) { - upb_status_setf(status, UPB_ERROR, "Enum had no name."); - return; - } - if (upb_inttable_count(&e->iton) == 0) { - upb_status_setf(status, UPB_ERROR, "Enum had no values."); - return; - } -} - -static upb_flow_t upb_enumdef_EnumDescriptorProto_name(void *_r, - upb_value fval, - upb_value val) { - (void)fval; - upb_descreader *r = _r; - upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r)); - free(e->base.fqname); - e->base.fqname = upb_strref_dup(upb_value_getstrref(val)); - return UPB_CONTINUE; -} - -static upb_mhandlers *upb_enumdef_register_EnumDescriptorProto(upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_enumdef_EnumDescriptorProto_startmsg); - upb_mhandlers_setendmsg(m, &upb_enumdef_EnumDescriptorProto_endmsg); - -#define FNUM(f) GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_ ## f ## __FIELDNUM -#define FTYPE(f) GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_ ## f ## __FIELDTYPE - upb_fhandlers *f = - upb_mhandlers_newfhandlers(m, FNUM(NAME), FTYPE(NAME), false); - upb_fhandlers_setvalue(f, &upb_enumdef_EnumDescriptorProto_name); - - upb_mhandlers_newfhandlers_subm(m, FNUM(VALUE), FTYPE(VALUE), true, - upb_enumdef_register_EnumValueDescriptorProto(h)); - return m; -} -#undef FNUM -#undef FTYPE - -static upb_flow_t upb_fielddef_startmsg(void *_r) { - upb_descreader *r = _r; - r->f = upb_fielddef_new(); - return UPB_CONTINUE; -} - -// Converts the default value in string "str" into "d". Passes a ref on str. -// Returns true on success. -static bool upb_fielddef_parsedefault(char *str, upb_value *d, int type) { - bool success = true; - if (type == UPB_TYPE(STRING) || type == UPB_TYPE(BYTES) || type == UPB_TYPE(ENUM)) { - // We'll keep the ref we had on it. We include enums in this case because - // we need the enumdef to resolve the name, but we may not have it yet. - // We'll resolve it later. - if (!str) str = strdup(""); - upb_value_setptr(d, str); - } else if (type == UPB_TYPE(MESSAGE) || type == UPB_TYPE(GROUP)) { - // We don't expect to get a default value. - free(str); - if (str != NULL) success = false; - } else if (type == UPB_TYPE(BOOL)) { - if (!str || strcmp(str, "false") == 0) - upb_value_setbool(d, false); - else if (strcmp(str, "true") == 0) - upb_value_setbool(d, true); - else - success = false; - free(str); - } else { - // The strto* functions need the string to be NULL-terminated. - if (!str) str = strdup("0"); - char *end; - switch (type) { - case UPB_TYPE(INT32): - case UPB_TYPE(SINT32): - case UPB_TYPE(SFIXED32): { - long val = strtol(str, &end, 0); - if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end) - success = false; - else - upb_value_setint32(d, val); - break; - } - case UPB_TYPE(INT64): - case UPB_TYPE(SINT64): - case UPB_TYPE(SFIXED64): - upb_value_setint64(d, strtoll(str, &end, 0)); - if (errno == ERANGE || *end) success = false; - break; - case UPB_TYPE(UINT32): - case UPB_TYPE(FIXED32): { - unsigned long val = strtoul(str, &end, 0); - if (val > UINT32_MAX || errno == ERANGE || *end) - success = false; - else - upb_value_setuint32(d, val); - break; - } - case UPB_TYPE(UINT64): - case UPB_TYPE(FIXED64): - upb_value_setuint64(d, strtoull(str, &end, 0)); - if (errno == ERANGE || *end) success = false; - break; - case UPB_TYPE(DOUBLE): - upb_value_setdouble(d, strtod(str, &end)); - if (errno == ERANGE || *end) success = false; - break; - case UPB_TYPE(FLOAT): - upb_value_setfloat(d, strtof(str, &end)); - if (errno == ERANGE || *end) success = false; - break; - } - free(str); - } - return success; -} - -static void upb_fielddef_endmsg(void *_r, upb_status *status) { - upb_descreader *r = _r; - upb_fielddef *f = r->f; - // TODO: verify that all required fields were present. - assert(f->number != -1 && f->name != NULL); - assert((f->def != NULL) == upb_hasdef(f)); - - // Field was successfully read, add it as a field of the msgdef. - upb_msgdef *m = upb_descreader_top(r); - upb_msgdef_addfield(m, f); - char *dstr = r->default_string; - r->default_string = NULL; - upb_value val; - if (!upb_fielddef_parsedefault(dstr, &val, f->type)) { - // We don't worry too much about giving a great error message since the - // compiler should have ensured this was correct. - upb_status_setf(status, UPB_ERROR, "Error converting default value."); - return; - } - upb_fielddef_setdefault(f, val); -} - -static upb_flow_t upb_fielddef_ontype(void *_r, upb_value fval, upb_value val) { - (void)fval; - upb_descreader *r = _r; - upb_fielddef_settype(r->f, upb_value_getint32(val)); - return UPB_CONTINUE; -} - -static upb_flow_t upb_fielddef_onlabel(void *_r, upb_value fval, upb_value val) { - (void)fval; - upb_descreader *r = _r; - upb_fielddef_setlabel(r->f, upb_value_getint32(val)); - return UPB_CONTINUE; -} - -static upb_flow_t upb_fielddef_onnumber(void *_r, upb_value fval, upb_value val) { - (void)fval; - upb_descreader *r = _r; - upb_fielddef_setnumber(r->f, upb_value_getint32(val)); - return UPB_CONTINUE; -} - -static upb_flow_t upb_fielddef_onname(void *_r, upb_value fval, upb_value val) { - (void)fval; - upb_descreader *r = _r; - char *name = upb_strref_dup(upb_value_getstrref(val)); - upb_fielddef_setname(r->f, name); - free(name); - return UPB_CONTINUE; -} - -static upb_flow_t upb_fielddef_ontypename(void *_r, upb_value fval, - upb_value val) { - (void)fval; - upb_descreader *r = _r; - char *name = upb_strref_dup(upb_value_getstrref(val)); - upb_fielddef_settypename(r->f, name); - free(name); - return UPB_CONTINUE; -} - -static upb_flow_t upb_fielddef_ondefaultval(void *_r, upb_value fval, - upb_value val) { - (void)fval; - upb_descreader *r = _r; - // Have to convert from string to the correct type, but we might not know the - // type yet. - free(r->default_string); - r->default_string = upb_strref_dup(upb_value_getstrref(val)); - return UPB_CONTINUE; -} - -static upb_mhandlers *upb_fielddef_register_FieldDescriptorProto( - upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_fielddef_startmsg); - upb_mhandlers_setendmsg(m, &upb_fielddef_endmsg); - -#define FIELD(name, handler) \ - upb_fhandlers_setvalue( \ - upb_mhandlers_newfhandlers(m, \ - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_ ## name ## __FIELDNUM, \ - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_ ## name ## __FIELDTYPE, \ - false), \ - handler); - FIELD(TYPE, &upb_fielddef_ontype); - FIELD(LABEL, &upb_fielddef_onlabel); - FIELD(NUMBER, &upb_fielddef_onnumber); - FIELD(NAME, &upb_fielddef_onname); - FIELD(TYPE_NAME, &upb_fielddef_ontypename); - FIELD(DEFAULT_VALUE, &upb_fielddef_ondefaultval); - return m; -} -#undef FNUM -#undef FTYPE - - -// google.protobuf.DescriptorProto. -static upb_flow_t upb_msgdef_startmsg(void *_r) { - upb_descreader *r = _r; - upb_deflist_push(&r->defs, UPB_UPCAST(upb_msgdef_new())); - upb_descreader_startcontainer(r); - return UPB_CONTINUE; -} - -static void upb_msgdef_endmsg(void *_r, upb_status *status) { - upb_descreader *r = _r; - upb_msgdef *m = upb_descreader_top(r); - if(!m->base.fqname) { - upb_status_setf(status, UPB_ERROR, "Encountered message with no name."); - return; - } - - upb_msgdef_layout(m); - upb_descreader_endcontainer(r); -} - -static upb_flow_t upb_msgdef_onname(void *_r, upb_value fval, upb_value val) { - (void)fval; - upb_descreader *r = _r; - assert(val.type == UPB_TYPE(STRING)); - upb_msgdef *m = upb_descreader_top(r); - free(m->base.fqname); - m->base.fqname = upb_strref_dup(upb_value_getstrref(val)); - upb_descreader_setscopename(r, strdup(m->base.fqname)); - return UPB_CONTINUE; -} - -static upb_mhandlers *upb_msgdef_register_DescriptorProto(upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_msgdef_startmsg); - upb_mhandlers_setendmsg(m, &upb_msgdef_endmsg); - -#define FNUM(f) GOOGLE_PROTOBUF_DESCRIPTORPROTO_ ## f ## __FIELDNUM -#define FTYPE(f) GOOGLE_PROTOBUF_DESCRIPTORPROTO_ ## f ## __FIELDTYPE - upb_fhandlers *f = - upb_mhandlers_newfhandlers(m, FNUM(NAME), FTYPE(NAME), false); - upb_fhandlers_setvalue(f, &upb_msgdef_onname); - - upb_mhandlers_newfhandlers_subm(m, FNUM(FIELD), FTYPE(FIELD), true, - upb_fielddef_register_FieldDescriptorProto(h)); - upb_mhandlers_newfhandlers_subm(m, FNUM(ENUM_TYPE), FTYPE(ENUM_TYPE), true, - upb_enumdef_register_EnumDescriptorProto(h)); - - // DescriptorProto is self-recursive, so we must link the definition. - upb_mhandlers_newfhandlers_subm( - m, FNUM(NESTED_TYPE), FTYPE(NESTED_TYPE), true, m); - - // TODO: extensions. - return m; -} -#undef FNUM -#undef FTYPE - diff --git a/src/upb_descriptor.h b/src/upb_descriptor.h deleted file mode 100644 index ee05e2f..0000000 --- a/src/upb_descriptor.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * Routines for building defs by parsing descriptors in descriptor.proto format. - * This only needs to use the public API of upb_symtab. Later we may also - * add routines for dumping a symtab to a descriptor. - */ - -#ifndef UPB_DESCRIPTOR_H -#define UPB_DESCRIPTOR_H - -#include "upb_handlers.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* upb_descreader ************************************************************/ - -// upb_descreader reads a descriptor and puts defs in a upb_symtabtxn. - -// We keep a stack of all the messages scopes we are currently in, as well as -// the top-level file scope. This is necessary to correctly qualify the -// definitions that are contained inside. "name" tracks the name of the -// message or package (a bare name -- not qualified by any enclosing scopes). -typedef struct { - char *name; - // Index of the first def that is under this scope. For msgdefs, the - // msgdef itself is at start-1. - int start; -} upb_descreader_frame; - -typedef struct { - upb_deflist defs; - upb_symtabtxn *txn; - upb_descreader_frame stack[UPB_MAX_TYPE_DEPTH]; - int stack_len; - upb_status status; - - uint32_t number; - char *name; - bool saw_number; - bool saw_name; - - char *default_string; - - upb_fielddef *f; -} upb_descreader; - -// Creates a new descriptor builder that will add defs to the given txn. -void upb_descreader_init(upb_descreader *r, upb_symtabtxn *txn); -void upb_descreader_uninit(upb_descreader *r); - -// Registers handlers that will load descriptor data into a symtabtxn. -// Pass the descreader as the closure. The messages will have -// upb_msgdef_layout() called on them before adding to the txn. -upb_mhandlers *upb_descreader_reghandlers(upb_handlers *h); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/src/upb_encoder.c b/src/upb_encoder.c deleted file mode 100644 index 139dc88..0000000 --- a/src/upb_encoder.c +++ /dev/null @@ -1,421 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ - -#include "upb_encoder.h" - -#include -#include "descriptor.h" - -/* Functions for calculating sizes of wire values. ****************************/ - -static size_t upb_v_uint64_t_size(uint64_t val) { -#ifdef __GNUC__ - int high_bit = 63 - __builtin_clzll(val); // 0-based, undef if val == 0. -#else - int high_bit = 0; - uint64_t tmp = val; - while(tmp >>= 1) high_bit++; -#endif - return val == 0 ? 1 : high_bit / 7 + 1; -} - -static size_t upb_v_int32_t_size(int32_t val) { - // v_uint32's are sign-extended to maintain wire compatibility with int64s. - return upb_v_uint64_t_size((int64_t)val); -} -static size_t upb_v_uint32_t_size(uint32_t val) { - return upb_v_uint64_t_size(val); -} -static size_t upb_f_uint64_t_size(uint64_t val) { - (void)val; // Length is independent of value. - return sizeof(uint64_t); -} -static size_t upb_f_uint32_t_size(uint32_t val) { - (void)val; // Length is independent of value. - return sizeof(uint32_t); -} - - -/* Functions to write wire values. ********************************************/ - -// Since we know in advance the longest that the value could be, we always make -// sure that our buffer is long enough. This saves us from having to perform -// bounds checks. - -// Puts a varint (wire type: UPB_WIRE_TYPE_VARINT). -static uint8_t *upb_put_v_uint64_t(uint8_t *buf, uint64_t val) -{ - do { - uint8_t byte = val & 0x7f; - val >>= 7; - if(val) byte |= 0x80; - *buf++ = byte; - } while(val); - return buf; -} - -// Puts an unsigned 32-bit varint, verbatim. Never uses the high 64 bits. -static uint8_t *upb_put_v_uint32_t(uint8_t *buf, uint32_t val) -{ - return upb_put_v_uint64_t(buf, val); -} - -// Puts a signed 32-bit varint, first sign-extending to 64-bits. We do this to -// maintain wire-compatibility with 64-bit signed integers. -static uint8_t *upb_put_v_int32_t(uint8_t *buf, int32_t val) -{ - return upb_put_v_uint64_t(buf, (int64_t)val); -} - -static void upb_put32(uint8_t *buf, uint32_t val) { - buf[0] = val & 0xff; - buf[1] = (val >> 8) & 0xff; - buf[2] = (val >> 16) & 0xff; - buf[3] = (val >> 24); -} - -// Puts a fixed-length 32-bit integer (wire type: UPB_WIRE_TYPE_32BIT). -static uint8_t *upb_put_f_uint32_t(uint8_t *buf, uint32_t val) -{ - uint8_t *uint32_end = buf + sizeof(uint32_t); -#if UPB_UNALIGNED_READS_OK - *(uint32_t*)buf = val; -#else - upb_put32(buf, val); -#endif - return uint32_end; -} - -// Puts a fixed-length 64-bit integer (wire type: UPB_WIRE_TYPE_64BIT). -static uint8_t *upb_put_f_uint64_t(uint8_t *buf, uint64_t val) -{ - uint8_t *uint64_end = buf + sizeof(uint64_t); -#if UPB_UNALIGNED_READS_OK - *(uint64_t*)buf = val; -#else - upb_put32(buf, (uint32_t)val); - upb_put32(buf, (uint32_t)(val >> 32)); -#endif - return uint64_end; -} - -/* Functions to write and calculate sizes for .proto values. ******************/ - -// Performs zig-zag encoding, which is used by sint32 and sint64. -static uint32_t upb_zzenc_32(int32_t n) { return (n << 1) ^ (n >> 31); } -static uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); } - -/* Use macros to define a set of two functions for each .proto type: - * - * // Converts and writes a .proto value into buf. "end" indicates the end - * // of the current available buffer (if the buffer does not contain enough - * // space UPB_STATUS_NEED_MORE_DATA is returned). On success, *outbuf will - * // point one past the data that was written. - * uint8_t *upb_put_INT32(uint8_t *buf, int32_t val); - * - * // Returns the number of bytes required to encode val. - * size_t upb_get_INT32_size(int32_t val); - * - * // Given a .proto value s (source) convert it to a wire value. - * uint32_t upb_vtowv_INT32(int32_t s); - */ - -#define VTOWV(type, wire_t, val_t) \ - static wire_t upb_vtowv_ ## type(val_t s) - -#define PUT(type, v_or_f, wire_t, val_t, member_name) \ - static uint8_t *upb_put_ ## type(uint8_t *buf, val_t val) { \ - wire_t tmp = upb_vtowv_ ## type(val); \ - return upb_put_ ## v_or_f ## _ ## wire_t(buf, tmp); \ - } - -#define T(type, v_or_f, wire_t, val_t, member_name) \ - static size_t upb_get_ ## type ## _size(val_t val) { \ - return upb_ ## v_or_f ## _ ## wire_t ## _size(val); \ - } \ - VTOWV(type, wire_t, val_t); /* prototype for PUT below */ \ - PUT(type, v_or_f, wire_t, val_t, member_name) \ - VTOWV(type, wire_t, val_t) - -T(INT32, v, int32_t, int32_t, int32) { return (uint32_t)s; } -T(INT64, v, uint64_t, int64_t, int64) { return (uint64_t)s; } -T(UINT32, v, uint32_t, uint32_t, uint32) { return s; } -T(UINT64, v, uint64_t, uint64_t, uint64) { return s; } -T(SINT32, v, uint32_t, int32_t, int32) { return upb_zzenc_32(s); } -T(SINT64, v, uint64_t, int64_t, int64) { return upb_zzenc_64(s); } -T(FIXED32, f, uint32_t, uint32_t, uint32) { return s; } -T(FIXED64, f, uint64_t, uint64_t, uint64) { return s; } -T(SFIXED32, f, uint32_t, int32_t, int32) { return (uint32_t)s; } -T(SFIXED64, f, uint64_t, int64_t, int64) { return (uint64_t)s; } -T(BOOL, v, uint32_t, bool, _bool) { return (uint32_t)s; } -T(ENUM, v, uint32_t, int32_t, int32) { return (uint32_t)s; } -T(DOUBLE, f, uint64_t, double, _double) { - upb_value v; - v._double = s; - return v.uint64; -} -T(FLOAT, f, uint32_t, float, _float) { - upb_value v; - v._float = s; - return v.uint32; -} -#undef VTOWV -#undef PUT -#undef T - -static uint8_t *upb_encode_value(uint8_t *buf, upb_field_type_t ft, upb_value v) -{ -#define CASE(t, member_name) \ - case UPB_TYPE(t): return upb_put_ ## t(buf, v.member_name); - switch(ft) { - CASE(DOUBLE, _double) - CASE(FLOAT, _float) - CASE(INT32, int32) - CASE(INT64, int64) - CASE(UINT32, uint32) - CASE(UINT64, uint64) - CASE(SINT32, int32) - CASE(SINT64, int64) - CASE(FIXED32, uint32) - CASE(FIXED64, uint64) - CASE(SFIXED32, int32) - CASE(SFIXED64, int64) - CASE(BOOL, _bool) - CASE(ENUM, int32) - default: assert(false); return buf; - } -#undef CASE -} - -static uint32_t _upb_get_value_size(upb_field_type_t ft, upb_value v) -{ -#define CASE(t, member_name) \ - case UPB_TYPE(t): return upb_get_ ## t ## _size(v.member_name); - switch(ft) { - CASE(DOUBLE, _double) - CASE(FLOAT, _float) - CASE(INT32, int32) - CASE(INT64, int64) - CASE(UINT32, uint32) - CASE(UINT64, uint64) - CASE(SINT32, int32) - CASE(SINT64, int64) - CASE(FIXED32, uint32) - CASE(FIXED64, uint64) - CASE(SFIXED32, int32) - CASE(SFIXED64, int64) - CASE(BOOL, _bool) - CASE(ENUM, int32) - default: assert(false); return 0; - } -#undef CASE -} - -static uint8_t *_upb_put_tag(uint8_t *buf, upb_field_number_t num, - upb_wire_type_t wt) -{ - return upb_put_UINT32(buf, wt | (num << 3)); -} - -static uint32_t _upb_get_tag_size(upb_field_number_t num) -{ - return upb_get_UINT32_size(num << 3); -} - - -/* upb_sizebuilder ************************************************************/ - -struct upb_sizebuilder { - // Accumulating size for the current level. - uint32_t size; - - // Stack of sizes for our current nesting. - uint32_t stack[UPB_MAX_NESTING], *top; - - // Vector of sizes. - uint32_t *sizes; - int sizes_len; - int sizes_size; - - upb_status status; -}; - -// upb_sink callbacks. -static upb_sink_status _upb_sizebuilder_valuecb(upb_sink *sink, upb_fielddef *f, - upb_value val, - upb_status *status) -{ - (void)status; - upb_sizebuilder *sb = (upb_sizebuilder*)sink; - uint32_t size = 0; - size += _upb_get_tag_size(f->number); - size += _upb_get_value_size(f->type, val); - sb->size += size; - return UPB_SINK_CONTINUE; -} - -static upb_sink_status _upb_sizebuilder_strcb(upb_sink *sink, upb_fielddef *f, - upb_strptr str, - int32_t start, uint32_t end, - upb_status *status) -{ - (void)status; - (void)str; // String data itself is not used. - upb_sizebuilder *sb = (upb_sizebuilder*)sink; - if(start >= 0) { - uint32_t size = 0; - size += _upb_get_tag_size(f->number); - size += upb_get_UINT32_size(end - start); - sb->size += size; - } - return UPB_SINK_CONTINUE; -} - -static upb_sink_status _upb_sizebuilder_startcb(upb_sink *sink, upb_fielddef *f, - upb_status *status) -{ - (void)status; - (void)f; // Unused (we calculate tag size and delimiter in endcb). - upb_sizebuilder *sb = (upb_sizebuilder*)sink; - if(f->type == UPB_TYPE(MESSAGE)) { - *sb->top = sb->size; - sb->top++; - sb->size = 0; - } else { - assert(f->type == UPB_TYPE(GROUP)); - sb->size += _upb_get_tag_size(f->number); - } - return UPB_SINK_CONTINUE; -} - -static upb_sink_status _upb_sizebuilder_endcb(upb_sink *sink, upb_fielddef *f, - upb_status *status) -{ - (void)status; - upb_sizebuilder *sb = (upb_sizebuilder*)sink; - if(f->type == UPB_TYPE(MESSAGE)) { - sb->top--; - if(sb->sizes_len == sb->sizes_size) { - sb->sizes_size *= 2; - sb->sizes = realloc(sb->sizes, sb->sizes_size * sizeof(*sb->sizes)); - } - uint32_t child_size = sb->size; - uint32_t parent_size = *sb->top; - sb->sizes[sb->sizes_len++] = child_size; - // The size according to the parent includes the tag size and delimiter of - // the submessage. - parent_size += upb_get_UINT32_size(child_size); - parent_size += _upb_get_tag_size(f->number); - // Include size accumulated in parent before child began. - sb->size = child_size + parent_size; - } else { - assert(f->type == UPB_TYPE(GROUP)); - // As an optimization, we could just add this number twice in startcb, to - // avoid having to recalculate it. - sb->size += _upb_get_tag_size(f->number); - } - return UPB_SINK_CONTINUE; -} - -upb_sink_callbacks _upb_sizebuilder_sink_vtbl = { - _upb_sizebuilder_valuecb, - _upb_sizebuilder_strcb, - _upb_sizebuilder_startcb, - _upb_sizebuilder_endcb -}; - - -/* upb_sink callbacks *********************************************************/ - -struct upb_encoder { - upb_sink base; - //upb_bytesink *bytesink; - uint32_t *sizes; - int size_offset; -}; - - -// Within one callback we may need to encode up to two separate values. -#define UPB_ENCODER_BUFSIZE (UPB_MAX_ENCODED_SIZE * 2) - -static upb_sink_status _upb_encoder_push_buf(upb_encoder *s, const uint8_t *buf, - size_t len, upb_status *status) -{ - // TODO: conjure a upb_strptr that points to buf. - //upb_strptr ptr; - (void)s; - (void)buf; - (void)status; - size_t written = 5;// = upb_bytesink_onbytes(s->bytesink, ptr); - if(written < len) { - // TODO: mark to skip "written" bytes next time. - return UPB_SINK_STOP; - } else { - return UPB_SINK_CONTINUE; - } -} - -static upb_sink_status _upb_encoder_valuecb(upb_sink *sink, upb_fielddef *f, - upb_value val, upb_status *status) -{ - upb_encoder *s = (upb_encoder*)sink; - uint8_t buf[UPB_ENCODER_BUFSIZE], *ptr = buf; - upb_wire_type_t wt = upb_types[f->type].expected_wire_type; - // TODO: handle packed encoding. - ptr = _upb_put_tag(ptr, f->number, wt); - ptr = upb_encode_value(ptr, f->type, val); - return _upb_encoder_push_buf(s, buf, ptr - buf, status); -} - -static upb_sink_status _upb_encoder_strcb(upb_sink *sink, upb_fielddef *f, - upb_strptr str, - int32_t start, uint32_t end, - upb_status *status) -{ - upb_encoder *s = (upb_encoder*)sink; - uint8_t buf[UPB_ENCODER_BUFSIZE], *ptr = buf; - if(start >= 0) { - ptr = _upb_put_tag(ptr, f->number, UPB_WIRE_TYPE_DELIMITED); - ptr = upb_put_UINT32(ptr, end - start); - } - // TODO: properly handle partially consumed strings and partially supplied - // strings. - _upb_encoder_push_buf(s, buf, ptr - buf, status); - return _upb_encoder_push_buf(s, (uint8_t*)upb_string_getrobuf(str), end - start, status); -} - -static upb_sink_status _upb_encoder_startcb(upb_sink *sink, upb_fielddef *f, - upb_status *status) -{ - upb_encoder *s = (upb_encoder*)sink; - uint8_t buf[UPB_ENCODER_BUFSIZE], *ptr = buf; - if(f->type == UPB_TYPE(GROUP)) { - ptr = _upb_put_tag(ptr, f->number, UPB_WIRE_TYPE_START_GROUP); - } else { - ptr = _upb_put_tag(ptr, f->number, UPB_WIRE_TYPE_DELIMITED); - ptr = upb_put_UINT32(ptr, s->sizes[--s->size_offset]); - } - return _upb_encoder_push_buf(s, buf, ptr - buf, status); -} - -static upb_sink_status _upb_encoder_endcb(upb_sink *sink, upb_fielddef *f, - upb_status *status) -{ - upb_encoder *s = (upb_encoder*)sink; - uint8_t buf[UPB_ENCODER_BUFSIZE], *ptr = buf; - if(f->type != UPB_TYPE(GROUP)) return UPB_SINK_CONTINUE; - ptr = _upb_put_tag(ptr, f->number, UPB_WIRE_TYPE_END_GROUP); - return _upb_encoder_push_buf(s, buf, ptr - buf, status); -} - -upb_sink_callbacks _upb_encoder_sink_vtbl = { - _upb_encoder_valuecb, - _upb_encoder_strcb, - _upb_encoder_startcb, - _upb_encoder_endcb -}; - diff --git a/src/upb_encoder.h b/src/upb_encoder.h deleted file mode 100644 index 64c5047..0000000 --- a/src/upb_encoder.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009-2010 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * Implements a set of upb_handlers that write protobuf data to the binary wire - * format. - * - * For messages that have any submessages, the encoder needs a buffer - * containing the submessage sizes, so they can be properly written at the - * front of each message. Note that groups do *not* have this requirement. - */ - -#ifndef UPB_ENCODER_H_ -#define UPB_ENCODER_H_ - -#include "upb.h" -#include "upb_stream.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* upb_encoder ****************************************************************/ - -// A upb_encoder is a upb_sink that emits data to a upb_bytesink in the protocol -// buffer binary wire format. -struct upb_encoder; -typedef struct upb_encoder upb_encoder; - -upb_encoder *upb_encoder_new(upb_msgdef *md); -void upb_encoder_free(upb_encoder *e); - -// Resets the given upb_encoder such that is is ready to begin encoding, -// outputting data to "bytesink" (which must live until the encoder is -// reset or destroyed). -void upb_encoder_reset(upb_encoder *e, upb_bytesink *bytesink); - -// Returns the upb_sink to which data can be written. The sink is invalidated -// when the encoder is reset or destroyed. Note that if the client wants to -// encode any length-delimited submessages it must first call -// upb_encoder_buildsizes() below. -upb_sink *upb_encoder_sink(upb_encoder *e); - -// Call prior to pushing any data with embedded submessages. "src" must yield -// exactly the same data as what will next be encoded, but in reverse order. -// The encoder iterates over this data in order to determine the sizes of the -// submessages. If any errors are returned by the upb_src, the status will -// be saved in *status. If the client is sure that the upb_src will not throw -// any errors, "status" may be NULL. -void upb_encoder_buildsizes(upb_encoder *e, upb_src *src, upb_status *status); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_ENCODER_H_ */ diff --git a/src/upb_glue.c b/src/upb_glue.c deleted file mode 100644 index 1f5bd3f..0000000 --- a/src/upb_glue.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2010 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ - -#include "upb_decoder.h" -#include "upb_descriptor.h" -#include "upb_glue.h" -#include "upb_msg.h" -#include "upb_strstream.h" -#include "upb_textprinter.h" - -void upb_strtomsg(const char *str, size_t len, void *msg, upb_msgdef *md, - upb_status *status) { - upb_stringsrc strsrc; - upb_stringsrc_init(&strsrc); - upb_stringsrc_reset(&strsrc, str, len); - - upb_decoder d; - upb_decoder_initformsgdef(&d, md); - upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), 0, UINT64_MAX, msg); - upb_decoder_decode(&d, status); - - upb_stringsrc_uninit(&strsrc); - upb_decoder_uninit(&d); -} - -#if 0 -void upb_msgtotext(upb_string *str, upb_msg *msg, upb_msgdef *md, - bool single_line) { - upb_stringsink strsink; - upb_stringsink_init(&strsink); - upb_stringsink_reset(&strsink, str); - - upb_textprinter *p = upb_textprinter_new(); - upb_handlers *h = upb_handlers_new(); - upb_textprinter_reghandlers(h, md); - upb_textprinter_reset(p, upb_stringsink_bytesink(&strsink), single_line); - - upb_status status = UPB_STATUS_INIT; - upb_msg_runhandlers(msg, md, h, p, &status); - // None of {upb_msg_runhandlers, upb_textprinter, upb_stringsink} should be - // capable of returning an error. - assert(upb_ok(&status)); - upb_status_uninit(&status); - - upb_stringsink_uninit(&strsink); - upb_textprinter_free(p); - upb_handlers_unref(h); -} -#endif - -// TODO: read->load. -void upb_read_descriptor(upb_symtab *symtab, const char *str, size_t len, - upb_status *status) { - upb_stringsrc strsrc; - upb_stringsrc_init(&strsrc); - upb_stringsrc_reset(&strsrc, str, len); - - upb_handlers *h = upb_handlers_new(); - upb_descreader_reghandlers(h); - - upb_decoder d; - upb_decoder_initforhandlers(&d, h); - upb_handlers_unref(h); - upb_descreader r; - upb_symtabtxn txn; - upb_symtabtxn_init(&txn); - upb_descreader_init(&r, &txn); - upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), 0, UINT64_MAX, &r); - - upb_decoder_decode(&d, status); - - // Set default accessors and layouts on all messages. - // for msgdef in symtabtxn: - upb_symtabtxn_iter i; - upb_symtabtxn_begin(&i, &txn); - for(; !upb_symtabtxn_done(&i); upb_symtabtxn_next(&i)) { - upb_def *def = upb_symtabtxn_iter_def(&i); - upb_msgdef *md = upb_dyncast_msgdef(def); - if (!md) return; - // For field in msgdef: - upb_msg_iter i; - for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) { - upb_fielddef *f = upb_msg_iter_field(i); - upb_fielddef_setaccessor(f, upb_stdmsg_accessor(f)); - } - upb_msgdef_layout(md); - } - - if (upb_ok(status)) upb_symtab_commit(symtab, &txn, status); - - upb_symtabtxn_uninit(&txn); - upb_descreader_uninit(&r); - upb_stringsrc_uninit(&strsrc); - upb_decoder_uninit(&d); -} - -char *upb_readfile(const char *filename, size_t *len) { - FILE *f = fopen(filename, "rb"); - if(!f) return NULL; - if(fseek(f, 0, SEEK_END) != 0) goto error; - long size = ftell(f); - if(size < 0) goto error; - if(fseek(f, 0, SEEK_SET) != 0) goto error; - char *buf = malloc(size); - if(fread(buf, size, 1, f) != 1) goto error; - fclose(f); - if (len) *len = size; - return buf; - -error: - fclose(f); - return NULL; -} - -void upb_read_descriptorfile(upb_symtab *symtab, const char *fname, - upb_status *status) { - size_t len; - char *data = upb_readfile(fname, &len); - if (!data) { - upb_status_setf(status, UPB_ERROR, "Couldn't read file: %s", fname); - return; - } - upb_read_descriptor(symtab, data, len, status); - free(data); -} diff --git a/src/upb_glue.h b/src/upb_glue.h deleted file mode 100644 index 0448c2f..0000000 --- a/src/upb_glue.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * upb's core components like upb_decoder and upb_msg are carefully designed to - * avoid depending on each other for maximum orthogonality. In other words, - * you can use a upb_decoder to decode into *any* kind of structure; upb_msg is - * just one such structure. A upb_msg can be serialized/deserialized into any - * format, protobuf binary format is just one such format. - * - * However, for convenience we provide functions here for doing common - * operations like deserializing protobuf binary format into a upb_msg. The - * compromise is that this file drags in almost all of upb as a dependency, - * which could be undesirable if you're trying to use a trimmed-down build of - * upb. - * - * While these routines are convenient, they do not reuse any encoding/decoding - * state. For example, if a decoder is JIT-based, it will be re-JITted every - * time these functions are called. For this reason, if you are parsing lots - * of data and efficiency is an issue, these may not be the best functions to - * use (though they are useful for prototyping, before optimizing). - */ - -#ifndef UPB_GLUE_H -#define UPB_GLUE_H - -#include -#include "upb.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Forward-declares so we don't have to include everything in this .h file. -// Clients should use the regular, typedef'd names (eg. upb_string). -struct _upb_msg; -struct _upb_msgdef; -struct _upb_symtab; - -// Decodes the given string, which must be in protobuf binary format, to the -// given upb_msg with msgdef "md", storing the status of the operation in "s". -void upb_strtomsg(const char *str, size_t len, void *msg, - struct _upb_msgdef *md, upb_status *s); - -//void upb_msgtotext(struct _upb_string *str, void *msg, -// struct _upb_msgdef *md, bool single_line); - -void upb_read_descriptor(struct _upb_symtab *symtab, const char *str, size_t len, - upb_status *status); - -void upb_read_descriptorfile(struct _upb_symtab *symtab, const char *fname, - upb_status *status); - -char *upb_readfile(const char *filename, size_t *len); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/src/upb_handlers.c b/src/upb_handlers.c deleted file mode 100644 index f513dfd..0000000 --- a/src/upb_handlers.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ - -#include -#include "upb_handlers.h" - - -/* upb_mhandlers **************************************************************/ - -static upb_mhandlers *upb_mhandlers_new() { - upb_mhandlers *m = malloc(sizeof(*m)); - upb_inttable_init(&m->fieldtab, 8, sizeof(upb_fhandlers)); - m->startmsg = NULL; - m->endmsg = NULL; - m->tablearray = NULL; - m->is_group = false; - return m; -} - -static upb_fhandlers *_upb_mhandlers_newfhandlers(upb_mhandlers *m, uint32_t n, - upb_fieldtype_t type, - bool repeated) { - uint32_t tag = n << 3 | upb_types[type].native_wire_type; - upb_fhandlers *f = upb_inttable_lookup(&m->fieldtab, tag); - if (f) abort(); - upb_fhandlers new_f = {false, type, repeated, - repeated && upb_isprimitivetype(type), UPB_ATOMIC_INIT(0), - n, m, NULL, UPB_NO_VALUE, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, NULL}; - upb_inttable_insert(&m->fieldtab, tag, &new_f); - f = upb_inttable_lookup(&m->fieldtab, tag); - assert(f); - assert(f->type == type); - return f; -} - -upb_fhandlers *upb_mhandlers_newfhandlers(upb_mhandlers *m, uint32_t n, - upb_fieldtype_t type, bool repeated) { - assert(type != UPB_TYPE(MESSAGE)); - assert(type != UPB_TYPE(GROUP)); - return _upb_mhandlers_newfhandlers(m, n, type, repeated); -} - -upb_fhandlers *upb_mhandlers_newfhandlers_subm(upb_mhandlers *m, uint32_t n, - upb_fieldtype_t type, - bool repeated, - upb_mhandlers *subm) { - assert(type == UPB_TYPE(MESSAGE) || type == UPB_TYPE(GROUP)); - assert(subm); - upb_fhandlers *f = _upb_mhandlers_newfhandlers(m, n, type, repeated); - f->submsg = subm; - if (type == UPB_TYPE(GROUP)) - _upb_mhandlers_newfhandlers(subm, n, UPB_TYPE_ENDGROUP, false); - return f; -} - - -/* upb_handlers ***************************************************************/ - -upb_handlers *upb_handlers_new() { - upb_handlers *h = malloc(sizeof(*h)); - upb_atomic_init(&h->refcount, 1); - h->msgs_len = 0; - h->msgs_size = 4; - h->msgs = malloc(h->msgs_size * sizeof(*h->msgs)); - h->should_jit = true; - return h; -} - -void upb_handlers_ref(upb_handlers *h) { upb_atomic_ref(&h->refcount); } - -void upb_handlers_unref(upb_handlers *h) { - if (upb_atomic_unref(&h->refcount)) { - for (int i = 0; i < h->msgs_len; i++) { - upb_mhandlers *mh = h->msgs[i]; - upb_inttable_free(&mh->fieldtab); - free(mh->tablearray); - free(mh); - } - free(h->msgs); - free(h); - } -} - -upb_mhandlers *upb_handlers_newmhandlers(upb_handlers *h) { - if (h->msgs_len == h->msgs_size) { - h->msgs_size *= 2; - h->msgs = realloc(h->msgs, h->msgs_size * sizeof(*h->msgs)); - } - upb_mhandlers *mh = upb_mhandlers_new(); - h->msgs[h->msgs_len++] = mh; - return mh; -} - -typedef struct { - upb_mhandlers *mh; -} upb_mtab_ent; - -static upb_mhandlers *upb_regmsg_dfs(upb_handlers *h, upb_msgdef *m, - upb_onmsgreg *msgreg_cb, - upb_onfieldreg *fieldreg_cb, - void *closure, upb_strtable *mtab) { - upb_mhandlers *mh = upb_handlers_newmhandlers(h); - upb_mtab_ent e = {mh}; - upb_strtable_insert(mtab, m->base.fqname, &e); - if (msgreg_cb) msgreg_cb(closure, mh, m); - upb_msg_iter i; - for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) { - upb_fielddef *f = upb_msg_iter_field(i); - upb_fhandlers *fh; - if (upb_issubmsg(f)) { - upb_mhandlers *sub_mh; - upb_mtab_ent *subm_ent; - // The table lookup is necessary to break the DFS for type cycles. - if ((subm_ent = upb_strtable_lookup(mtab, f->def->fqname)) != NULL) { - sub_mh = subm_ent->mh; - } else { - sub_mh = upb_regmsg_dfs(h, upb_downcast_msgdef(f->def), msgreg_cb, - fieldreg_cb, closure, mtab); - } - fh = upb_mhandlers_newfhandlers_subm( - mh, f->number, f->type, upb_isseq(f), sub_mh); - } else { - fh = upb_mhandlers_newfhandlers(mh, f->number, f->type, upb_isseq(f)); - } - if (fieldreg_cb) fieldreg_cb(closure, fh, f); - } - return mh; -} - -upb_mhandlers *upb_handlers_regmsgdef(upb_handlers *h, upb_msgdef *m, - upb_onmsgreg *msgreg_cb, - upb_onfieldreg *fieldreg_cb, - void *closure) { - upb_strtable mtab; - upb_strtable_init(&mtab, 8, sizeof(upb_mtab_ent)); - upb_mhandlers *ret = - upb_regmsg_dfs(h, m, msgreg_cb, fieldreg_cb, closure, &mtab); - upb_strtable_free(&mtab); - return ret; -} - - -/* upb_dispatcher *************************************************************/ - -static upb_fhandlers toplevel_f = { - false, UPB_TYPE(GROUP), false, false, UPB_ATOMIC_INIT(0), 0, - NULL, NULL, // submsg -#ifdef NDEBUG - {{0}}, -#else - {{0}, -1}, -#endif - NULL, NULL, NULL, NULL, NULL, 0, 0, 0, NULL}; - -void upb_dispatcher_init(upb_dispatcher *d, upb_handlers *h, - upb_skip_handler *skip, upb_exit_handler *exit, - void *srcclosure) { - d->handlers = h; - upb_handlers_ref(h); - for (int i = 0; i < h->msgs_len; i++) { - upb_mhandlers *m = h->msgs[i]; - upb_inttable_compact(&m->fieldtab); - } - d->stack[0].f = &toplevel_f; - d->limit = &d->stack[UPB_MAX_NESTING]; - d->skip = skip; - d->exit = exit; - d->srcclosure = srcclosure; - upb_status_init(&d->status); -} - -upb_dispatcher_frame *upb_dispatcher_reset(upb_dispatcher *d, void *closure) { - d->msgent = d->handlers->msgs[0]; - d->dispatch_table = &d->msgent->fieldtab; - d->top = d->stack; - d->top->closure = closure; - d->top->is_sequence = false; - return d->top; -} - -void upb_dispatcher_uninit(upb_dispatcher *d) { - upb_handlers_unref(d->handlers); - upb_status_uninit(&d->status); -} - -void upb_dispatch_startmsg(upb_dispatcher *d) { - upb_flow_t flow = UPB_CONTINUE; - if (d->msgent->startmsg) d->msgent->startmsg(d->top->closure); - if (flow != UPB_CONTINUE) _upb_dispatcher_unwind(d, flow); -} - -void upb_dispatch_endmsg(upb_dispatcher *d, upb_status *status) { - assert(d->top == d->stack); - if (d->msgent->endmsg) d->msgent->endmsg(d->top->closure, &d->status); - // TODO: should we avoid this copy by passing client's status obj to cbs? - upb_status_copy(status, &d->status); -} - -void indent(upb_dispatcher *d) { - for (int i = 0; i < (d->top - d->stack); i++) fprintf(stderr, " "); -} - -void indentm1(upb_dispatcher *d) { - for (int i = 0; i < (d->top - d->stack - 1); i++) fprintf(stderr, " "); -} - -upb_dispatcher_frame *upb_dispatch_startseq(upb_dispatcher *d, - upb_fhandlers *f) { - //indent(d); - //fprintf(stderr, "START SEQ: %d\n", f->number); - if((d->top+1) >= d->limit) { - upb_status_setf(&d->status, UPB_ERROR, "Nesting too deep."); - _upb_dispatcher_unwind(d, UPB_BREAK); - return d->top; // Dummy. - } - - upb_sflow_t sflow = UPB_CONTINUE_WITH(d->top->closure); - if (f->startseq) sflow = f->startseq(d->top->closure, f->fval); - if (sflow.flow != UPB_CONTINUE) { - _upb_dispatcher_unwind(d, sflow.flow); - return d->top; // Dummy. - } - - ++d->top; - d->top->f = f; - d->top->is_sequence = true; - d->top->closure = sflow.closure; - return d->top; -} - -upb_dispatcher_frame *upb_dispatch_endseq(upb_dispatcher *d) { - //indentm1(d); - //fprintf(stderr, "END SEQ\n"); - assert(d->top > d->stack); - assert(d->top->is_sequence); - upb_fhandlers *f = d->top->f; - --d->top; - upb_flow_t flow = UPB_CONTINUE; - if (f->endseq) flow = f->endseq(d->top->closure, f->fval); - if (flow != UPB_CONTINUE) { - printf("YO, UNWINDING!\n"); - _upb_dispatcher_unwind(d, flow); - return d->top; // Dummy. - } - d->msgent = d->top->f->submsg ? d->top->f->submsg : d->handlers->msgs[0]; - d->dispatch_table = &d->msgent->fieldtab; - return d->top; -} - -upb_dispatcher_frame *upb_dispatch_startsubmsg(upb_dispatcher *d, - upb_fhandlers *f) { - //indent(d); - //fprintf(stderr, "START SUBMSG: %d\n", f->number); - if((d->top+1) >= d->limit) { - upb_status_setf(&d->status, UPB_ERROR, "Nesting too deep."); - _upb_dispatcher_unwind(d, UPB_BREAK); - return d->top; // Dummy. - } - - upb_sflow_t sflow = UPB_CONTINUE_WITH(d->top->closure); - if (f->startsubmsg) sflow = f->startsubmsg(d->top->closure, f->fval); - if (sflow.flow != UPB_CONTINUE) { - _upb_dispatcher_unwind(d, sflow.flow); - return d->top; // Dummy. - } - - ++d->top; - d->top->f = f; - d->top->is_sequence = false; - d->top->closure = sflow.closure; - d->msgent = f->submsg; - d->dispatch_table = &d->msgent->fieldtab; - upb_dispatch_startmsg(d); - return d->top; -} - -upb_dispatcher_frame *upb_dispatch_endsubmsg(upb_dispatcher *d) { - //indentm1(d); - //fprintf(stderr, "END SUBMSG\n"); - assert(d->top > d->stack); - assert(!d->top->is_sequence); - upb_fhandlers *f = d->top->f; - if (d->msgent->endmsg) d->msgent->endmsg(d->top->closure, &d->status); - d->msgent = d->top->f->msg; - d->dispatch_table = &d->msgent->fieldtab; - --d->top; - upb_flow_t flow = UPB_CONTINUE; - if (f->endsubmsg) f->endsubmsg(d->top->closure, f->fval); - if (flow != UPB_CONTINUE) _upb_dispatcher_unwind(d, flow); - return d->top; -} - -bool upb_dispatcher_stackempty(upb_dispatcher *d) { - return d->top == d->stack; -} - -void _upb_dispatcher_unwind(upb_dispatcher *d, upb_flow_t flow) { - upb_dispatcher_frame *frame = d->top; - while (1) { - frame->f->submsg->endmsg(frame->closure, &d->status); - frame->f->endsubmsg(frame->closure, frame->f->fval); - --frame; - if (frame < d->stack) { d->exit(d->srcclosure); return; } - d->top = frame; - if (flow == UPB_SKIPSUBMSG) return; - } -} diff --git a/src/upb_handlers.h b/src/upb_handlers.h deleted file mode 100644 index 1ccc59f..0000000 --- a/src/upb_handlers.h +++ /dev/null @@ -1,373 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2010-2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * upb_handlers is a generic visitor-like interface for iterating over a stream - * of protobuf data. You can register function pointers that will be called - * for each message and/or field as the data is being parsed or iterated over, - * without having to know the source format that we are parsing from. This - * decouples the parsing logic from the processing logic. - */ - -#ifndef UPB_HANDLERS_H -#define UPB_HANDLERS_H - -#include -#include "upb.h" -#include "upb_def.h" -#include "upb_bytestream.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Handlers protocol definition ***********************************************/ - -// A upb_handlers object represents a graph of handlers. Each message can have -// a set of handlers as well as a set of fields which themselves have handlers. -// Fields that represent submessages or groups are linked to other message -// handlers, so the overall set of handlers can form a graph structure (which -// may be cyclic). -// -// The upb_mhandlers (message handlers) object can have the following handlers: -// -// static upb_flow_t startmsg(void *closure) { -// // Called when the message begins. "closure" was supplied by our caller. -// return UPB_CONTINUE; -// } -// -// static void endmsg(void *closure, upb_status *status) { -// // Called when processing of this message ends, whether in success or -// // failure. "status" indicates the final status of processing, and can -// / also be modified in-place to update the final status. -// // -// // Since this callback is guaranteed to always be called eventually, it -// // can be used to free any resources that were allocated during processing. -// } -// -// TODO: unknown field handler. -// -// The upb_fhandlers (field handlers) object can have the following handlers: -// -// static upb_flow_t value(void *closure, upb_value fval, upb_value val) { -// // Called when the field's value is encountered. "fval" contains -// // whatever value was bound to this field at registration type -// // (for upb_register_all(), this will be the field's upb_fielddef*). -// return UPB_CONTINUE; -// } -// -// static upb_sflow_t startsubmsg(void *closure, upb_value fval) { -// // Called when a submessage begins. The second element of the return -// // value is the closure for the submessage. -// return UPB_CONTINUE_WITH(closure); -// } -// -// static upb_flow_t endsubmsg(void *closure, upb_value fval) { -// // Called when a submessage ends. -// return UPB_CONTINUE; -// } -// -// static upb_sflow_t startseqmsg(void *closure, upb_value fval) { -// // Called when a sequence (repeated field) begins. The second element -// // of the return value is the closure for the sequence. -// return UPB_CONTINUE_WITH(closure); -// } -// -// static upb_flow_t endeqvoid *closure, upb_value fval) { -// // Called when a sequence ends. -// return UPB_CONTINUE; -// } -// -// All handlers except the endmsg handler return a value from this enum, to -// control whether parsing will continue or not. -typedef enum { - // Data source should continue calling callbacks. - UPB_CONTINUE = 0, - - // Halt processing permanently (in a non-resumable way). The endmsg handlers - // for any currently open messages will be called which can supply a more - // specific status message. No further input data will be consumed. - UPB_BREAK, - - // Skips to the end of the current submessage (or if we are at the top - // level, skips to the end of the entire message). In other words, it is - // like a UPB_BREAK that applies only to the current level. - // - // If you UPB_SKIPSUBMSG from a startmsg handler, the endmsg handler will - // be called to perform cleanup and return a status. Returning - // UPB_SKIPSUBMSG from a startsubmsg handler will *not* call the startmsg, - // endmsg, or endsubmsg handlers. - // - // If UPB_SKIPSUBMSG is called from the top-level message, no further input - // data will be consumed. - UPB_SKIPSUBMSG, - - // TODO: Add UPB_SUSPEND, for resumable producers/consumers. -} upb_flow_t; - -// The startsubmsg handler needs to also pass a closure to the submsg. -typedef struct { - upb_flow_t flow; - void *closure; -} upb_sflow_t; - -INLINE upb_sflow_t UPB_SFLOW(upb_flow_t flow, void *closure) { - upb_sflow_t ret = {flow, closure}; - return ret; -} -#define UPB_CONTINUE_WITH(c) UPB_SFLOW(UPB_CONTINUE, c) -#define UPB_SBREAK UPB_SFLOW(UPB_BREAK, NULL) - -// Typedefs for all of the handler functions defined above. -typedef upb_flow_t (upb_startmsg_handler)(void *c); -typedef void (upb_endmsg_handler)(void *c, upb_status *status); -typedef upb_flow_t (upb_value_handler)(void *c, upb_value fval, upb_value val); -typedef upb_sflow_t (upb_startfield_handler)(void *closure, upb_value fval); -typedef upb_flow_t (upb_endfield_handler)(void *closure, upb_value fval); - - -/* upb_fhandlers **************************************************************/ - -// A upb_fhandlers object represents the set of handlers associated with one -// specific message field. -struct _upb_decoder; -struct _upb_mhandlers; -typedef struct _upb_fieldent { - bool junk; - upb_fieldtype_t type; - bool repeated; - bool is_repeated_primitive; - upb_atomic_t refcount; - uint32_t number; - struct _upb_mhandlers *msg; - struct _upb_mhandlers *submsg; // Set iff upb_issubmsgtype(type) == true. - upb_value fval; - upb_value_handler *value; - upb_startfield_handler *startsubmsg; - upb_endfield_handler *endsubmsg; - upb_startfield_handler *startseq; - upb_endfield_handler *endseq; - uint32_t jit_pclabel; - uint32_t jit_pclabel_notypecheck; - uint32_t jit_submsg_done_pclabel; - void (*decode)(struct _upb_decoder *d, struct _upb_fieldent *f); -} upb_fhandlers; - -// fhandlers are created as part of a upb_handlers instance, but can be ref'd -// and unref'd to prolong the life of the handlers. -void upb_fhandlers_ref(upb_fhandlers *m); -void upb_fhandlers_unref(upb_fhandlers *m); - -// upb_fhandlers accessors -#define UPB_FHANDLERS_ACCESSORS(name, type) \ - INLINE void upb_fhandlers_set ## name(upb_fhandlers *f, type v){f->name = v;} \ - INLINE type upb_fhandlers_get ## name(upb_fhandlers *f) { return f->name; } -UPB_FHANDLERS_ACCESSORS(fval, upb_value) -UPB_FHANDLERS_ACCESSORS(value, upb_value_handler*) -UPB_FHANDLERS_ACCESSORS(startsubmsg, upb_startfield_handler*) -UPB_FHANDLERS_ACCESSORS(endsubmsg, upb_endfield_handler*) -UPB_FHANDLERS_ACCESSORS(startseq, upb_startfield_handler*) -UPB_FHANDLERS_ACCESSORS(endseq, upb_endfield_handler*) -UPB_FHANDLERS_ACCESSORS(submsg, struct _upb_mhandlers*) - - -/* upb_mhandlers **************************************************************/ - -// A upb_mhandlers object represents the set of handlers associated with a -// message in the graph of messages. - -typedef struct _upb_mhandlers { - upb_atomic_t refcount; - upb_startmsg_handler *startmsg; - upb_endmsg_handler *endmsg; - upb_inttable fieldtab; // Maps field number -> upb_fhandlers. - uint32_t jit_startmsg_pclabel; - uint32_t jit_endofbuf_pclabel; - uint32_t jit_endofmsg_pclabel; - uint32_t jit_unknownfield_pclabel; - bool is_group; - int32_t jit_parent_field_done_pclabel; - uint32_t max_field_number; - // Currently keyed on field number. Could also try keying it - // on encoded or decoded tag, or on encoded field number. - void **tablearray; -} upb_mhandlers; - -// mhandlers are created as part of a upb_handlers instance, but can be ref'd -// and unref'd to prolong the life of the handlers. -void upb_mhandlers_ref(upb_mhandlers *m); -void upb_mhandlers_unref(upb_mhandlers *m); - -// Creates a new field with the given name and number. There must not be an -// existing field with either this name or number or abort() will be called. -// TODO: this should take a name also. -upb_fhandlers *upb_mhandlers_newfhandlers(upb_mhandlers *m, uint32_t n, - upb_fieldtype_t type, bool repeated); -// Like the previous but for MESSAGE or GROUP fields. For GROUP fields, the -// given submessage must not have any fields with this field number. -upb_fhandlers *upb_mhandlers_newfhandlers_subm(upb_mhandlers *m, uint32_t n, - upb_fieldtype_t type, - bool repeated, - upb_mhandlers *subm); - -// upb_mhandlers accessors. -#define UPB_MHANDLERS_ACCESSORS(name, type) \ - INLINE void upb_mhandlers_set ## name(upb_mhandlers *m, type v){m->name = v;} \ - INLINE type upb_mhandlers_get ## name(upb_mhandlers *m) { return m->name; } -UPB_MHANDLERS_ACCESSORS(startmsg, upb_startmsg_handler*); -UPB_MHANDLERS_ACCESSORS(endmsg, upb_endmsg_handler*); - - -/* upb_handlers ***************************************************************/ - -struct _upb_handlers { - upb_atomic_t refcount; - upb_mhandlers **msgs; // Array of msgdefs, [0]=toplevel. - int msgs_len, msgs_size; - bool should_jit; -}; -typedef struct _upb_handlers upb_handlers; - -upb_handlers *upb_handlers_new(); -void upb_handlers_ref(upb_handlers *h); -void upb_handlers_unref(upb_handlers *h); - -// Appends a new message to the graph of handlers and returns it. This message -// can be obtained later at index upb_handlers_msgcount()-1. All handlers will -// be initialized to no-op handlers. -upb_mhandlers *upb_handlers_newmhandlers(upb_handlers *h); -upb_mhandlers *upb_handlers_getmhandlers(upb_handlers *h, int index); - -// Convenience function for registering handlers for all messages and -// fields in a msgdef and all its children. For every registered message -// "msgreg_cb" will be called with the newly-created mhandlers, and likewise -// with "fieldreg_cb" -// -// See upb_handlers_reghandlerset() below for an example. -typedef void upb_onmsgreg(void *closure, upb_mhandlers *mh, upb_msgdef *m); -typedef void upb_onfieldreg(void *closure, upb_fhandlers *mh, upb_fielddef *m); -upb_mhandlers *upb_handlers_regmsgdef(upb_handlers *h, upb_msgdef *m, - upb_onmsgreg *msgreg_cb, - upb_onfieldreg *fieldreg_cb, - void *closure); - -// Convenience function for registering a set of handlers for all messages and -// fields in a msgdef and its children, with the fval bound to the upb_fielddef. -// Any of the handlers may be NULL, in which case no callback will be set and -// the nop callback will be used. -typedef struct { - upb_startmsg_handler *startmsg; - upb_endmsg_handler *endmsg; - upb_value_handler *value; - upb_startfield_handler *startsubmsg; - upb_endfield_handler *endsubmsg; - upb_startfield_handler *startseq; - upb_endfield_handler *endseq; -} upb_handlerset; - -INLINE void upb_onmreg_hset(void *c, upb_mhandlers *mh, upb_msgdef *m) { - (void)m; - upb_handlerset *hs = (upb_handlerset*)c; - if (hs->startmsg) upb_mhandlers_setstartmsg(mh, hs->startmsg); - if (hs->endmsg) upb_mhandlers_setendmsg(mh, hs->endmsg); -} -INLINE void upb_onfreg_hset(void *c, upb_fhandlers *fh, upb_fielddef *f) { - upb_handlerset *hs = (upb_handlerset*)c; - if (hs->value) upb_fhandlers_setvalue(fh, hs->value); - if (hs->startsubmsg) upb_fhandlers_setstartsubmsg(fh, hs->startsubmsg); - if (hs->endsubmsg) upb_fhandlers_setendsubmsg(fh, hs->endsubmsg); - if (hs->startseq) upb_fhandlers_setstartseq(fh, hs->startseq); - if (hs->endseq) upb_fhandlers_setendseq(fh, hs->endseq); - upb_value val; - upb_value_setfielddef(&val, f); - upb_fhandlers_setfval(fh, val); -} -INLINE upb_mhandlers *upb_handlers_reghandlerset(upb_handlers *h, upb_msgdef *m, - upb_handlerset *hs) { - return upb_handlers_regmsgdef(h, m, &upb_onmreg_hset, &upb_onfreg_hset, hs); -} - - -/* upb_dispatcher *************************************************************/ - -// upb_dispatcher can be used by sources of data to invoke the appropriate -// handlers on a upb_handlers object. Besides maintaining the runtime stack of -// closures and handlers, the dispatcher checks the return status of user -// callbacks and properly handles statuses other than UPB_CONTINUE, invoking -// "skip" or "exit" handlers on the underlying data source as appropriate. - -typedef struct { - upb_fhandlers *f; - void *closure; - - // Members to use as the data source requires. - void *srcclosure; - uint64_t end_ofs; - uint16_t msgindex; - uint16_t fieldindex; - - bool is_sequence; // frame represents seq or submsg? (f might be both). - bool is_packed; // !upb_issubmsg(f) && end_ofs != UINT64_MAX (strings aren't pushed) -} upb_dispatcher_frame; - -// Called when some of the input needs to be skipped. All frames from -// top to bottom, inclusive, should be skipped. -typedef void upb_skip_handler(void *, upb_dispatcher_frame *top, - upb_dispatcher_frame *bottom); -typedef void upb_exit_handler(void *); - -typedef struct { - upb_dispatcher_frame *top, *limit; - - upb_handlers *handlers; - - // Msg and dispatch table for the current level. - upb_mhandlers *msgent; - upb_inttable *dispatch_table; - upb_skip_handler *skip; - upb_exit_handler *exit; - void *srcclosure; - - // Stack. - upb_status status; - upb_dispatcher_frame stack[UPB_MAX_NESTING]; -} upb_dispatcher; - -void upb_dispatcher_init(upb_dispatcher *d, upb_handlers *h, - upb_skip_handler *skip, upb_exit_handler *exit, - void *closure); -upb_dispatcher_frame *upb_dispatcher_reset(upb_dispatcher *d, void *topclosure); -void upb_dispatcher_uninit(upb_dispatcher *d); - -// Tests whether the runtime stack is in the base level message. -bool upb_dispatcher_stackempty(upb_dispatcher *d); - -// Looks up a field by number for the current message. -INLINE upb_fhandlers *upb_dispatcher_lookup(upb_dispatcher *d, uint32_t n) { - return (upb_fhandlers*)upb_inttable_fastlookup( - d->dispatch_table, n, sizeof(upb_fhandlers)); -} - -void _upb_dispatcher_unwind(upb_dispatcher *d, upb_flow_t flow); - -// Dispatch functions -- call the user handler and handle errors. -INLINE void upb_dispatch_value(upb_dispatcher *d, upb_fhandlers *f, - upb_value val) { - upb_flow_t flow = UPB_CONTINUE; - if (f->value) flow = f->value(d->top->closure, f->fval, val); - if (flow != UPB_CONTINUE) _upb_dispatcher_unwind(d, flow); -} -void upb_dispatch_startmsg(upb_dispatcher *d); -void upb_dispatch_endmsg(upb_dispatcher *d, upb_status *status); -upb_dispatcher_frame *upb_dispatch_startsubmsg(upb_dispatcher *d, upb_fhandlers *f); -upb_dispatcher_frame *upb_dispatch_endsubmsg(upb_dispatcher *d); -upb_dispatcher_frame *upb_dispatch_startseq(upb_dispatcher *d, upb_fhandlers *f); -upb_dispatcher_frame *upb_dispatch_endseq(upb_dispatcher *d); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/src/upb_msg.c b/src/upb_msg.c deleted file mode 100644 index 83fa6ff..0000000 --- a/src/upb_msg.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2010 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * Data structure for storing a message of protobuf data. - */ - -#include "upb.h" -#include "upb_msg.h" - -void upb_msg_clear(void *msg, upb_msgdef *md) { - memset(msg, 0, md->hasbit_bytes); - // TODO: set primitive fields to defaults? -} - -void *upb_stdarray_append(upb_stdarray *a, size_t type_size) { - assert(a->len <= a->size); - if (a->len == a->size) { - size_t old_size = a->size; - a->size = old_size == 0 ? 8 : (old_size * 2); - a->ptr = realloc(a->ptr, a->size * type_size); - memset(&a->ptr[old_size * type_size], 0, (a->size - old_size) * type_size); - } - return &a->ptr[a->len++ * type_size]; -} - -#if 0 -static upb_flow_t upb_msg_dispatch(upb_msg *msg, upb_msgdef *md, - upb_dispatcher *d); - -static upb_flow_t upb_msg_pushval(upb_value val, upb_fielddef *f, - upb_dispatcher *d, upb_fhandlers *hf) { - if (upb_issubmsg(f)) { - upb_msg *msg = upb_value_getmsg(val); - upb_dispatch_startsubmsg(d, hf); - upb_msg_dispatch(msg, upb_downcast_msgdef(f->def), d); - upb_dispatch_endsubmsg(d); - } else { - upb_dispatch_value(d, hf, val); - } - return UPB_CONTINUE; -} - -static upb_flow_t upb_msg_dispatch(upb_msg *msg, upb_msgdef *md, - upb_dispatcher *d) { - upb_msg_iter i; - for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) { - upb_fielddef *f = upb_msg_iter_field(i); - if (!upb_msg_has(msg, f)) continue; - upb_fhandlers *hf = upb_dispatcher_lookup(d, f->number); - if (!hf) continue; - upb_value val = upb_msg_get(msg, f); - if (upb_isarray(f)) { - upb_array *arr = upb_value_getarr(val); - for (uint32_t j = 0; j < upb_array_len(arr); ++j) { - upb_msg_pushval(upb_array_get(arr, f, j), f, d, hf); - } - } else { - upb_msg_pushval(val, f, d, hf); - } - } - return UPB_CONTINUE; -} - -void upb_msg_runhandlers(upb_msg *msg, upb_msgdef *md, upb_handlers *h, - void *closure, upb_status *status) { - upb_dispatcher d; - upb_dispatcher_init(&d, h, NULL, NULL, NULL); - upb_dispatcher_reset(&d, closure); - - upb_dispatch_startmsg(&d); - upb_msg_dispatch(msg, md, &d); - upb_dispatch_endmsg(&d, status); - - upb_dispatcher_uninit(&d); -} -#endif - -/* Standard writers. **********************************************************/ - -void upb_stdmsg_sethas(void *_m, upb_value fval) { - char *m = _m; - upb_fielddef *f = upb_value_getfielddef(fval); - if (f->hasbit >= 0) m[f->hasbit / 8] |= (1 << (f->hasbit % 8)); -} - -bool upb_stdmsg_has(void *_m, upb_value fval) { - char *m = _m; - upb_fielddef *f = upb_value_getfielddef(fval); - return f->hasbit < 0 || (m[f->hasbit / 8] & (1 << (f->hasbit % 8))); -} - -#define UPB_ACCESSORS(type, ctype) \ - upb_flow_t upb_stdmsg_set ## type (void *_m, upb_value fval, \ - upb_value val) { \ - upb_fielddef *f = upb_value_getfielddef(fval); \ - uint8_t *m = _m; \ - upb_stdmsg_sethas(_m, fval); \ - *(ctype*)&m[f->offset] = upb_value_get ## type(val); \ - return UPB_CONTINUE; \ - } \ - \ - upb_flow_t upb_stdmsg_set ## type ## _r(void *a, upb_value _fval, \ - upb_value val) { \ - (void)_fval; \ - ctype *p = upb_stdarray_append((upb_stdarray*)a, sizeof(ctype)); \ - *p = upb_value_get ## type(val); \ - return UPB_CONTINUE; \ - } \ - \ - upb_value upb_stdmsg_get ## type(void *_m, upb_value fval) { \ - uint8_t *m = _m; \ - upb_fielddef *f = upb_value_getfielddef(fval); \ - upb_value ret; \ - upb_value_set ## type(&ret, *(ctype*)&m[f->offset]); \ - return ret; \ - } \ - upb_value upb_stdmsg_seqget ## type(void *i) { \ - upb_value val; \ - upb_value_set ## type(&val, *(ctype*)i); \ - return val; \ - } - -UPB_ACCESSORS(double, double) -UPB_ACCESSORS(float, float) -UPB_ACCESSORS(int32, int32_t) -UPB_ACCESSORS(int64, int64_t) -UPB_ACCESSORS(uint32, uint32_t) -UPB_ACCESSORS(uint64, uint64_t) -UPB_ACCESSORS(bool, bool) -UPB_ACCESSORS(ptr, void*) -#undef UPB_ACCESSORS - -static void _upb_stdmsg_setstr(void *_dst, upb_value src) { - upb_stdarray **dstp = _dst; - upb_stdarray *dst = *dstp; - if (!dst) { - dst = malloc(sizeof(*dst)); - dst->size = 0; - dst->ptr = NULL; - *dstp = dst; - } - dst->len = 0; - upb_strref *ref = upb_value_getstrref(src); - if (ref->len > dst->size) { - dst->size = ref->len; - dst->ptr = realloc(dst->ptr, dst->size); - } - dst->len = ref->len; - upb_bytesrc_read(ref->bytesrc, ref->stream_offset, ref->len, dst->ptr); -} - -upb_flow_t upb_stdmsg_setstr(void *_m, upb_value fval, upb_value val) { - char *m = _m; - upb_fielddef *f = upb_value_getfielddef(fval); - upb_stdmsg_sethas(_m, fval); - _upb_stdmsg_setstr(&m[f->offset], val); - return UPB_CONTINUE; -} - -upb_flow_t upb_stdmsg_setstr_r(void *a, upb_value fval, upb_value val) { - (void)fval; - _upb_stdmsg_setstr(upb_stdarray_append((upb_stdarray*)a, sizeof(void*)), val); - return UPB_CONTINUE; -} - -upb_value upb_stdmsg_getstr(void *m, upb_value fval) { - return upb_stdmsg_getptr(m, fval); -} - -upb_value upb_stdmsg_seqgetstr(void *i) { - return upb_stdmsg_seqgetptr(i); -} - -void *upb_stdmsg_new(upb_msgdef *md) { - void *m = malloc(md->size); - memset(m, 0, md->size); - upb_msg_clear(m, md); - return m; -} - -void upb_stdseq_free(void *s, upb_fielddef *f) { - upb_stdarray *a = s; - if (upb_issubmsg(f) || upb_isstring(f)) { - void **p = (void**)a->ptr; - for (uint32_t i = 0; i < a->size; i++) { - if (upb_issubmsg(f)) { - upb_stdmsg_free(p[i], upb_downcast_msgdef(f->def)); - } else { - upb_stdarray *str = p[i]; - free(str->ptr); - free(str); - } - } - } - free(a->ptr); - free(a); -} - -void upb_stdmsg_free(void *m, upb_msgdef *md) { - if (m == NULL) return; - upb_msg_iter i; - for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) { - upb_fielddef *f = upb_msg_iter_field(i); - if (!upb_isseq(f) && !upb_issubmsg(f) && !upb_isstring(f)) continue; - void *subp = upb_value_getptr(upb_stdmsg_getptr(m, f->fval)); - if (subp == NULL) continue; - if (upb_isseq(f)) { - upb_stdseq_free(subp, f); - } else if (upb_issubmsg(f)) { - upb_stdmsg_free(subp, upb_downcast_msgdef(f->def)); - } else { - upb_stdarray *str = subp; - free(str->ptr); - free(str); - } - } - free(m); -} - -upb_sflow_t upb_stdmsg_startseq(void *_m, upb_value fval) { - char *m = _m; - upb_fielddef *f = upb_value_getfielddef(fval); - upb_stdarray **arr = (void*)&m[f->offset]; - if (!upb_stdmsg_has(_m, fval)) { - if (!*arr) { - *arr = malloc(sizeof(**arr)); - (*arr)->size = 0; - (*arr)->ptr = NULL; - } - (*arr)->len = 0; - upb_stdmsg_sethas(m, fval); - } - return UPB_CONTINUE_WITH(*arr); -} - -void upb_stdmsg_recycle(void **m, upb_msgdef *md) { - if (*m) - upb_msg_clear(*m, md); - else - *m = upb_stdmsg_new(md); -} - -upb_sflow_t upb_stdmsg_startsubmsg(void *_m, upb_value fval) { - char *m = _m; - upb_fielddef *f = upb_value_getfielddef(fval); - void **subm = (void*)&m[f->offset]; - if (!upb_stdmsg_has(m, fval)) { - upb_stdmsg_recycle(subm, upb_downcast_msgdef(f->def)); - upb_stdmsg_sethas(m, fval); - } - return UPB_CONTINUE_WITH(*subm); -} - -upb_sflow_t upb_stdmsg_startsubmsg_r(void *a, upb_value fval) { - assert(a != NULL); - upb_fielddef *f = upb_value_getfielddef(fval); - void **subm = upb_stdarray_append((upb_stdarray*)a, sizeof(void*)); - upb_stdmsg_recycle(subm, upb_downcast_msgdef(f->def)); - return UPB_CONTINUE_WITH(*subm); -} - -void *upb_stdmsg_seqbegin(void *_a) { - upb_stdarray *a = _a; - return a->len > 0 ? a->ptr : NULL; -} - -#define NEXTFUNC(size) \ - void *upb_stdmsg_ ## size ## byte_seqnext(void *_a, void *iter) { \ - upb_stdarray *a = _a; \ - void *next = (char*)iter + size; \ - return (char*)next < (char*)a->ptr + (a->len * size) ? next : NULL; \ - } - -NEXTFUNC(8) -NEXTFUNC(4) -NEXTFUNC(1) - -#define STDMSG(type) { static upb_accessor_vtbl vtbl = {NULL, &upb_stdmsg_startsubmsg, \ - &upb_stdmsg_set ## type, &upb_stdmsg_has, &upb_stdmsg_get ## type, \ - NULL, NULL, NULL}; return &vtbl; } -#define STDMSG_R(type, size) { static upb_accessor_vtbl vtbl = { \ - &upb_stdmsg_startseq, &upb_stdmsg_startsubmsg_r, &upb_stdmsg_set ## type ## _r, \ - &upb_stdmsg_has, &upb_stdmsg_getptr, &upb_stdmsg_seqbegin, \ - &upb_stdmsg_ ## size ## byte_seqnext, &upb_stdmsg_seqget ## type}; \ - return &vtbl; } - -upb_accessor_vtbl *upb_stdmsg_accessor(upb_fielddef *f) { - if (upb_isseq(f)) { - switch (f->type) { - case UPB_TYPE(DOUBLE): STDMSG_R(double, 8) - case UPB_TYPE(FLOAT): STDMSG_R(float, 4) - case UPB_TYPE(UINT64): - case UPB_TYPE(FIXED64): STDMSG_R(uint64, 8) - case UPB_TYPE(INT64): - case UPB_TYPE(SFIXED64): - case UPB_TYPE(SINT64): STDMSG_R(int64, 8) - case UPB_TYPE(INT32): - case UPB_TYPE(SINT32): - case UPB_TYPE(ENUM): - case UPB_TYPE(SFIXED32): STDMSG_R(int32, 4) - case UPB_TYPE(UINT32): - case UPB_TYPE(FIXED32): STDMSG_R(uint32, 4) - case UPB_TYPE(BOOL): STDMSG_R(bool, 1) - case UPB_TYPE(STRING): - case UPB_TYPE(BYTES): - case UPB_TYPE(GROUP): - case UPB_TYPE(MESSAGE): STDMSG_R(str, 8) // TODO: 32-bit - } - } else { - switch (f->type) { - case UPB_TYPE(DOUBLE): STDMSG(double) - case UPB_TYPE(FLOAT): STDMSG(float) - case UPB_TYPE(UINT64): - case UPB_TYPE(FIXED64): STDMSG(uint64) - case UPB_TYPE(INT64): - case UPB_TYPE(SFIXED64): - case UPB_TYPE(SINT64): STDMSG(int64) - case UPB_TYPE(INT32): - case UPB_TYPE(SINT32): - case UPB_TYPE(ENUM): - case UPB_TYPE(SFIXED32): STDMSG(int32) - case UPB_TYPE(UINT32): - case UPB_TYPE(FIXED32): STDMSG(uint32) - case UPB_TYPE(BOOL): STDMSG(bool) - case UPB_TYPE(STRING): - case UPB_TYPE(BYTES): - case UPB_TYPE(GROUP): - case UPB_TYPE(MESSAGE): STDMSG(str) - } - } - return NULL; -} - -static void upb_accessors_onfreg(void *c, upb_fhandlers *fh, upb_fielddef *f) { - (void)c; - if (f->accessor) { - upb_fhandlers_setstartseq(fh, f->accessor->appendseq); - upb_fhandlers_setvalue(fh, f->accessor->set); - upb_fhandlers_setstartsubmsg(fh, f->accessor->appendsubmsg); - upb_fhandlers_setfval(fh, f->fval); - } -} - -upb_mhandlers *upb_accessors_reghandlers(upb_handlers *h, upb_msgdef *m) { - return upb_handlers_regmsgdef(h, m, NULL, &upb_accessors_onfreg, NULL); -} diff --git a/src/upb_msg.h b/src/upb_msg.h deleted file mode 100644 index af328e3..0000000 --- a/src/upb_msg.h +++ /dev/null @@ -1,270 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2010-2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * Routines for reading and writing message data to an in-memory structure, - * similar to a C struct. - * - * upb does not define one single message object that everyone must use. - * Rather it defines an abstract interface for reading and writing members - * of a message object, and all of the parsers and serializers use this - * abstract interface. This allows upb's parsers and serializers to be used - * regardless of what memory management scheme or synchronization model the - * application is using. - * - * A standard set of accessors is provided for doing simple reads and writes at - * a known offset into the message. These accessors should be used when - * possible, because they are specially optimized -- for example, the JIT can - * recognize them and emit specialized code instead of having to call the - * function at all. The application can substitute its own accessors when the - * standard accessors are not suitable. - */ - -#ifndef UPB_MSG_H -#define UPB_MSG_H - -#include -#include "upb_def.h" -#include "upb_handlers.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* upb_accessor ***************************************************************/ - -// A upb_accessor is a table of function pointers for doing reads and writes -// for one specific upb_fielddef. Each field has a separate accessor, which -// lives in the fielddef. - -typedef bool upb_has_reader(void *m, upb_value fval); -typedef upb_value upb_value_reader(void *m, upb_value fval); - -typedef void *upb_seqbegin_handler(void *s); -typedef void *upb_seqnext_handler(void *s, void *iter); -typedef upb_value upb_seqget_handler(void *iter); -INLINE bool upb_seq_done(void *iter) { return iter == NULL; } - -typedef struct _upb_accessor_vtbl { - // Writers. These take an fval as a parameter because the callbacks are used - // as upb_handlers, but the fval is always the fielddef for that field. - upb_startfield_handler *appendseq; // Repeated fields only. - upb_startfield_handler *appendsubmsg; // Submsg fields (repeated or no). - upb_value_handler *set; // Scalar fields (repeated or no). - - // Readers. - upb_has_reader *has; - upb_value_reader *get; - upb_seqbegin_handler *seqbegin; - upb_seqnext_handler *seqnext; - upb_seqget_handler *seqget; -} upb_accessor_vtbl; - -// Registers handlers for writing into a message of the given type. -upb_mhandlers *upb_accessors_reghandlers(upb_handlers *h, upb_msgdef *m); - -// Returns an stdmsg accessor for the given fielddef. -upb_accessor_vtbl *upb_stdmsg_accessor(upb_fielddef *f); - - -/* upb_msg/upb_seq ************************************************************/ - -// upb_msg and upb_seq allow for generic access to a message through its -// accessor vtable. Note that these do *not* allow you to create, destroy, or -// take references on the objects -- these operations are specifically outside -// the scope of what the accessors define. - -// Clears all hasbits. -// TODO: Add a separate function for setting primitive values back to their -// defaults (but not strings, submessages, or arrays). -void upb_msg_clear(void *msg, upb_msgdef *md); - -// Could add a method that recursively clears submessages, strings, and -// arrays if desired. This could be a win if you wanted to merge without -// needing hasbits, because during parsing you would never clear submessages -// or arrays. Also this could be desired to provide proto2 operations on -// generated messages. - -INLINE bool upb_msg_has(void *m, upb_fielddef *f) { - return f->accessor && f->accessor->has(m, f->fval); -} - -// May only be called for fields that are known to be set. -INLINE upb_value upb_msg_get(void *m, upb_fielddef *f) { - assert(upb_msg_has(m, f)); - return f->accessor->get(m, f->fval); -} - -INLINE void *upb_seq_begin(void *s, upb_fielddef *f) { - assert(f->accessor); - return f->accessor->seqbegin(s); -} -INLINE void *upb_seq_next(void *s, void *iter, upb_fielddef *f) { - assert(f->accessor); - assert(!upb_seq_done(iter)); - return f->accessor->seqnext(s, iter); -} -INLINE upb_value upb_seq_get(void *iter, upb_fielddef *f) { - assert(f->accessor); - assert(!upb_seq_done(iter)); - return f->accessor->seqget(iter); -} - - -/* upb_msgvisitor *************************************************************/ - -// A upb_msgvisitor reads data from an in-memory structure using its accessors, -// pushing the results to a given set of upb_handlers. -// TODO: not yet implemented. - -typedef struct { - upb_fhandlers *fh; - upb_fielddef *f; - uint16_t msgindex; // Only when upb_issubmsg(f). -} upb_msgvisitor_field; - -typedef struct { - upb_msgvisitor_field *fields; - int fields_len; -} upb_msgvisitor_msg; - -typedef struct { - uint16_t msgindex; - uint16_t fieldindex; - uint32_t arrayindex; // UINT32_MAX if not an array frame. -} upb_msgvisitor_frame; - -typedef struct { - upb_msgvisitor_msg *messages; - int messages_len; - upb_dispatcher dispatcher; -} upb_msgvisitor; - -// Initializes a msgvisitor that will push data from messages of the given -// msgdef to the given set of handlers. -void upb_msgvisitor_init(upb_msgvisitor *v, upb_msgdef *md, upb_handlers *h); -void upb_msgvisitor_uninit(upb_msgvisitor *v); - -void upb_msgvisitor_reset(upb_msgvisitor *v, void *m); -void upb_msgvisitor_visit(upb_msgvisitor *v, upb_status *status); - - -/* Standard writers. **********************************************************/ - -// Allocates a new stdmsg. -void *upb_stdmsg_new(upb_msgdef *md); - -// Recursively frees any strings or submessages that the message refers to. -void upb_stdmsg_free(void *m, upb_msgdef *md); - -// "hasbit" must be <= UPB_MAX_FIELDS. If it is <0, this field has no hasbit. -upb_value upb_stdmsg_packfval(int16_t hasbit, uint16_t value_offset); -upb_value upb_stdmsg_packfval_subm(int16_t hasbit, uint16_t value_offset, - uint16_t subm_size, uint8_t subm_setbytes); - -// Value writers for every in-memory type: write the data to a known offset -// from the closure "c" and set the hasbit (if any). -// TODO: can we get away with having only one for int64, uint64, double, etc? -// The main thing in the way atm is that the upb_value is strongly typed. -// in debug mode. -upb_flow_t upb_stdmsg_setint64(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setint32(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setuint64(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setuint32(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setdouble(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setfloat(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setbool(void *c, upb_value fval, upb_value val); - -// Value writers for repeated fields: the closure points to a standard array -// struct, appends the value to the end of the array, resizing with realloc() -// if necessary. -typedef struct { - char *ptr; - uint32_t len; // Number of elements present. - uint32_t size; // Number of elements allocated. -} upb_stdarray; - -upb_flow_t upb_stdmsg_setint64_r(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setint32_r(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setuint64_r(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setuint32_r(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setdouble_r(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setfloat_r(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setbool_r(void *c, upb_value fval, upb_value val); - -// Writers for C strings (NULL-terminated): we can find a char* at a known -// offset from the closure "c". Calls realloc() on the pointer to allocate -// the memory (TODO: investigate whether checking malloc_usable_size() would -// be cheaper than realloc()). Also sets the hasbit, if any. -// -// Since the string is NULL terminated and does not store an explicit length, -// these are not suitable for binary data that can contain NULLs. -upb_flow_t upb_stdmsg_setcstr(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setcstr_r(void *c, upb_value fval, upb_value val); - -// Writers for length-delimited strings: we explicitly store the length, so -// the data can contain NULLs. Stores the data using upb_stdarray -// which is located at a known offset from the closure "c" (note that it -// is included inline rather than pointed to). Also sets the hasbit, if any. -upb_flow_t upb_stdmsg_setstr(void *c, upb_value fval, upb_value val); -upb_flow_t upb_stdmsg_setstr_r(void *c, upb_value fval, upb_value val); - -// Writers for startseq and startmsg which allocate (or reuse, if possible) -// a sub data structure (upb_stdarray or a submessage, respectively), -// setting the hasbit. If the hasbit is already set, the existing data -// structure is used verbatim. If the hasbit is not already set, the pointer -// is checked for NULL. If it is NULL, a new substructure is allocated, -// cleared, and used. If it is not NULL, the existing substructure is -// cleared and reused. -// -// If there is no hasbit, we always behave as if the hasbit was not set, -// so any existing data for this array or submessage is cleared. In most -// cases this will be fine since each array or non-repeated submessage should -// occur at most once in the stream. But if the client is using "concatenation -// as merging", it will want to make sure hasbits are allocated so merges can -// happen appropriately. -// -// If there was a demand for the behavior that absence of a hasbit acts as if -// the bit was always set, we could provide that also. But Clear() would need -// to act recursively, which is less efficient since it requires an extra pass -// over the tree. -upb_sflow_t upb_stdmsg_startseq(void *c, upb_value fval); -upb_sflow_t upb_stdmsg_startsubmsg(void *c, upb_value fval); -upb_sflow_t upb_stdmsg_startsubmsg_r(void *c, upb_value fval); - - -/* Standard readers. **********************************************************/ - -bool upb_stdmsg_has(void *c, upb_value fval); -void *upb_stdmsg_seqbegin(void *c); - -upb_value upb_stdmsg_getint64(void *c, upb_value fval); -upb_value upb_stdmsg_getint32(void *c, upb_value fval); -upb_value upb_stdmsg_getuint64(void *c, upb_value fval); -upb_value upb_stdmsg_getuint32(void *c, upb_value fval); -upb_value upb_stdmsg_getdouble(void *c, upb_value fval); -upb_value upb_stdmsg_getfloat(void *c, upb_value fval); -upb_value upb_stdmsg_getbool(void *c, upb_value fval); -upb_value upb_stdmsg_getptr(void *c, upb_value fval); - -void *upb_stdmsg_8byte_seqnext(void *c, void *iter); -void *upb_stdmsg_4byte_seqnext(void *c, void *iter); -void *upb_stdmsg_1byte_seqnext(void *c, void *iter); - -upb_value upb_stdmsg_seqgetint64(void *c); -upb_value upb_stdmsg_seqgetint32(void *c); -upb_value upb_stdmsg_seqgetuint64(void *c); -upb_value upb_stdmsg_seqgetuint32(void *c); -upb_value upb_stdmsg_seqgetdouble(void *c); -upb_value upb_stdmsg_seqgetfloat(void *c); -upb_value upb_stdmsg_seqgetbool(void *c); -upb_value upb_stdmsg_seqgetptr(void *c); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/src/upb_stdio.c b/src/upb_stdio.c deleted file mode 100644 index 20a3c15..0000000 --- a/src/upb_stdio.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2010 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ - -#include "upb_stdio.h" - -#include -#include -#include - -// We can make this configurable if necessary. -#define BUF_SIZE 32768 - - -/* upb_bytesrc methods ********************************************************/ - -int upb_stdio_cmpbuf(const void *_key, const void *_elem) { - const uint64_t *ofs = _key; - const upb_stdio_buf *buf = _elem; - return (*ofs / BUF_SIZE) - (buf->ofs / BUF_SIZE); -} - -static upb_stdio_buf *upb_stdio_findbuf(upb_stdio *s, uint64_t ofs) { - // TODO: it is probably faster to linear search short lists, and to - // special-case the last one or two bufs. - return bsearch(&ofs, s->bufs, s->nbuf, sizeof(*s->bufs), &upb_stdio_cmpbuf); -} - -//static upb_strlen_t upb_stdio_read(void *src, uint32_t ofs, upb_buf *b, -// upb_status *status) { -// upb_stdio *stdio = (upb_stdio*)src; -// size_t read = fread(buf, 1, BLOCK_SIZE, stdio->file); -// if(read < (size_t)BLOCK_SIZE) { -// // Error or EOF. -// if(feof(stdio->file)) { -// upb_seterr(status, UPB_EOF, ""); -// } else if(ferror(stdio->file)) { -// upb_status_fromerrno(s); -// return 0; -// } -// } -// b->len = read; -// stdio->next_ofs += read; -// return stdio->next_ofs; -//} - -size_t upb_stdio_fetch(void *src, uint64_t ofs, upb_status *s) { - (void)src; - (void)ofs; - (void)s; - - return 0; -} - -void upb_stdio_read(void *src, uint64_t src_ofs, size_t len, char *dst) { - upb_stdio_buf *buf = upb_stdio_findbuf(src, src_ofs); - src_ofs -= buf->ofs; - memcpy(dst, &buf->data[src_ofs], BUF_SIZE - src_ofs); - len -= (BUF_SIZE - src_ofs); - dst += (BUF_SIZE - src_ofs); - while (len > 0) { - ++buf; - size_t bytes = UPB_MIN(len, BUF_SIZE); - memcpy(dst, buf->data, bytes); - len -= bytes; - dst += bytes; - } -} - -const char *upb_stdio_getptr(void *src, uint64_t ofs, size_t *len) { - upb_stdio_buf *buf = upb_stdio_findbuf(src, ofs); - ofs -= buf->ofs; - *len = BUF_SIZE - ofs; - return &buf->data[ofs]; -} - -void upb_stdio_refregion(void *src, uint64_t ofs, size_t len) { - upb_stdio_buf *buf = upb_stdio_findbuf(src, ofs); - len -= (BUF_SIZE - ofs); - ++buf->refcount; - while (len > 0) { - ++buf; - ++buf->refcount; - } -} - -void upb_stdio_unrefregion(void *src, uint64_t ofs, size_t len) { - (void)src; - (void)ofs; - (void)len; -} - - -/* upb_bytesink methods *******************************************************/ - -#if 0 -upb_strlen_t upb_stdio_putstr(upb_bytesink *sink, upb_string *str, upb_status *status) { - upb_stdio *stdio = (upb_stdio*)((char*)sink - offsetof(upb_stdio, sink)); - upb_strlen_t len = upb_string_len(str); - upb_strlen_t written = fwrite(upb_string_getrobuf(str), 1, len, stdio->file); - if(written < len) { - upb_status_setf(status, UPB_ERROR, "Error writing to stdio stream."); - return -1; - } - return written; -} -#endif - -uint32_t upb_stdio_vprintf(upb_bytesink *sink, upb_status *status, - const char *fmt, va_list args) { - upb_stdio *stdio = (upb_stdio*)((char*)sink - offsetof(upb_stdio, sink)); - int written = vfprintf(stdio->file, fmt, args); - if (written < 0) { - upb_status_setf(status, UPB_ERROR, "Error writing to stdio stream."); - return -1; - } - return written; -} - -void upb_stdio_init(upb_stdio *stdio) { - static upb_bytesrc_vtbl bytesrc_vtbl = { - upb_stdio_fetch, - upb_stdio_read, - upb_stdio_getptr, - upb_stdio_refregion, - upb_stdio_unrefregion, - NULL, - NULL - }; - upb_bytesrc_init(&stdio->src, &bytesrc_vtbl); - - //static upb_bytesink_vtbl bytesink_vtbl = { - // upb_stdio_putstr, - // upb_stdio_vprintf - //}; - //upb_bytesink_init(&stdio->bytesink, &bytesink_vtbl); -} - -void upb_stdio_reset(upb_stdio* stdio, FILE *file) { - stdio->file = file; - stdio->should_close = false; -} - -void upb_stdio_open(upb_stdio *stdio, const char *filename, const char *mode, - upb_status *s) { - FILE *f = fopen(filename, mode); - if (!f) { - upb_status_fromerrno(s); - return; - } - setvbuf(stdio->file, NULL, _IONBF, 0); // Disable buffering; we do our own. - upb_stdio_reset(stdio, f); - stdio->should_close = true; -} - -void upb_stdio_uninit(upb_stdio *stdio) { - // Can't report status; caller should flush() to ensure data is written. - if (stdio->should_close) fclose(stdio->file); - stdio->file = NULL; -} - -upb_bytesrc* upb_stdio_bytesrc(upb_stdio *stdio) { return &stdio->src; } -upb_bytesink* upb_stdio_bytesink(upb_stdio *stdio) { return &stdio->sink; } diff --git a/src/upb_stdio.h b/src/upb_stdio.h deleted file mode 100644 index 858830c..0000000 --- a/src/upb_stdio.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2010 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * This file provides upb_bytesrc and upb_bytesink implementations for - * ANSI C stdio, which is less efficient than posixfd, but more portable. - * - * Specifically, stdio functions acquire locks on every operation (unless you - * use the f{read,write,...}_unlocked variants, which are not standard) and - * performs redundant buffering (unless you disable it with setvbuf(), but we - * can only do this on newly-opened filehandles). - */ - -#include -#include "upb_bytestream.h" - -#ifndef UPB_STDIO_H_ -#define UPB_STDIO_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint64_t ofs; - uint32_t refcount; - char data[]; -} upb_stdio_buf; - -// We use a single object for both bytesrc and bytesink for simplicity. -// The object is still not thread-safe, and may only be used by one reader -// and one writer at a time. -typedef struct { - upb_bytesrc src; - upb_bytesink sink; - FILE *file; - bool should_close; - upb_stdio_buf **bufs; - uint32_t nbuf, szbuf; -} upb_stdio; - -void upb_stdio_init(upb_stdio *stdio); -// Caller should call upb_stdio_flush prior to calling this to ensure that -// all data is flushed, otherwise data can be silently dropped if an error -// occurs flushing the remaining buffers. -void upb_stdio_uninit(upb_stdio *stdio); - -// Resets the object to read/write to the given "file." The caller is -// responsible for closing the file, which must outlive this object. -void upb_stdio_reset(upb_stdio *stdio, FILE *file); - -// As an alternative to upb_stdio_reset(), initializes the object by opening a -// file, and will handle closing it. This may result in more efficient I/O -// than the previous since we can call setvbuf() to disable buffering. -void upb_stdio_open(upb_stdio *stdio, const char *filename, const char *mode, - upb_status *s); - -// Must be called to cleanup after the object, including closing the file if -// it was opened with upb_stdio_open() (which can fail, hence the status). -// - -upb_bytesrc *upb_stdio_bytesrc(upb_stdio *stdio); -upb_bytesink *upb_stdio_bytesink(upb_stdio *stdio); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/src/upb_strstream.c b/src/upb_strstream.c deleted file mode 100644 index 9e17d75..0000000 --- a/src/upb_strstream.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2010 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ - -#include "upb_strstream.h" - -#include - - -/* upb_stringsrc **************************************************************/ - -size_t upb_stringsrc_fetch(void *_src, uint64_t ofs, upb_status *s) { - upb_stringsrc *src = _src; - size_t bytes = src->len - ofs; - if (bytes == 0) s->code = UPB_EOF; - return bytes; -} - -void upb_stringsrc_read(void *_src, uint64_t src_ofs, size_t len, char *dst) { - upb_stringsrc *src = _src; - memcpy(dst, src->str + src_ofs, len); -} - -const char *upb_stringsrc_getptr(void *_src, uint64_t ofs, size_t *len) { - upb_stringsrc *src = _src; - *len = src->len - ofs; - return src->str + ofs; -} - -void upb_stringsrc_init(upb_stringsrc *s) { - static upb_bytesrc_vtbl vtbl = { - &upb_stringsrc_fetch, - &upb_stringsrc_read, - &upb_stringsrc_getptr, - NULL, NULL, NULL, NULL - }; - upb_bytesrc_init(&s->bytesrc, &vtbl); - s->str = NULL; -} - -void upb_stringsrc_reset(upb_stringsrc *s, const char *str, size_t len) { - s->str = str; - s->len = len; -} - -void upb_stringsrc_uninit(upb_stringsrc *s) { (void)s; } - -upb_bytesrc *upb_stringsrc_bytesrc(upb_stringsrc *s) { - return &s->bytesrc; -} - - -/* upb_stringsink *************************************************************/ - -void upb_stringsink_uninit(upb_stringsink *s) { - free(s->str); -} - -// Resets the stringsink to a state where it will append to the given string. -// The string must be newly created or recycled. The stringsink will take a -// reference on the string, so the caller need not ensure that it outlives the -// stringsink. A stringsink can be reset multiple times. -void upb_stringsink_reset(upb_stringsink *s, char *str, size_t size) { - free(s->str); - s->str = str; - s->len = 0; - s->size = size; -} - -upb_bytesink *upb_stringsink_bytesink(upb_stringsink *s) { - return &s->bytesink; -} - -static int32_t upb_stringsink_vprintf(void *_s, upb_status *status, - const char *fmt, va_list args) { - (void)status; // TODO: report realloc() errors. - upb_stringsink *s = _s; - int ret = upb_vrprintf(&s->str, &s->size, s->len, fmt, args); - if (ret >= 0) s->len += ret; - return ret; -} - -bool upb_stringsink_write(void *_s, const char *buf, size_t len, - upb_status *status) { - (void)status; // TODO: report realloc() errors. - upb_stringsink *s = _s; - if (s->len + len > s->size) { - while(s->len + len > s->size) s->size *= 2; - s->str = realloc(s->str, s->size); - } - memcpy(s->str + s->len, buf, len); - s->len += len; - return true; -} - -void upb_stringsink_init(upb_stringsink *s) { - static upb_bytesink_vtbl vtbl = { - upb_stringsink_write, - upb_stringsink_vprintf - }; - upb_bytesink_init(&s->bytesink, &vtbl); - s->str = NULL; -} diff --git a/src/upb_strstream.h b/src/upb_strstream.h deleted file mode 100644 index e57406e..0000000 --- a/src/upb_strstream.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009-2010 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * This file contains upb_bytesrc and upb_bytesink implementations for - * upb_string. - */ - -#ifndef UPB_STRSTREAM_H -#define UPB_STRSTREAM_H - -#include "upb_bytestream.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* upb_stringsrc **************************************************************/ - -struct _upb_stringsrc { - upb_bytesrc bytesrc; - const char *str; - size_t len; -}; -typedef struct _upb_stringsrc upb_stringsrc; - -// Create/free a stringsrc. -void upb_stringsrc_init(upb_stringsrc *s); -void upb_stringsrc_uninit(upb_stringsrc *s); - -// Resets the stringsrc to a state where it will vend the given string. The -// stringsrc will take a reference on the string, so the caller need not ensure -// that it outlives the stringsrc. A stringsrc can be reset multiple times. -void upb_stringsrc_reset(upb_stringsrc *s, const char *str, size_t len); - -// Returns the upb_bytesrc* for this stringsrc. -upb_bytesrc *upb_stringsrc_bytesrc(upb_stringsrc *s); - - -/* upb_stringsink *************************************************************/ - -struct _upb_stringsink { - upb_bytesink bytesink; - char *str; - size_t len, size; -}; -typedef struct _upb_stringsink upb_stringsink; - -// Create/free a stringsrc. -void upb_stringsink_init(upb_stringsink *s); -void upb_stringsink_uninit(upb_stringsink *s); - -// Resets the sink's string to "str", which the sink takes ownership of. -// "str" may be NULL, which will make the sink allocate a new string. -void upb_stringsink_reset(upb_stringsink *s, char *str, size_t size); - -// Releases ownership of the returned string (which is "len" bytes long) and -// resets the internal string to be empty again (as if reset were called with -// NULL). -const char *upb_stringsink_release(upb_stringsink *s, size_t *len); - -// Returns the upb_bytesink* for this stringsrc. Invalidated by reset above. -upb_bytesink *upb_stringsink_bytesink(); - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/src/upb_table.c b/src/upb_table.c deleted file mode 100644 index fc9e9de..0000000 --- a/src/upb_table.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * There are a few printf's strewn throughout this file, uncommenting them - * can be useful for debugging. - */ - -#include "upb_table.h" - -#include -#include -#include - -static const double MAX_LOAD = 0.85; - -// The minimum percentage of an array part that we will allow. This is a -// speed/memory-usage tradeoff (though it's not straightforward because of -// cache effects). The lower this is, the more memory we'll use. -static const double MIN_DENSITY = 0.1; - -static uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed); - -/* Base table (shared code) ***************************************************/ - -static uint32_t upb_table_size(upb_table *t) { return 1 << t->size_lg2; } -static size_t upb_table_entrysize(upb_table *t) { return t->entry_size; } -static size_t upb_table_valuesize(upb_table *t) { return t->value_size; } - -void upb_table_init(upb_table *t, uint32_t size, uint16_t entry_size) { - t->count = 0; - t->entry_size = entry_size; - t->size_lg2 = 1; - while(upb_table_size(t) < size) t->size_lg2++; - size_t bytes = upb_table_size(t) * t->entry_size; - t->mask = upb_table_size(t) - 1; - t->entries = malloc(bytes); -} - -void upb_table_free(upb_table *t) { free(t->entries); } - -/* upb_inttable ***************************************************************/ - -static upb_inttable_entry *intent(upb_inttable *t, int32_t i) { - //printf("looking up int entry %d, size of entry: %d\n", i, t->t.entry_size); - return UPB_INDEX(t->t.entries, i, t->t.entry_size); -} - -static uint32_t upb_inttable_hashtablesize(upb_inttable *t) { - return upb_table_size(&t->t); -} - -void upb_inttable_sizedinit(upb_inttable *t, uint32_t arrsize, uint32_t hashsize, - uint16_t value_size) { - size_t entsize = _upb_inttable_entrysize(value_size); - upb_table_init(&t->t, hashsize, entsize); - for (uint32_t i = 0; i < upb_table_size(&t->t); i++) { - upb_inttable_entry *e = intent(t, i); - e->hdr.key = 0; - e->hdr.next = UPB_END_OF_CHAIN; - e->val.has_entry = 0; - } - t->t.value_size = value_size; - // Always make the array part at least 1 long, so that we know key 0 - // won't be in the hash part (which lets us speed up that code path). - t->array_size = UPB_MAX(1, arrsize); - t->array = malloc(upb_table_valuesize(&t->t) * t->array_size); - t->array_count = 0; - for (uint32_t i = 0; i < t->array_size; i++) { - upb_inttable_value *val = UPB_INDEX(t->array, i, upb_table_valuesize(&t->t)); - val->has_entry = false; - } -} - -void upb_inttable_init(upb_inttable *t, uint32_t hashsize, uint16_t value_size) { - upb_inttable_sizedinit(t, 0, hashsize, value_size); -} - -void upb_inttable_free(upb_inttable *t) { - upb_table_free(&t->t); - free(t->array); -} - -static uint32_t empty_intbucket(upb_inttable *table) -{ - // TODO: does it matter that this is biased towards the front of the table? - for(uint32_t i = 0; i < upb_inttable_hashtablesize(table); i++) { - upb_inttable_entry *e = intent(table, i); - if(!e->val.has_entry) return i; - } - assert(false); - return 0; -} - -// The insert routines have a lot more code duplication between int/string -// variants than I would like, but there's just a bit too much that varies to -// parameterize them. -static void intinsert(upb_inttable *t, uint32_t key, const void *val) { - assert(upb_inttable_lookup(t, key) == NULL); - upb_inttable_value *table_val; - if (_upb_inttable_isarrkey(t, key)) { - table_val = UPB_INDEX(t->array, key, upb_table_valuesize(&t->t)); - t->array_count++; - //printf("Inserting key %d to Array part! %p\n", key, table_val); - } else { - t->t.count++; - uint32_t bucket = _upb_inttable_bucket(t, key); - upb_inttable_entry *table_e = intent(t, bucket); - //printf("Hash part! Inserting into bucket %d?\n", bucket); - if(table_e->val.has_entry) { /* Collision. */ - //printf("Collision!\n"); - if(bucket == _upb_inttable_bucket(t, table_e->hdr.key)) { - /* Existing element is in its main posisiton. Find an empty slot to - * place our new element and append it to this key's chain. */ - uint32_t empty_bucket = empty_intbucket(t); - while (table_e->hdr.next != UPB_END_OF_CHAIN) - table_e = intent(t, table_e->hdr.next); - table_e->hdr.next = empty_bucket; - table_e = intent(t, empty_bucket); - } else { - /* Existing element is not in its main position. Move it to an empty - * slot and put our element in its main position. */ - uint32_t empty_bucket = empty_intbucket(t); - uint32_t evictee_bucket = _upb_inttable_bucket(t, table_e->hdr.key); - memcpy(intent(t, empty_bucket), table_e, t->t.entry_size); /* copies next */ - upb_inttable_entry *evictee_e = intent(t, evictee_bucket); - while(1) { - assert(evictee_e->val.has_entry); - assert(evictee_e->hdr.next != UPB_END_OF_CHAIN); - if(evictee_e->hdr.next == bucket) { - evictee_e->hdr.next = empty_bucket; - break; - } - evictee_e = intent(t, evictee_e->hdr.next); - } - /* table_e remains set to our mainpos. */ - } - } - //printf("Inserting! to:%p, copying to: %p\n", table_e, &table_e->val); - table_val = &table_e->val; - table_e->hdr.key = key; - table_e->hdr.next = UPB_END_OF_CHAIN; - } - memcpy(table_val, val, upb_table_valuesize(&t->t)); - table_val->has_entry = true; - assert(upb_inttable_lookup(t, key) == table_val); -} - -// Insert all elements from src into dest. Caller ensures that a resize will -// not be necessary. -static void upb_inttable_insertall(upb_inttable *dst, upb_inttable *src) { - for(upb_inttable_iter i = upb_inttable_begin(src); !upb_inttable_done(i); - i = upb_inttable_next(src, i)) { - //printf("load check: %d %d\n", upb_table_count(&dst->t), upb_inttable_hashtablesize(dst)); - assert((double)(upb_table_count(&dst->t)) / - upb_inttable_hashtablesize(dst) <= MAX_LOAD); - intinsert(dst, upb_inttable_iter_key(i), upb_inttable_iter_value(i)); - } -} - -void upb_inttable_insert(upb_inttable *t, uint32_t key, const void *val) { - if((double)(t->t.count + 1) / upb_inttable_hashtablesize(t) > MAX_LOAD) { - //printf("RESIZE!\n"); - // Need to resize. Allocate new table with double the size of however many - // elements we have now, add old elements to it. We create the new hash - // table without an array part, even if the old table had an array part. - // If/when the user calls upb_inttable_compact() again, we'll create an - // array part then. - upb_inttable new_table; - //printf("Old table count=%d, size=%d\n", upb_inttable_count(t), upb_inttable_hashtablesize(t)); - upb_inttable_init(&new_table, upb_inttable_count(t)*2, upb_table_valuesize(&t->t)); - upb_inttable_insertall(&new_table, t); - upb_inttable_free(t); - *t = new_table; - } - intinsert(t, key, val); -} - -void upb_inttable_compact(upb_inttable *t) { - // Find the largest array part we can that satisfies the MIN_DENSITY - // definition. For now we just count down powers of two. - uint32_t largest_key = 0; - for(upb_inttable_iter i = upb_inttable_begin(t); !upb_inttable_done(i); - i = upb_inttable_next(t, i)) { - largest_key = UPB_MAX(largest_key, upb_inttable_iter_key(i)); - } - int lg2_array = 0; - while ((1UL << lg2_array) < largest_key) ++lg2_array; - ++lg2_array; // Undo the first iteration. - size_t array_size; - int array_count = 0; - while (lg2_array > 0) { - array_size = (1 << --lg2_array); - //printf("Considering size %d (btw, our table has %d things total)\n", array_size, upb_inttable_count(t)); - if ((double)upb_inttable_count(t) / array_size < MIN_DENSITY) { - // Even if 100% of the keys were in the array pary, an array of this - // size would not be dense enough. - continue; - } - array_count = 0; - for(upb_inttable_iter i = upb_inttable_begin(t); !upb_inttable_done(i); - i = upb_inttable_next(t, i)) { - if (upb_inttable_iter_key(i) < array_size) - array_count++; - } - //printf("There would be %d things in that array\n", array_count); - if ((double)array_count / array_size >= MIN_DENSITY) break; - } - upb_inttable new_table; - int hash_size = (upb_inttable_count(t) - array_count + 1) / MAX_LOAD; - //printf("array_count: %d, array_size: %d, hash_size: %d, table size: %d\n", array_count, array_size, hash_size, upb_inttable_count(t)); - upb_inttable_sizedinit(&new_table, array_size, hash_size, - upb_table_valuesize(&t->t)); - //printf("For %d things, using array size=%d, hash_size = %d\n", upb_inttable_count(t), array_size, hash_size); - upb_inttable_insertall(&new_table, t); - upb_inttable_free(t); - *t = new_table; -} - -upb_inttable_iter upb_inttable_begin(upb_inttable *t) { - upb_inttable_iter iter = {-1, NULL, true}; // -1 will overflow to 0 on the first iteration. - return upb_inttable_next(t, iter); -} - -upb_inttable_iter upb_inttable_next(upb_inttable *t, upb_inttable_iter iter) { - const size_t hdrsize = sizeof(upb_inttable_header); - const size_t entsize = upb_table_entrysize(&t->t); - if (iter.array_part) { - while (++iter.key < t->array_size) { - //printf("considering value %d\n", iter.key); - iter.value = UPB_INDEX(t->array, iter.key, t->t.value_size); - if (iter.value->has_entry) return iter; - } - //printf("Done with array part!\n"); - iter.array_part = false; - // Point to the value of the table[-1] entry. - iter.value = UPB_INDEX(intent(t, -1), 1, hdrsize); - } - void *end = intent(t, upb_inttable_hashtablesize(t)); - // Point to the entry for the value that was previously in iter. - upb_inttable_entry *e = UPB_INDEX(iter.value, -1, hdrsize); - do { - e = UPB_INDEX(e, 1, entsize); - //printf("considering value %p (val: %p)\n", e, &e->val); - if(e == end) { - //printf("No values.\n"); - iter.value = NULL; - return iter; - } - } while(!e->val.has_entry); - //printf("USING VALUE! %p\n", e); - iter.key = e->hdr.key; - iter.value = &e->val; - return iter; -} - - -/* upb_strtable ***************************************************************/ - -static upb_strtable_entry *strent(upb_strtable *t, int32_t i) { - //fprintf(stderr, "i: %d, table_size: %d\n", i, upb_table_size(&t->t)); - assert(i <= (int32_t)upb_table_size(&t->t)); - return UPB_INDEX(t->t.entries, i, t->t.entry_size); -} - -static uint32_t upb_strtable_size(upb_strtable *t) { - return upb_table_size(&t->t); -} - -void upb_strtable_init(upb_strtable *t, uint32_t size, uint16_t valuesize) { - t->t.value_size = valuesize; - size_t entsize = upb_align_up(sizeof(upb_strtable_header) + valuesize, 8); - upb_table_init(&t->t, size, entsize); - for (uint32_t i = 0; i < upb_table_size(&t->t); i++) { - upb_strtable_entry *e = strent(t, i); - e->hdr.key = NULL; - e->hdr.next = UPB_END_OF_CHAIN; - } -} - -void upb_strtable_free(upb_strtable *t) { - // Free keys from the strtable. - upb_strtable_iter i; - for(upb_strtable_begin(&i, t); !upb_strtable_done(&i); upb_strtable_next(&i)) - free((char*)upb_strtable_iter_key(&i)); - upb_table_free(&t->t); -} - -static uint32_t strtable_bucket(upb_strtable *t, const char *key) { - uint32_t hash = MurmurHash2(key, strlen(key), 0); - return (hash & t->t.mask); -} - -void *upb_strtable_lookup(upb_strtable *t, const char *key) { - uint32_t bucket = strtable_bucket(t, key); - upb_strtable_entry *e; - do { - e = strent(t, bucket); - if(e->hdr.key && strcmp(e->hdr.key, key) == 0) return &e->val; - } while((bucket = e->hdr.next) != UPB_END_OF_CHAIN); - return NULL; -} - -void *upb_strtable_lookupl(upb_strtable *t, const char *key, size_t len) { - // TODO: improve. - char key2[len+1]; - memcpy(key2, key, len); - key2[len] = '\0'; - return upb_strtable_lookup(t, key2); -} - -static uint32_t empty_strbucket(upb_strtable *table) { - // TODO: does it matter that this is biased towards the front of the table? - for(uint32_t i = 0; i < upb_strtable_size(table); i++) { - upb_strtable_entry *e = strent(table, i); - if(!e->hdr.key) return i; - } - assert(false); - return 0; -} - -static void strinsert(upb_strtable *t, const char *key, const void *val) { - assert(upb_strtable_lookup(t, key) == NULL); - t->t.count++; - uint32_t bucket = strtable_bucket(t, key); - upb_strtable_entry *table_e = strent(t, bucket); - if(table_e->hdr.key) { /* Collision. */ - if(bucket == strtable_bucket(t, table_e->hdr.key)) { - /* Existing element is in its main posisiton. Find an empty slot to - * place our new element and append it to this key's chain. */ - uint32_t empty_bucket = empty_strbucket(t); - while (table_e->hdr.next != UPB_END_OF_CHAIN) - table_e = strent(t, table_e->hdr.next); - table_e->hdr.next = empty_bucket; - table_e = strent(t, empty_bucket); - } else { - /* Existing element is not in its main position. Move it to an empty - * slot and put our element in its main position. */ - uint32_t empty_bucket = empty_strbucket(t); - uint32_t evictee_bucket = strtable_bucket(t, table_e->hdr.key); - memcpy(strent(t, empty_bucket), table_e, t->t.entry_size); /* copies next */ - upb_strtable_entry *evictee_e = strent(t, evictee_bucket); - while(1) { - assert(evictee_e->hdr.key); - assert(evictee_e->hdr.next != UPB_END_OF_CHAIN); - if(evictee_e->hdr.next == bucket) { - evictee_e->hdr.next = empty_bucket; - break; - } - evictee_e = strent(t, evictee_e->hdr.next); - } - /* table_e remains set to our mainpos. */ - } - } - //fprintf(stderr, "val: %p\n", val); - //fprintf(stderr, "val size: %d\n", t->t.value_size); - memcpy(&table_e->val, val, t->t.value_size); - table_e->hdr.key = strdup(key); - table_e->hdr.next = UPB_END_OF_CHAIN; - //fprintf(stderr, "Looking up, string=%s...\n", key); - assert(upb_strtable_lookup(t, key) == &table_e->val); - //printf("Yay!\n"); -} - -void upb_strtable_insert(upb_strtable *t, const char *key, const void *val) { - if((double)(t->t.count + 1) / upb_strtable_size(t) > MAX_LOAD) { - // Need to resize. New table of double the size, add old elements to it. - //printf("RESIZE!!\n"); - upb_strtable new_table; - upb_strtable_init(&new_table, upb_strtable_size(t)*2, t->t.value_size); - upb_strtable_iter i; - upb_strtable_begin(&i, t); - for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { - strinsert(&new_table, - upb_strtable_iter_key(&i), - upb_strtable_iter_value(&i)); - } - upb_strtable_free(t); - *t = new_table; - } - strinsert(t, key, val); -} - -void upb_strtable_begin(upb_strtable_iter *i, upb_strtable *t) { - i->e = strent(t, -1); - i->t = t; - upb_strtable_next(i); -} - -void upb_strtable_next(upb_strtable_iter *i) { - upb_strtable_entry *end = strent(i->t, upb_strtable_size(i->t)); - upb_strtable_entry *cur = i->e; - do { - cur = (void*)((char*)cur + i->t->t.entry_size); - if(cur == end) { i->e = NULL; return; } - } while(cur->hdr.key == NULL); - i->e = cur; -} - -#ifdef UPB_UNALIGNED_READS_OK -//----------------------------------------------------------------------------- -// MurmurHash2, by Austin Appleby (released as public domain). -// Reformatted and C99-ified by Joshua Haberman. -// Note - This code makes a few assumptions about how your machine behaves - -// 1. We can read a 4-byte value from any address without crashing -// 2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t -// And it has a few limitations - -// 1. It will not work incrementally. -// 2. It will not produce the same results on little-endian and big-endian -// machines. -static uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed) -{ - // 'm' and 'r' are mixing constants generated offline. - // They're not really 'magic', they just happen to work well. - const uint32_t m = 0x5bd1e995; - const int32_t r = 24; - - // Initialize the hash to a 'random' value - uint32_t h = seed ^ len; - - // Mix 4 bytes at a time into the hash - const uint8_t * data = (const uint8_t *)key; - while(len >= 4) { - uint32_t k = *(uint32_t *)data; - - k *= m; - k ^= k >> r; - k *= m; - - h *= m; - h ^= k; - - data += 4; - len -= 4; - } - - // Handle the last few bytes of the input array - switch(len) { - case 3: h ^= data[2] << 16; - case 2: h ^= data[1] << 8; - case 1: h ^= data[0]; h *= m; - }; - - // Do a few final mixes of the hash to ensure the last few - // bytes are well-incorporated. - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; -} - -#else // !UPB_UNALIGNED_READS_OK - -//----------------------------------------------------------------------------- -// MurmurHashAligned2, by Austin Appleby -// Same algorithm as MurmurHash2, but only does aligned reads - should be safer -// on certain platforms. -// Performance will be lower than MurmurHash2 - -#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; } - -static uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) -{ - const uint32_t m = 0x5bd1e995; - const int32_t r = 24; - const uint8_t * data = (const uint8_t *)key; - uint32_t h = seed ^ len; - uint8_t align = (uintptr_t)data & 3; - - if(align && (len >= 4)) { - // Pre-load the temp registers - uint32_t t = 0, d = 0; - - switch(align) { - case 1: t |= data[2] << 16; - case 2: t |= data[1] << 8; - case 3: t |= data[0]; - } - - t <<= (8 * align); - - data += 4-align; - len -= 4-align; - - int32_t sl = 8 * (4-align); - int32_t sr = 8 * align; - - // Mix - - while(len >= 4) { - d = *(uint32_t *)data; - t = (t >> sr) | (d << sl); - - uint32_t k = t; - - MIX(h,k,m); - - t = d; - - data += 4; - len -= 4; - } - - // Handle leftover data in temp registers - - d = 0; - - if(len >= align) { - switch(align) { - case 3: d |= data[2] << 16; - case 2: d |= data[1] << 8; - case 1: d |= data[0]; - } - - uint32_t k = (t >> sr) | (d << sl); - MIX(h,k,m); - - data += align; - len -= align; - - //---------- - // Handle tail bytes - - switch(len) { - case 3: h ^= data[2] << 16; - case 2: h ^= data[1] << 8; - case 1: h ^= data[0]; h *= m; - }; - } else { - switch(len) { - case 3: d |= data[2] << 16; - case 2: d |= data[1] << 8; - case 1: d |= data[0]; - case 0: h ^= (t >> sr) | (d << sl); h *= m; - } - } - - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; - } else { - while(len >= 4) { - uint32_t k = *(uint32_t *)data; - - MIX(h,k,m); - - data += 4; - len -= 4; - } - - //---------- - // Handle tail bytes - - switch(len) { - case 3: h ^= data[2] << 16; - case 2: h ^= data[1] << 8; - case 1: h ^= data[0]; h *= m; - }; - - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; - } -} -#undef MIX - -#endif // UPB_UNALIGNED_READS_OK diff --git a/src/upb_table.h b/src/upb_table.h deleted file mode 100644 index 376465b..0000000 --- a/src/upb_table.h +++ /dev/null @@ -1,225 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * This file defines very fast int->struct (inttable) and string->struct - * (strtable) hash tables. The struct can be of any size, and it is stored - * in the table itself, for cache-friendly performance. - * - * The table uses internal chaining with Brent's variation (inspired by the - * Lua implementation of hash tables). The hash function for strings is - * Austin Appleby's "MurmurHash." - */ - -#ifndef UPB_TABLE_H_ -#define UPB_TABLE_H_ - -#include -#include "upb.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define UPB_END_OF_CHAIN (uint32_t)-1 - -typedef struct { - bool has_entry:1; - // The rest of the bits are the user's. -} upb_inttable_value; - -typedef struct { - uint32_t key; - uint32_t next; // Internal chaining. -} upb_inttable_header; - -typedef struct { - upb_inttable_header hdr; - upb_inttable_value val; -} upb_inttable_entry; - -// TODO: consider storing the hash in the entry. This would avoid the need to -// rehash on table resizes, but more importantly could possibly improve lookup -// performance by letting us compare hashes before comparing lengths or the -// strings themselves. -typedef struct { - char *key; // We own, nullz. TODO: store explicit len? - uint32_t next; // Internal chaining. -} upb_strtable_header; - -typedef struct { - upb_strtable_header hdr; - uint32_t val; // Val is at least 32 bits. -} upb_strtable_entry; - -typedef struct { - void *entries; // Hash table. - uint32_t count; // Number of entries in the hash part. - uint32_t mask; // Mask to turn hash value -> bucket. - uint16_t entry_size; // Size of each entry. - uint16_t value_size; // Size of each value. - uint8_t size_lg2; // Size of the hash table part is 2^size_lg2 entries. -} upb_table; - -typedef struct { - upb_table t; -} upb_strtable; - -typedef struct { - upb_table t; - void *array; // Array part of the table. - uint32_t array_size; // Array part size. - uint32_t array_count; // Array part number of elements. -} upb_inttable; - -// Initialize and free a table, respectively. Specify the initial size -// with 'size' (the size will be increased as necessary). Value size -// specifies how many bytes each value in the table is. -// -// WARNING! The lowest bit of every entry is reserved by the hash table. -// It will always be overwritten when you insert, and must not be modified -// when looked up! -void upb_inttable_init(upb_inttable *table, uint32_t size, uint16_t value_size); -void upb_inttable_free(upb_inttable *table); -void upb_strtable_init(upb_strtable *table, uint32_t size, uint16_t value_size); -void upb_strtable_free(upb_strtable *table); - -// Number of values in the hash table. -INLINE uint32_t upb_table_count(upb_table *t) { return t->count; } -INLINE uint32_t upb_inttable_count(upb_inttable *t) { - return t->array_count + upb_table_count(&t->t); -} -INLINE uint32_t upb_strtable_count(upb_strtable *t) { - return upb_table_count(&t->t); -} - -// Inserts the given key into the hashtable with the given value. The key must -// not already exist in the hash table. The data will be copied from val into -// the hashtable (the amount of data copied comes from value_size when the -// table was constructed). Therefore the data at val may be freed once the -// call returns. For string tables, the table takes ownership of the string. -// -// WARNING: the lowest bit of val is reserved and will be overwritten! -void upb_inttable_insert(upb_inttable *t, uint32_t key, const void *val); -// TODO: may want to allow for more complex keys with custom hash/comparison -// functions. -void upb_strtable_insert(upb_strtable *t, const char *key, const void *val); -void upb_inttable_compact(upb_inttable *t); -INLINE void upb_strtable_clear(upb_strtable *t) { - // TODO: improve. - uint16_t entry_size = t->t.entry_size; - upb_strtable_free(t); - upb_strtable_init(t, 8, entry_size); -} - -INLINE uint32_t _upb_inttable_bucket(upb_inttable *t, uint32_t k) { - uint32_t bucket = k & t->t.mask; // Identity hash for ints. - assert(bucket != UPB_END_OF_CHAIN); - return bucket; -} - -// Returns true if this key belongs in the array part of the table. -INLINE bool _upb_inttable_isarrkey(upb_inttable *t, uint32_t k) { - return (k < t->array_size); -} - -// Looks up key in this table, returning a pointer to the user's inserted data. -// We have the caller specify the entry_size because fixing this as a literal -// (instead of reading table->entry_size) gives the compiler more ability to -// optimize. -INLINE void *_upb_inttable_fastlookup(upb_inttable *t, uint32_t key, - size_t entry_size, size_t value_size) { - upb_inttable_value *arrval = - (upb_inttable_value*)UPB_INDEX(t->array, key, value_size); - if (_upb_inttable_isarrkey(t, key)) { - //DEBUGPRINTF("array lookup for key %d, &val=%p, has_entry=%d\n", key, val, val->has_entry); - return (arrval->has_entry) ? arrval : NULL; - } - uint32_t bucket = _upb_inttable_bucket(t, key); - upb_inttable_entry *e = - (upb_inttable_entry*)UPB_INDEX(t->t.entries, bucket, entry_size); - //DEBUGPRINTF("looking in first bucket %d, entry size=%zd, addr=%p\n", bucket, entry_size, e); - while (1) { - //DEBUGPRINTF("%d, %d, %d\n", e->val.has_entry, e->hdr.key, key); - if (e->hdr.key == key) { - //DEBUGPRINTF("returning val from hash part\n"); - return &e->val; - } - if ((bucket = e->hdr.next) == UPB_END_OF_CHAIN) return NULL; - //DEBUGPRINTF("looking in bucket %d\n", bucket); - e = (upb_inttable_entry*)UPB_INDEX(t->t.entries, bucket, entry_size); - } -} - -INLINE size_t _upb_inttable_entrysize(size_t value_size) { - return upb_align_up(sizeof(upb_inttable_header) + value_size, 8); -} - -INLINE void *upb_inttable_fastlookup(upb_inttable *t, uint32_t key, - uint32_t value_size) { - return _upb_inttable_fastlookup(t, key, _upb_inttable_entrysize(value_size), value_size); -} - -INLINE void *upb_inttable_lookup(upb_inttable *t, uint32_t key) { - return _upb_inttable_fastlookup(t, key, t->t.entry_size, t->t.value_size); -} - -void *upb_strtable_lookupl(upb_strtable *t, const char *key, size_t len); -void *upb_strtable_lookup(upb_strtable *t, const char *key); - - -/* upb_strtable_iter **********************************************************/ - -// Strtable iteration. Order is undefined. Insertions invalidate iterators. -// upb_strtable_iter i; -// for(upb_strtable_begin(&i, t); !upb_strtable_done(&i); upb_strtable_next(&i)) { -// const char *key = upb_strtable_iter_key(&i); -// const myval *val = upb_strtable_iter_value(&i); -// // ... -// } -typedef struct { - upb_strtable *t; - upb_strtable_entry *e; -} upb_strtable_iter; - -void upb_strtable_begin(upb_strtable_iter *i, upb_strtable *t); -void upb_strtable_next(upb_strtable_iter *i); -INLINE bool upb_strtable_done(upb_strtable_iter *i) { return i->e == NULL; } -INLINE const char *upb_strtable_iter_key(upb_strtable_iter *i) { - return i->e->hdr.key; -} -INLINE const void *upb_strtable_iter_value(upb_strtable_iter *i) { - return &i->e->val; -} - - -/* upb_inttable_iter **********************************************************/ - -// Inttable iteration. Order is undefined. Insertions invalidate iterators. -// for(upb_inttable_iter i = upb_inttable_begin(t); !upb_inttable_done(i); -// i = upb_inttable_next(t, i)) { -// // ... -// } -typedef struct { - uint32_t key; - upb_inttable_value *value; - bool array_part; -} upb_inttable_iter; - -upb_inttable_iter upb_inttable_begin(upb_inttable *t); -upb_inttable_iter upb_inttable_next(upb_inttable *t, upb_inttable_iter iter); -INLINE bool upb_inttable_done(upb_inttable_iter iter) { return iter.value == NULL; } -INLINE uint32_t upb_inttable_iter_key(upb_inttable_iter iter) { - return iter.key; -} -INLINE void *upb_inttable_iter_value(upb_inttable_iter iter) { - return iter.value; -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_TABLE_H_ */ diff --git a/src/upb_textprinter.c b/src/upb_textprinter.c deleted file mode 100644 index 14cce9b..0000000 --- a/src/upb_textprinter.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ - -#include "upb_textprinter.h" - -#include -#include -#include -#include - -struct _upb_textprinter { - upb_bytesink *bytesink; - int indent_depth; - bool single_line; - upb_status status; -}; - -#define CHECK(x) if ((x) < 0) goto err; - -static int upb_textprinter_putescaped(upb_textprinter *p, upb_strref *strref, - bool preserve_utf8) { - // Based on CEscapeInternal() from Google's protobuf release. - // TODO; we could read directly fraom a bytesrc's buffer instead. - // TODO; we could write directly into a bytesink's buffer instead. - char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf); - char buf[strref->len], *src = buf; - char *end = src + strref->len; - upb_strref_read(strref, src); - - // I think hex is prettier and more useful, but proto2 uses octal; should - // investigate whether it can parse hex also. - bool use_hex = false; - bool last_hex_escape = false; // true if last output char was \xNN - - for (; src < end; src++) { - if (dstend - dst < 4) { - CHECK(upb_bytesink_write(p->bytesink, dstbuf, dst - dstbuf, &p->status)); - dst = dstbuf; - } - - bool is_hex_escape = false; - switch (*src) { - case '\n': *(dst++) = '\\'; *(dst++) = 'n'; break; - case '\r': *(dst++) = '\\'; *(dst++) = 'r'; break; - case '\t': *(dst++) = '\\'; *(dst++) = 't'; break; - case '\"': *(dst++) = '\\'; *(dst++) = '\"'; break; - case '\'': *(dst++) = '\\'; *(dst++) = '\''; break; - case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break; - default: - // Note that if we emit \xNN and the src character after that is a hex - // digit then that digit must be escaped too to prevent it being - // interpreted as part of the character code by C. - if ((!preserve_utf8 || (uint8_t)*src < 0x80) && - (!isprint(*src) || (last_hex_escape && isxdigit(*src)))) { - sprintf(dst, (use_hex ? "\\x%02x" : "\\%03o"), (uint8_t)*src); - is_hex_escape = use_hex; - dst += 4; - } else { - *(dst++) = *src; break; - } - } - last_hex_escape = is_hex_escape; - } - // Flush remaining data. - CHECK(upb_bytesink_write(p->bytesink, dst, dst - dstbuf, &p->status)); - return 0; -err: - return -1; -} - -static int upb_textprinter_indent(upb_textprinter *p) { - if(!p->single_line) - for(int i = 0; i < p->indent_depth; i++) - CHECK(upb_bytesink_writestr(p->bytesink, " ", &p->status)); - return 0; -err: - return -1; -} - -static int upb_textprinter_endfield(upb_textprinter *p) { - if(p->single_line) { - CHECK(upb_bytesink_writestr(p->bytesink, " ", &p->status)); - } else { - CHECK(upb_bytesink_writestr(p->bytesink, "\n", &p->status)); - } - return 0; -err: - return -1; -} - -static upb_flow_t upb_textprinter_value(void *_p, upb_value fval, - upb_value val) { - upb_textprinter *p = _p; - upb_fielddef *f = upb_value_getfielddef(fval); - upb_textprinter_indent(p); - CHECK(upb_bytesink_printf(p->bytesink, &p->status, "%s: ", f->name)); -#define CASE(fmtstr, member) \ - CHECK(upb_bytesink_printf(p->bytesink, &p->status, fmtstr, upb_value_get ## member(val))); break; - switch(f->type) { - // TODO: figure out what we should really be doing for these - // floating-point formats. - case UPB_TYPE(DOUBLE): - CHECK(upb_bytesink_printf(p->bytesink, &p->status, "%.*g", DBL_DIG, upb_value_getdouble(val))); break; - case UPB_TYPE(FLOAT): - CHECK(upb_bytesink_printf(p->bytesink, &p->status, "%.*g", FLT_DIG+2, upb_value_getfloat(val))); break; - case UPB_TYPE(INT64): - case UPB_TYPE(SFIXED64): - case UPB_TYPE(SINT64): - CASE("%" PRId64, int64) - case UPB_TYPE(UINT64): - case UPB_TYPE(FIXED64): - CASE("%" PRIu64, uint64) - case UPB_TYPE(UINT32): - case UPB_TYPE(FIXED32): - CASE("%" PRIu32, uint32); - case UPB_TYPE(ENUM): { - upb_enumdef *enum_def = upb_downcast_enumdef(f->def); - const char *label = upb_enumdef_iton(enum_def, upb_value_getint32(val)); - if (label) { - // We found a corresponding string for this enum. Otherwise we fall - // through to the int32 code path. - CHECK(upb_bytesink_writestr(p->bytesink, label, &p->status)); - break; - } - } - case UPB_TYPE(INT32): - case UPB_TYPE(SFIXED32): - case UPB_TYPE(SINT32): - CASE("%" PRId32, int32) - case UPB_TYPE(BOOL): - CASE("%hhu", bool); - case UPB_TYPE(STRING): - case UPB_TYPE(BYTES): { - CHECK(upb_bytesink_writestr(p->bytesink, "\"", &p->status)); - CHECK(upb_textprinter_putescaped(p, upb_value_getstrref(val), - f->type == UPB_TYPE(STRING))); - CHECK(upb_bytesink_writestr(p->bytesink, "\"", &p->status)); - break; - } - } - upb_textprinter_endfield(p); - return UPB_CONTINUE; -err: - return UPB_BREAK; -} - -static upb_sflow_t upb_textprinter_startsubmsg(void *_p, upb_value fval) { - upb_textprinter *p = _p; - upb_fielddef *f = upb_value_getfielddef(fval); - upb_textprinter_indent(p); - bool ret = upb_bytesink_printf(p->bytesink, &p->status, "%s {", f->name); - if (!ret) return UPB_SBREAK; - if (!p->single_line) - upb_bytesink_writestr(p->bytesink, "\n", &p->status); - p->indent_depth++; - return UPB_CONTINUE_WITH(_p); -} - -static upb_flow_t upb_textprinter_endsubmsg(void *_p, upb_value fval) { - (void)fval; - upb_textprinter *p = _p; - p->indent_depth--; - upb_textprinter_indent(p); - upb_bytesink_writestr(p->bytesink, "}", &p->status); - upb_textprinter_endfield(p); - return UPB_CONTINUE; -} - -upb_textprinter *upb_textprinter_new() { - upb_textprinter *p = malloc(sizeof(*p)); - return p; -} - -void upb_textprinter_free(upb_textprinter *p) { - free(p); -} - -void upb_textprinter_reset(upb_textprinter *p, upb_bytesink *sink, - bool single_line) { - p->bytesink = sink; - p->single_line = single_line; - p->indent_depth = 0; -} - -upb_mhandlers *upb_textprinter_reghandlers(upb_handlers *h, upb_msgdef *m) { - upb_handlerset hset = { - NULL, // startmsg - NULL, // endmsg - upb_textprinter_value, - upb_textprinter_startsubmsg, - upb_textprinter_endsubmsg, - NULL, // startseq - NULL, // endseq - }; - return upb_handlers_reghandlerset(h, m, &hset); -} diff --git a/src/upb_textprinter.h b/src/upb_textprinter.h deleted file mode 100644 index 2d70d2e..0000000 --- a/src/upb_textprinter.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ - -#ifndef UPB_TEXT_H_ -#define UPB_TEXT_H_ - -#include "upb_bytestream.h" -#include "upb_handlers.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct _upb_textprinter; -typedef struct _upb_textprinter upb_textprinter; - -upb_textprinter *upb_textprinter_new(); -void upb_textprinter_free(upb_textprinter *p); -void upb_textprinter_reset(upb_textprinter *p, upb_bytesink *sink, - bool single_line); -upb_mhandlers *upb_textprinter_reghandlers(upb_handlers *h, upb_msgdef *m); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_TEXT_H_ */ diff --git a/src/upb_varint.c b/src/upb_varint.c deleted file mode 100644 index 25052aa..0000000 --- a/src/upb_varint.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ - -#include "upb_varint.h" - -// Given an encoded varint v, returns an integer with a single bit set that -// indicates the end of the varint. Subtracting one from this value will -// yield a mask that leaves only bits that are part of the varint. Returns -// 0 if the varint is unterminated. -INLINE uint64_t upb_get_vstopbit(uint64_t v) { - uint64_t cbits = v | 0x7f7f7f7f7f7f7f7fULL; - return ~cbits & (cbits+1); -} -INLINE uint64_t upb_get_vmask(uint64_t v) { return upb_get_vstopbit(v) - 1; } - -upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r) { - uint64_t b; - memcpy(&b, r.p, sizeof(b)); - uint64_t stop_bit = upb_get_vstopbit(b); - b = (b & 0x7f7f7f7f7f7f7f7fULL) & (stop_bit - 1); - b += b & 0x007f007f007f007fULL; - b += 3 * (b & 0x0000ffff0000ffffULL); - b += 15 * (b & 0x00000000ffffffffULL); - if (stop_bit == 0) { - // Error: unterminated varint. - upb_decoderet err_r = {(void*)0, 0}; - return err_r; - } - upb_decoderet my_r = {r.p + ((__builtin_ctzll(stop_bit) + 1) / 8), - r.val | (b << 7)}; - return my_r; -} - -upb_decoderet upb_vdecode_max8_wright(upb_decoderet r) { - uint64_t b; - memcpy(&b, r.p, sizeof(b)); - uint64_t stop_bit = upb_get_vstopbit(b); - b &= (stop_bit - 1); - b = ((b & 0x7f007f007f007f00) >> 1) | (b & 0x007f007f007f007f); - b = ((b & 0xffff0000ffff0000) >> 2) | (b & 0x0000ffff0000ffff); - b = ((b & 0xffffffff00000000) >> 4) | (b & 0x00000000ffffffff); - if (stop_bit == 0) { - // Error: unterminated varint. - upb_decoderet err_r = {(void*)0, 0}; - return err_r; - } - upb_decoderet my_r = {r.p + ((__builtin_ctzll(stop_bit) + 1) / 8), - r.val | (b << 14)}; - return my_r; -} diff --git a/src/upb_varint.h b/src/upb_varint.h deleted file mode 100644 index 87fca2b..0000000 --- a/src/upb_varint.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * A number of routines for varint manipulation (we keep them all around to - * have multiple approaches available for benchmarking). - */ - -#ifndef UPB_VARINT_DECODER_H_ -#define UPB_VARINT_DECODER_H_ - -#include "upb.h" -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Decoding *******************************************************************/ - -// All decoding functions return this struct by value. -typedef struct { - const char *p; // NULL if the varint was unterminated. - uint64_t val; -} upb_decoderet; - -// A basic branch-based decoder, uses 32-bit values to get good performance -// on 32-bit architectures (but performs well on 64-bits also). -INLINE upb_decoderet upb_vdecode_branch32(const char *p) { - upb_decoderet r = {NULL, 0}; - uint32_t low, high = 0; - uint32_t b; - b = *(p++); low = (b & 0x7f) ; if(!(b & 0x80)) goto done; - b = *(p++); low |= (b & 0x7f) << 7; if(!(b & 0x80)) goto done; - b = *(p++); low |= (b & 0x7f) << 14; if(!(b & 0x80)) goto done; - b = *(p++); low |= (b & 0x7f) << 21; if(!(b & 0x80)) goto done; - b = *(p++); low |= (b & 0x7f) << 28; - high = (b & 0x7f) >> 4; if(!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7f) << 3; if(!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7f) << 10; if(!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7f) << 17; if(!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7f) << 24; if(!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7f) << 31; if(!(b & 0x80)) goto done; - return r; - -done: - r.val = ((uint64_t)high << 32) | low; - r.p = p; - return r; -} - -// Like the previous, but uses 64-bit values. -INLINE upb_decoderet upb_vdecode_branch64(const char *p) { - uint64_t val; - uint64_t b; - upb_decoderet r = {(void*)0, 0}; - b = *(p++); val = (b & 0x7f) ; if(!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7f) << 7; if(!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7f) << 14; if(!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7f) << 21; if(!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7f) << 28; if(!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7f) << 35; if(!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7f) << 42; if(!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7f) << 49; if(!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7f) << 56; if(!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7f) << 63; if(!(b & 0x80)) goto done; - return r; - -done: - r.val = val; - r.p = p; - return r; -} - -// Decodes a varint of at most 8 bytes without branching (except for error). -upb_decoderet upb_vdecode_max8_wright(upb_decoderet r); - -// Another implementation of the previous. -upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r); - -// Template for a function that checks the first two bytes with branching -// and dispatches 2-10 bytes with a separate function. -#define UPB_VARINT_DECODER_CHECK2(name, decode_max8_function) \ -INLINE upb_decoderet upb_vdecode_check2_ ## name(const char *_p) { \ - uint8_t *p = (uint8_t*)_p; \ - if ((*p & 0x80) == 0) { upb_decoderet r = {_p + 1, *p & 0x7f}; return r; } \ - upb_decoderet r = {_p + 2, (*p & 0x7f) | ((*(p + 1) & 0x7f) << 7)}; \ - if ((*(p + 1) & 0x80) == 0) return r; \ - return decode_max8_function(r); \ -} - -UPB_VARINT_DECODER_CHECK2(wright, upb_vdecode_max8_wright); -UPB_VARINT_DECODER_CHECK2(massimino, upb_vdecode_max8_massimino); -#undef UPB_VARINT_DECODER_CHECK2 - -// Our canonical functions for decoding varints, based on the currently -// favored best-performing implementations. -INLINE upb_decoderet upb_vdecode_fast(const char *p) { - // Use nobranch2 on 64-bit, branch32 on 32-bit. - if (sizeof(long) == 8) - return upb_vdecode_check2_massimino(p); - else - return upb_vdecode_branch32(p); -} - -INLINE upb_decoderet upb_vdecode_max8_fast(upb_decoderet r) { - return upb_vdecode_max8_massimino(r); -} - - -/* Encoding *******************************************************************/ - -INLINE size_t upb_value_size(uint64_t val) { -#ifdef __GNUC__ - int high_bit = 63 - __builtin_clzll(val); // 0-based, undef if val == 0. -#else - int high_bit = 0; - uint64_t tmp = val; - while(tmp >>= 1) high_bit++; -#endif - return val == 0 ? 1 : high_bit / 8 + 1; -} - -// Encodes a 32-bit varint, *not* sign-extended. -INLINE uint64_t upb_vencode32(uint32_t val) { - uint64_t ret = 0; - for (int bitpos = 0; val; bitpos+=8, val >>=7) { - if (bitpos > 0) ret |= (1 << (bitpos-1)); - ret |= (val & 0x7f) << bitpos; - } - return ret; -} - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_VARINT_DECODER_H_ */ diff --git a/src/upbc.c b/src/upbc.c deleted file mode 100644 index 956a1b2..0000000 --- a/src/upbc.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * upbc is the upb compiler, which at the moment simply takes a - * protocol descriptor and outputs a header file containing the - * names and types of the fields. - */ - -#include -#include -#include -#include -#include "upb_def.h" -#include "upb_msg.h" -#include "upb_glue.h" -#include "upb_strstream.h" -#include "upb_decoder.h" - -/* These are in-place string transformations that do not change the length of - * the string (and thus never need to re-allocate). */ - -// Convert to C identifier: foo.bar.Baz -> foo_bar_Baz. -static void to_cident(upb_string *str) -{ - upb_strlen_t len = upb_string_len(str); - char *buf = upb_string_getrwbuf(str, len); - for(int32_t i = 0; i < len; i++) - if(buf[i] == '.' || buf[i] == '/') - buf[i] = '_'; -} - -// Convert to C proprocessor identifier: foo.bar.Baz -> FOO_BAR_BAZ. -static void to_preproc(upb_string *str) -{ - to_cident(str); - upb_strlen_t len = upb_string_len(str); - char *buf = upb_string_getrwbuf(str, len); - for(int32_t i = 0; i < len; i++) - buf[i] = toupper(buf[i]); -} - -static int my_memrchr(const char *data, char c, size_t len) -{ - int off = len-1; - while(off > 0 && data[off] != c) --off; - return off; -} - -/* The _const.h file defines the constants (enums) defined in the .proto - * file. */ -static void write_const_h(upb_def *defs[], int num_entries, char *outfile_name, - FILE *stream) -{ - /* Header file prologue. */ - upb_string *include_guard_name = upb_strdupc(outfile_name); - to_preproc(include_guard_name); - /* A bit cheesy, but will do the job. */ - upb_strlen_t len = upb_string_len(include_guard_name); - char *buf = upb_string_getrwbuf(include_guard_name, len); - buf[len-1] = 'C'; - - fputs("/* This file was generated by upbc (the upb compiler). " - "Do not edit. */\n\n", stream), - fprintf(stream, "#ifndef " UPB_STRFMT "\n", UPB_STRARG(include_guard_name)); - fprintf(stream, "#define " UPB_STRFMT "\n\n", UPB_STRARG(include_guard_name)); - fputs("#ifdef __cplusplus\n", stream); - fputs("extern \"C\" {\n", stream); - fputs("#endif\n\n", stream); - - /* Enums. */ - fprintf(stream, "/* Enums. */\n\n"); - for(int i = 0; i < num_entries; i++) { /* Foreach enum */ - if(defs[i]->type != UPB_DEF_ENUM) continue; - upb_enumdef *enumdef = upb_downcast_enumdef(defs[i]); - upb_string *enum_name = upb_strdup(UPB_UPCAST(enumdef)->fqname); - upb_string *enum_val_prefix = upb_strdup(enum_name); - to_cident(enum_name); - - const char *data = upb_string_getrobuf(enum_val_prefix); - upb_strlen_t len = upb_string_len(enum_val_prefix); - upb_strlen_t lastsep = my_memrchr(data, UPB_SYMBOL_SEPARATOR, len); - upb_string_getrwbuf(enum_val_prefix, lastsep + 1); - to_preproc(enum_val_prefix); - - fprintf(stream, "typedef enum " UPB_STRFMT " {\n", UPB_STRARG(enum_name)); - bool first = true; - /* Foreach enum value. */ - for (upb_enum_iter iter = upb_enum_begin(enumdef); - !upb_enum_done(iter); - iter = upb_enum_next(enumdef, iter)) { - upb_string *value_name = upb_strdup(upb_enum_iter_name(iter)); - to_preproc(value_name); - /* " GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13," */ - if (!first) fputs(",\n", stream); - first = false; - fprintf(stream, " " UPB_STRFMT UPB_STRFMT " = %" PRIu32, - UPB_STRARG(enum_val_prefix), UPB_STRARG(value_name), upb_enum_iter_number(iter)); - upb_string_unref(value_name); - } - fprintf(stream, "\n} " UPB_STRFMT ";\n\n", UPB_STRARG(enum_name)); - upb_string_unref(enum_name); - upb_string_unref(enum_val_prefix); - } - - /* Constants for field names and numbers. */ - fprintf(stream, "/* Constants for field names and numbers. */\n\n"); - for(int i = 0; i < num_entries; i++) { /* Foreach enum */ - upb_msgdef *m = upb_dyncast_msgdef(defs[i]); - if(!m) continue; - upb_string *msg_name = upb_strdup(UPB_UPCAST(m)->fqname); - upb_string *msg_val_prefix = upb_strdup(msg_name); - to_preproc(msg_val_prefix); - upb_msg_iter i; - for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) { - upb_fielddef *f = upb_msg_iter_field(i); - upb_string *preproc_field_name = upb_strdup(f->name); - to_preproc(preproc_field_name); - fprintf(stream, "#define " UPB_STRFMT "_" UPB_STRFMT "_FIELDNUM %d\n", - UPB_STRARG(msg_val_prefix), UPB_STRARG(preproc_field_name), f->number); - fprintf(stream, "#define " UPB_STRFMT "_" UPB_STRFMT "_FIELDNAME \"" - UPB_STRFMT "\"\n", UPB_STRARG(msg_val_prefix), UPB_STRARG(preproc_field_name), UPB_STRARG(f->name)); - upb_string_unref(preproc_field_name); - } - upb_string_unref(msg_val_prefix); - upb_string_unref(msg_name); - } - - /* Epilogue. */ - fputs("#ifdef __cplusplus\n", stream); - fputs("} /* extern \"C\" */\n", stream); - fputs("#endif\n\n", stream); - fprintf(stream, "#endif /* " UPB_STRFMT " */\n", UPB_STRARG(include_guard_name)); - upb_string_unref(include_guard_name); -} - -const char usage[] = - "upbc -- upb compiler.\n" - "upb v0.1 http://blog.reverberate.org/upb/\n" - "\n" - "Usage: upbc [options] descriptor-file\n" - "\n" - " -o OUTFILE-BASE Write to OUTFILE-BASE.h and OUTFILE-BASE.c instead\n" - " of using the input file as a basename.\n" -; - -void usage_err(char *err) -{ - fprintf(stderr, "upbc: %s\n\n", err); - fputs(usage, stderr); - exit(1); -} - -void error(char *err, ...) -{ - va_list args; - va_start(args, err); - fprintf(stderr, "upbc: "); - vfprintf(stderr, err, args); - va_end(args); - exit(1); -} - -int main(int argc, char *argv[]) -{ - /* Parse arguments. */ - char *outfile_base = NULL, *input_file = NULL; - for(int i = 1; i < argc; i++) { - if(strcmp(argv[i], "-o") == 0) { - if(++i == argc) - usage_err("-o must be followed by a FILE-BASE."); - else if(outfile_base) - usage_err("-o was specified multiple times."); - outfile_base = argv[i]; - } else { - if(input_file) - usage_err("You can only specify one input file."); - input_file = argv[i]; - } - } - if(!input_file) usage_err("You must specify an input file."); - if(!outfile_base) outfile_base = input_file; - - // Read and parse input file. - upb_string *descriptor = upb_strreadfile(input_file); - if(!descriptor) - error("Couldn't read input file."); - - // TODO: make upb_parsedesc use a separate symtab, so we can use it here when - // importing descriptor.proto. - upb_symtab *s = upb_symtab_new(); - upb_status status = UPB_STATUS_INIT; - upb_parsedesc(s, descriptor, &status); - if(!upb_ok(&status)) { - upb_printerr(&status); - error("Failed to parse input file descriptor\n"); - } - upb_status_uninit(&status); - - /* Emit output files. */ - const int maxsize = 256; - char h_const_filename[maxsize]; - if(snprintf(h_const_filename, maxsize, "%s_const.h", outfile_base) >= maxsize) - error("File base too long.\n"); - - FILE *h_const_file = fopen(h_const_filename, "w"); - if(!h_const_file) error("Failed to open _const.h output file\n"); - - int symcount; - upb_def **defs = upb_symtab_getdefs(s, &symcount, UPB_DEF_ANY); - write_const_h(defs, symcount, h_const_filename, h_const_file); - for (int i = 0; i < symcount; i++) upb_def_unref(defs[i]); - free(defs); - upb_string_unref(descriptor); - upb_symtab_unref(s); - fclose(h_const_file); - - return 0; -} -- cgit v1.2.3