Communication protocol
This commit is contained in:
parent
135c02c59b
commit
9d2976159e
|
@ -9,8 +9,12 @@ include_directories(${Boost_INCLUDE_DIRS})
|
|||
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
|
||||
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
|
||||
|
||||
add_definitions(-DBOOST_NO_EXCEPTIONS)
|
||||
|
||||
include_directories("${PROJECT_SOURCE_DIR}/source")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/../Common")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/source/carla/Protocol/carlaProtocol/include")
|
||||
|
||||
add_subdirectory(source/carla/server)
|
||||
add_subdirectory(source/test)
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
# add_library(carla_server
|
||||
# carla_protocol.pb.h
|
||||
# carla_protocol.pb.cc
|
||||
# )
|
||||
file(GLOB carla_server_SRC
|
||||
"*.h"
|
||||
"*.cpp"
|
||||
)
|
||||
|
||||
add_library(carla_server ${carla_server_SRC})
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,94 @@
|
|||
|
||||
|
||||
// Client Messages
|
||||
message EpisodeStart {
|
||||
|
||||
|
||||
optional int32 start_index =1;
|
||||
optional int32 end_index =2;
|
||||
|
||||
|
||||
}
|
||||
|
||||
message SceneInit {
|
||||
|
||||
|
||||
optional int32 mode =1;
|
||||
optional int32 scene =2;
|
||||
|
||||
|
||||
}
|
||||
|
||||
message Control {
|
||||
|
||||
optional float steer = 1;
|
||||
optional float gas = 2;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Server messages
|
||||
|
||||
message World {
|
||||
|
||||
repeated int32 modes = 1;
|
||||
repeated int32 scenes = 2;
|
||||
|
||||
|
||||
}
|
||||
|
||||
message Scene {
|
||||
|
||||
|
||||
|
||||
message Projection_Matrix{
|
||||
|
||||
repeated float cam_param = 1;
|
||||
|
||||
|
||||
}
|
||||
message Position{
|
||||
|
||||
required float pos_x = 1;
|
||||
required float pos_y = 2;
|
||||
|
||||
|
||||
}
|
||||
|
||||
repeated Position position =1;
|
||||
repeated Projection_Matrix camera_matrix =2;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
message EpisodeReady{
|
||||
|
||||
optional bool ready =1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
message Reward {
|
||||
|
||||
optional float player_x = 1;
|
||||
optional float player_y = 2;
|
||||
optional float speed = 3;
|
||||
optional float collision_gen = 4;
|
||||
optional float collision_ped = 5;
|
||||
optional float collision_car = 6;
|
||||
optional float intersect = 7;
|
||||
optional float inertia_x = 8;
|
||||
optional float inertia_y = 9;
|
||||
optional float inertia_z = 10;
|
||||
optional int32 timestamp = 11;
|
||||
optional float ori_x = 12;
|
||||
optional float ori_y = 13;
|
||||
optional float ori_z = 14;
|
||||
repeated bytes image = 15;
|
||||
repeated bytes depth = 16;
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Defines the abstract interface implemented by each of the language-specific
|
||||
// code generators.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace io { class ZeroCopyOutputStream; }
|
||||
class FileDescriptor;
|
||||
|
||||
namespace compiler {
|
||||
|
||||
// Defined in this file.
|
||||
class CodeGenerator;
|
||||
class GeneratorContext;
|
||||
|
||||
// The abstract interface to a class which generates code implementing a
|
||||
// particular proto file in a particular language. A number of these may
|
||||
// be registered with CommandLineInterface to support various languages.
|
||||
class LIBPROTOC_EXPORT CodeGenerator {
|
||||
public:
|
||||
inline CodeGenerator() {}
|
||||
virtual ~CodeGenerator();
|
||||
|
||||
// Generates code for the given proto file, generating one or more files in
|
||||
// the given output directory.
|
||||
//
|
||||
// A parameter to be passed to the generator can be specified on the
|
||||
// command line. This is intended to be used by Java and similar languages
|
||||
// to specify which specific class from the proto file is to be generated,
|
||||
// though it could have other uses as well. It is empty if no parameter was
|
||||
// given.
|
||||
//
|
||||
// Returns true if successful. Otherwise, sets *error to a description of
|
||||
// the problem (e.g. "invalid parameter") and returns false.
|
||||
virtual bool Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator);
|
||||
};
|
||||
|
||||
// CodeGenerators generate one or more files in a given directory. This
|
||||
// abstract interface represents the directory to which the CodeGenerator is
|
||||
// to write and other information about the context in which the Generator
|
||||
// runs.
|
||||
class LIBPROTOC_EXPORT GeneratorContext {
|
||||
public:
|
||||
inline GeneratorContext() {}
|
||||
virtual ~GeneratorContext();
|
||||
|
||||
// Opens the given file, truncating it if it exists, and returns a
|
||||
// ZeroCopyOutputStream that writes to the file. The caller takes ownership
|
||||
// of the returned object. This method never fails (a dummy stream will be
|
||||
// returned instead).
|
||||
//
|
||||
// The filename given should be relative to the root of the source tree.
|
||||
// E.g. the C++ generator, when generating code for "foo/bar.proto", will
|
||||
// generate the files "foo/bar.pb.h" and "foo/bar.pb.cc"; note that
|
||||
// "foo/" is included in these filenames. The filename is not allowed to
|
||||
// contain "." or ".." components.
|
||||
virtual io::ZeroCopyOutputStream* Open(const string& filename) = 0;
|
||||
|
||||
// Similar to Open() but the output will be appended to the file if exists
|
||||
virtual io::ZeroCopyOutputStream* OpenForAppend(const string& filename);
|
||||
|
||||
// Creates a ZeroCopyOutputStream which will insert code into the given file
|
||||
// at the given insertion point. See plugin.proto (plugin.pb.h) for more
|
||||
// information on insertion points. The default implementation
|
||||
// assert-fails -- it exists only for backwards-compatibility.
|
||||
//
|
||||
// WARNING: This feature is currently EXPERIMENTAL and is subject to change.
|
||||
virtual io::ZeroCopyOutputStream* OpenForInsert(
|
||||
const string& filename, const string& insertion_point);
|
||||
|
||||
// Returns a vector of FileDescriptors for all the files being compiled
|
||||
// in this run. Useful for languages, such as Go, that treat files
|
||||
// differently when compiled as a set rather than individually.
|
||||
virtual void ListParsedFiles(vector<const FileDescriptor*>* output);
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
|
||||
};
|
||||
|
||||
// The type GeneratorContext was once called OutputDirectory. This typedef
|
||||
// provides backward compatibility.
|
||||
typedef GeneratorContext OutputDirectory;
|
||||
|
||||
// Several code generators treat the parameter argument as holding a
|
||||
// list of options separated by commas. This helper function parses
|
||||
// a set of comma-delimited name/value pairs: e.g.,
|
||||
// "foo=bar,baz,qux=corge"
|
||||
// parses to the pairs:
|
||||
// ("foo", "bar"), ("baz", ""), ("qux", "corge")
|
||||
extern void ParseGeneratorParameter(const string&,
|
||||
vector<pair<string, string> >*);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
|
|
@ -0,0 +1,378 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Implements the Protocol Compiler front-end such that it may be reused by
|
||||
// custom compilers written to support other languages.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Descriptor; // descriptor.h
|
||||
class DescriptorPool; // descriptor.h
|
||||
class FileDescriptor; // descriptor.h
|
||||
class FileDescriptorProto; // descriptor.pb.h
|
||||
template<typename T> class RepeatedPtrField; // repeated_field.h
|
||||
|
||||
namespace compiler {
|
||||
|
||||
class CodeGenerator; // code_generator.h
|
||||
class GeneratorContext; // code_generator.h
|
||||
class DiskSourceTree; // importer.h
|
||||
|
||||
// This class implements the command-line interface to the protocol compiler.
|
||||
// It is designed to make it very easy to create a custom protocol compiler
|
||||
// supporting the languages of your choice. For example, if you wanted to
|
||||
// create a custom protocol compiler binary which includes both the regular
|
||||
// C++ support plus support for your own custom output "Foo", you would
|
||||
// write a class "FooGenerator" which implements the CodeGenerator interface,
|
||||
// then write a main() procedure like this:
|
||||
//
|
||||
// int main(int argc, char* argv[]) {
|
||||
// google::protobuf::compiler::CommandLineInterface cli;
|
||||
//
|
||||
// // Support generation of C++ source and headers.
|
||||
// google::protobuf::compiler::cpp::CppGenerator cpp_generator;
|
||||
// cli.RegisterGenerator("--cpp_out", &cpp_generator,
|
||||
// "Generate C++ source and header.");
|
||||
//
|
||||
// // Support generation of Foo code.
|
||||
// FooGenerator foo_generator;
|
||||
// cli.RegisterGenerator("--foo_out", &foo_generator,
|
||||
// "Generate Foo file.");
|
||||
//
|
||||
// return cli.Run(argc, argv);
|
||||
// }
|
||||
//
|
||||
// The compiler is invoked with syntax like:
|
||||
// protoc --cpp_out=outdir --foo_out=outdir --proto_path=src src/foo.proto
|
||||
//
|
||||
// For a full description of the command-line syntax, invoke it with --help.
|
||||
class LIBPROTOC_EXPORT CommandLineInterface {
|
||||
public:
|
||||
CommandLineInterface();
|
||||
~CommandLineInterface();
|
||||
|
||||
// Register a code generator for a language.
|
||||
//
|
||||
// Parameters:
|
||||
// * flag_name: The command-line flag used to specify an output file of
|
||||
// this type. The name must start with a '-'. If the name is longer
|
||||
// than one letter, it must start with two '-'s.
|
||||
// * generator: The CodeGenerator which will be called to generate files
|
||||
// of this type.
|
||||
// * help_text: Text describing this flag in the --help output.
|
||||
//
|
||||
// Some generators accept extra parameters. You can specify this parameter
|
||||
// on the command-line by placing it before the output directory, separated
|
||||
// by a colon:
|
||||
// protoc --foo_out=enable_bar:outdir
|
||||
// The text before the colon is passed to CodeGenerator::Generate() as the
|
||||
// "parameter".
|
||||
void RegisterGenerator(const string& flag_name,
|
||||
CodeGenerator* generator,
|
||||
const string& help_text);
|
||||
|
||||
// Register a code generator for a language.
|
||||
// Besides flag_name you can specify another option_flag_name that could be
|
||||
// used to pass extra parameters to the registered code generator.
|
||||
// Suppose you have registered a generator by calling:
|
||||
// command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...)
|
||||
// Then you could invoke the compiler with a command like:
|
||||
// protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz
|
||||
// This will pass "enable_bar,enable_baz" as the parameter to the generator.
|
||||
void RegisterGenerator(const string& flag_name,
|
||||
const string& option_flag_name,
|
||||
CodeGenerator* generator,
|
||||
const string& help_text);
|
||||
|
||||
// Enables "plugins". In this mode, if a command-line flag ends with "_out"
|
||||
// but does not match any registered generator, the compiler will attempt to
|
||||
// find a "plugin" to implement the generator. Plugins are just executables.
|
||||
// They should live somewhere in the PATH.
|
||||
//
|
||||
// The compiler determines the executable name to search for by concatenating
|
||||
// exe_name_prefix with the unrecognized flag name, removing "_out". So, for
|
||||
// example, if exe_name_prefix is "protoc-" and you pass the flag --foo_out,
|
||||
// the compiler will try to run the program "protoc-foo".
|
||||
//
|
||||
// The plugin program should implement the following usage:
|
||||
// plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS
|
||||
// --out indicates the output directory (as passed to the --foo_out
|
||||
// parameter); if omitted, the current directory should be used. --parameter
|
||||
// gives the generator parameter, if any was provided. The PROTO_FILES list
|
||||
// the .proto files which were given on the compiler command-line; these are
|
||||
// the files for which the plugin is expected to generate output code.
|
||||
// Finally, DESCRIPTORS is an encoded FileDescriptorSet (as defined in
|
||||
// descriptor.proto). This is piped to the plugin's stdin. The set will
|
||||
// include descriptors for all the files listed in PROTO_FILES as well as
|
||||
// all files that they import. The plugin MUST NOT attempt to read the
|
||||
// PROTO_FILES directly -- it must use the FileDescriptorSet.
|
||||
//
|
||||
// The plugin should generate whatever files are necessary, as code generators
|
||||
// normally do. It should write the names of all files it generates to
|
||||
// stdout. The names should be relative to the output directory, NOT absolute
|
||||
// names or relative to the current directory. If any errors occur, error
|
||||
// messages should be written to stderr. If an error is fatal, the plugin
|
||||
// should exit with a non-zero exit code.
|
||||
void AllowPlugins(const string& exe_name_prefix);
|
||||
|
||||
// Run the Protocol Compiler with the given command-line parameters.
|
||||
// Returns the error code which should be returned by main().
|
||||
//
|
||||
// It may not be safe to call Run() in a multi-threaded environment because
|
||||
// it calls strerror(). I'm not sure why you'd want to do this anyway.
|
||||
int Run(int argc, const char* const argv[]);
|
||||
|
||||
// Call SetInputsAreCwdRelative(true) if the input files given on the command
|
||||
// line should be interpreted relative to the proto import path specified
|
||||
// using --proto_path or -I flags. Otherwise, input file names will be
|
||||
// interpreted relative to the current working directory (or as absolute
|
||||
// paths if they start with '/'), though they must still reside inside
|
||||
// a directory given by --proto_path or the compiler will fail. The latter
|
||||
// mode is generally more intuitive and easier to use, especially e.g. when
|
||||
// defining implicit rules in Makefiles.
|
||||
void SetInputsAreProtoPathRelative(bool enable) {
|
||||
inputs_are_proto_path_relative_ = enable;
|
||||
}
|
||||
|
||||
// Provides some text which will be printed when the --version flag is
|
||||
// used. The version of libprotoc will also be printed on the next line
|
||||
// after this text.
|
||||
void SetVersionInfo(const string& text) {
|
||||
version_info_ = text;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
class ErrorPrinter;
|
||||
class GeneratorContextImpl;
|
||||
class MemoryOutputStream;
|
||||
|
||||
// Clear state from previous Run().
|
||||
void Clear();
|
||||
|
||||
// Remaps each file in input_files_ so that it is relative to one of the
|
||||
// directories in proto_path_. Returns false if an error occurred. This
|
||||
// is only used if inputs_are_proto_path_relative_ is false.
|
||||
bool MakeInputsBeProtoPathRelative(
|
||||
DiskSourceTree* source_tree);
|
||||
|
||||
// Return status for ParseArguments() and InterpretArgument().
|
||||
enum ParseArgumentStatus {
|
||||
PARSE_ARGUMENT_DONE_AND_CONTINUE,
|
||||
PARSE_ARGUMENT_DONE_AND_EXIT,
|
||||
PARSE_ARGUMENT_FAIL
|
||||
};
|
||||
|
||||
// Parse all command-line arguments.
|
||||
ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
|
||||
|
||||
// Parses a command-line argument into a name/value pair. Returns
|
||||
// true if the next argument in the argv should be used as the value,
|
||||
// false otherwise.
|
||||
//
|
||||
// Exmaples:
|
||||
// "-Isrc/protos" ->
|
||||
// name = "-I", value = "src/protos"
|
||||
// "--cpp_out=src/foo.pb2.cc" ->
|
||||
// name = "--cpp_out", value = "src/foo.pb2.cc"
|
||||
// "foo.proto" ->
|
||||
// name = "", value = "foo.proto"
|
||||
bool ParseArgument(const char* arg, string* name, string* value);
|
||||
|
||||
// Interprets arguments parsed with ParseArgument.
|
||||
ParseArgumentStatus InterpretArgument(const string& name,
|
||||
const string& value);
|
||||
|
||||
// Print the --help text to stderr.
|
||||
void PrintHelpText();
|
||||
|
||||
// Generate the given output file from the given input.
|
||||
struct OutputDirective; // see below
|
||||
bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files,
|
||||
const OutputDirective& output_directive,
|
||||
GeneratorContext* generator_context);
|
||||
bool GeneratePluginOutput(const vector<const FileDescriptor*>& parsed_files,
|
||||
const string& plugin_name,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error);
|
||||
|
||||
// Implements --encode and --decode.
|
||||
bool EncodeOrDecode(const DescriptorPool* pool);
|
||||
|
||||
// Implements the --descriptor_set_out option.
|
||||
bool WriteDescriptorSet(const vector<const FileDescriptor*> parsed_files);
|
||||
|
||||
// Get all transitive dependencies of the given file (including the file
|
||||
// itself), adding them to the given list of FileDescriptorProtos. The
|
||||
// protos will be ordered such that every file is listed before any file that
|
||||
// depends on it, so that you can call DescriptorPool::BuildFile() on them
|
||||
// in order. Any files in *already_seen will not be added, and each file
|
||||
// added will be inserted into *already_seen. If include_source_code_info is
|
||||
// true then include the source code information in the FileDescriptorProtos.
|
||||
static void GetTransitiveDependencies(
|
||||
const FileDescriptor* file,
|
||||
bool include_source_code_info,
|
||||
set<const FileDescriptor*>* already_seen,
|
||||
RepeatedPtrField<FileDescriptorProto>* output);
|
||||
|
||||
// Implements the --print_free_field_numbers. This function prints free field
|
||||
// numbers into stdout for the message and it's nested message types in
|
||||
// post-order, i.e. nested types first. Printed range are left-right
|
||||
// inclusive, i.e. [a, b].
|
||||
//
|
||||
// Groups:
|
||||
// For historical reasons, groups are considered to share the same
|
||||
// field number space with the parent message, thus it will not print free
|
||||
// field numbers for groups. The field numbers used in the groups are
|
||||
// excluded in the free field numbers of the parent message.
|
||||
//
|
||||
// Extension Ranges:
|
||||
// Extension ranges are considered ocuppied field numbers and they will not be
|
||||
// listed as free numbers in the output.
|
||||
void PrintFreeFieldNumbers(const Descriptor* descriptor);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// The name of the executable as invoked (i.e. argv[0]).
|
||||
string executable_name_;
|
||||
|
||||
// Version info set with SetVersionInfo().
|
||||
string version_info_;
|
||||
|
||||
// Registered generators.
|
||||
struct GeneratorInfo {
|
||||
string flag_name;
|
||||
string option_flag_name;
|
||||
CodeGenerator* generator;
|
||||
string help_text;
|
||||
};
|
||||
typedef map<string, GeneratorInfo> GeneratorMap;
|
||||
GeneratorMap generators_by_flag_name_;
|
||||
GeneratorMap generators_by_option_name_;
|
||||
// A map from generator names to the parameters specified using the option
|
||||
// flag. For example, if the user invokes the compiler with:
|
||||
// protoc --foo_out=outputdir --foo_opt=enable_bar ...
|
||||
// Then there will be an entry ("--foo_out", "enable_bar") in this map.
|
||||
map<string, string> generator_parameters_;
|
||||
|
||||
// See AllowPlugins(). If this is empty, plugins aren't allowed.
|
||||
string plugin_prefix_;
|
||||
|
||||
// Maps specific plugin names to files. When executing a plugin, this map
|
||||
// is searched first to find the plugin executable. If not found here, the
|
||||
// PATH (or other OS-specific search strategy) is searched.
|
||||
map<string, string> plugins_;
|
||||
|
||||
// Stuff parsed from command line.
|
||||
enum Mode {
|
||||
MODE_COMPILE, // Normal mode: parse .proto files and compile them.
|
||||
MODE_ENCODE, // --encode: read text from stdin, write binary to stdout.
|
||||
MODE_DECODE, // --decode: read binary from stdin, write text to stdout.
|
||||
MODE_PRINT, // Print mode: print info of the given .proto files and exit.
|
||||
};
|
||||
|
||||
Mode mode_;
|
||||
|
||||
enum PrintMode {
|
||||
PRINT_NONE, // Not in MODE_PRINT
|
||||
PRINT_FREE_FIELDS, // --print_free_fields
|
||||
};
|
||||
|
||||
PrintMode print_mode_;
|
||||
|
||||
enum ErrorFormat {
|
||||
ERROR_FORMAT_GCC, // GCC error output format (default).
|
||||
ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs).
|
||||
};
|
||||
|
||||
ErrorFormat error_format_;
|
||||
|
||||
vector<pair<string, string> > proto_path_; // Search path for proto files.
|
||||
vector<string> input_files_; // Names of the input proto files.
|
||||
|
||||
// output_directives_ lists all the files we are supposed to output and what
|
||||
// generator to use for each.
|
||||
struct OutputDirective {
|
||||
string name; // E.g. "--foo_out"
|
||||
CodeGenerator* generator; // NULL for plugins
|
||||
string parameter;
|
||||
string output_location;
|
||||
};
|
||||
vector<OutputDirective> output_directives_;
|
||||
|
||||
// When using --encode or --decode, this names the type we are encoding or
|
||||
// decoding. (Empty string indicates --decode_raw.)
|
||||
string codec_type_;
|
||||
|
||||
// If --descriptor_set_out was given, this is the filename to which the
|
||||
// FileDescriptorSet should be written. Otherwise, empty.
|
||||
string descriptor_set_name_;
|
||||
|
||||
// True if --include_imports was given, meaning that we should
|
||||
// write all transitive dependencies to the DescriptorSet. Otherwise, only
|
||||
// the .proto files listed on the command-line are added.
|
||||
bool imports_in_descriptor_set_;
|
||||
|
||||
// True if --include_source_info was given, meaning that we should not strip
|
||||
// SourceCodeInfo from the DescriptorSet.
|
||||
bool source_info_in_descriptor_set_;
|
||||
|
||||
// Was the --disallow_services flag used?
|
||||
bool disallow_services_;
|
||||
|
||||
// See SetInputsAreProtoPathRelative().
|
||||
bool inputs_are_proto_path_relative_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface);
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
|
|
@ -0,0 +1,72 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Generates C++ code for a given .proto file.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// CodeGenerator implementation which generates a C++ source file and
|
||||
// header. If you create your own protocol compiler binary and you want
|
||||
// it to support C++ output, you can do so by registering an instance of this
|
||||
// CodeGenerator with the CommandLineInterface in your main() function.
|
||||
class LIBPROTOC_EXPORT CppGenerator : public CodeGenerator {
|
||||
public:
|
||||
CppGenerator();
|
||||
~CppGenerator();
|
||||
|
||||
// implements CodeGenerator ----------------------------------------
|
||||
bool Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CppGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
|
|
@ -0,0 +1,317 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// This file is the public interface to the .proto file parser.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor_database.h>
|
||||
#include <google/protobuf/compiler/parser.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace io { class ZeroCopyInputStream; }
|
||||
|
||||
namespace compiler {
|
||||
|
||||
// Defined in this file.
|
||||
class Importer;
|
||||
class MultiFileErrorCollector;
|
||||
class SourceTree;
|
||||
class DiskSourceTree;
|
||||
|
||||
// TODO(kenton): Move all SourceTree stuff to a separate file?
|
||||
|
||||
// An implementation of DescriptorDatabase which loads files from a SourceTree
|
||||
// and parses them.
|
||||
//
|
||||
// Note: This class is not thread-safe since it maintains a table of source
|
||||
// code locations for error reporting. However, when a DescriptorPool wraps
|
||||
// a DescriptorDatabase, it uses mutex locking to make sure only one method
|
||||
// of the database is called at a time, even if the DescriptorPool is used
|
||||
// from multiple threads. Therefore, there is only a problem if you create
|
||||
// multiple DescriptorPools wrapping the same SourceTreeDescriptorDatabase
|
||||
// and use them from multiple threads.
|
||||
//
|
||||
// Note: This class does not implement FindFileContainingSymbol() or
|
||||
// FindFileContainingExtension(); these will always return false.
|
||||
class LIBPROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
SourceTreeDescriptorDatabase(SourceTree* source_tree);
|
||||
~SourceTreeDescriptorDatabase();
|
||||
|
||||
// Instructs the SourceTreeDescriptorDatabase to report any parse errors
|
||||
// to the given MultiFileErrorCollector. This should be called before
|
||||
// parsing. error_collector must remain valid until either this method
|
||||
// is called again or the SourceTreeDescriptorDatabase is destroyed.
|
||||
void RecordErrorsTo(MultiFileErrorCollector* error_collector) {
|
||||
error_collector_ = error_collector;
|
||||
}
|
||||
|
||||
// Gets a DescriptorPool::ErrorCollector which records errors to the
|
||||
// MultiFileErrorCollector specified with RecordErrorsTo(). This collector
|
||||
// has the ability to determine exact line and column numbers of errors
|
||||
// from the information given to it by the DescriptorPool.
|
||||
DescriptorPool::ErrorCollector* GetValidationErrorCollector() {
|
||||
using_validation_error_collector_ = true;
|
||||
return &validation_error_collector_;
|
||||
}
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const string& filename, FileDescriptorProto* output);
|
||||
bool FindFileContainingSymbol(const string& symbol_name,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingExtension(const string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output);
|
||||
|
||||
private:
|
||||
class SingleFileErrorCollector;
|
||||
|
||||
SourceTree* source_tree_;
|
||||
MultiFileErrorCollector* error_collector_;
|
||||
|
||||
class LIBPROTOBUF_EXPORT ValidationErrorCollector : public DescriptorPool::ErrorCollector {
|
||||
public:
|
||||
ValidationErrorCollector(SourceTreeDescriptorDatabase* owner);
|
||||
~ValidationErrorCollector();
|
||||
|
||||
// implements ErrorCollector ---------------------------------------
|
||||
void AddError(const string& filename,
|
||||
const string& element_name,
|
||||
const Message* descriptor,
|
||||
ErrorLocation location,
|
||||
const string& message);
|
||||
|
||||
private:
|
||||
SourceTreeDescriptorDatabase* owner_;
|
||||
};
|
||||
friend class ValidationErrorCollector;
|
||||
|
||||
bool using_validation_error_collector_;
|
||||
SourceLocationTable source_locations_;
|
||||
ValidationErrorCollector validation_error_collector_;
|
||||
};
|
||||
|
||||
// Simple interface for parsing .proto files. This wraps the process
|
||||
// of opening the file, parsing it with a Parser, recursively parsing all its
|
||||
// imports, and then cross-linking the results to produce a FileDescriptor.
|
||||
//
|
||||
// This is really just a thin wrapper around SourceTreeDescriptorDatabase.
|
||||
// You may find that SourceTreeDescriptorDatabase is more flexible.
|
||||
//
|
||||
// TODO(kenton): I feel like this class is not well-named.
|
||||
class LIBPROTOBUF_EXPORT Importer {
|
||||
public:
|
||||
Importer(SourceTree* source_tree,
|
||||
MultiFileErrorCollector* error_collector);
|
||||
~Importer();
|
||||
|
||||
// Import the given file and build a FileDescriptor representing it. If
|
||||
// the file is already in the DescriptorPool, the existing FileDescriptor
|
||||
// will be returned. The FileDescriptor is property of the DescriptorPool,
|
||||
// and will remain valid until it is destroyed. If any errors occur, they
|
||||
// will be reported using the error collector and Import() will return NULL.
|
||||
//
|
||||
// A particular Importer object will only report errors for a particular
|
||||
// file once. All future attempts to import the same file will return NULL
|
||||
// without reporting any errors. The idea is that you might want to import
|
||||
// a lot of files without seeing the same errors over and over again. If
|
||||
// you want to see errors for the same files repeatedly, you can use a
|
||||
// separate Importer object to import each one (but use the same
|
||||
// DescriptorPool so that they can be cross-linked).
|
||||
const FileDescriptor* Import(const string& filename);
|
||||
|
||||
// The DescriptorPool in which all imported FileDescriptors and their
|
||||
// contents are stored.
|
||||
inline const DescriptorPool* pool() const {
|
||||
return &pool_;
|
||||
}
|
||||
|
||||
void AddUnusedImportTrackFile(const string& file_name);
|
||||
void ClearUnusedImportTrackFiles();
|
||||
|
||||
private:
|
||||
SourceTreeDescriptorDatabase database_;
|
||||
DescriptorPool pool_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Importer);
|
||||
};
|
||||
|
||||
// If the importer encounters problems while trying to import the proto files,
|
||||
// it reports them to a MultiFileErrorCollector.
|
||||
class LIBPROTOBUF_EXPORT MultiFileErrorCollector {
|
||||
public:
|
||||
inline MultiFileErrorCollector() {}
|
||||
virtual ~MultiFileErrorCollector();
|
||||
|
||||
// Line and column numbers are zero-based. A line number of -1 indicates
|
||||
// an error with the entire file (e.g. "not found").
|
||||
virtual void AddError(const string& filename, int line, int column,
|
||||
const string& message) = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultiFileErrorCollector);
|
||||
};
|
||||
|
||||
// Abstract interface which represents a directory tree containing proto files.
|
||||
// Used by the default implementation of Importer to resolve import statements
|
||||
// Most users will probably want to use the DiskSourceTree implementation,
|
||||
// below.
|
||||
class LIBPROTOBUF_EXPORT SourceTree {
|
||||
public:
|
||||
inline SourceTree() {}
|
||||
virtual ~SourceTree();
|
||||
|
||||
// Open the given file and return a stream that reads it, or NULL if not
|
||||
// found. The caller takes ownership of the returned object. The filename
|
||||
// must be a path relative to the root of the source tree and must not
|
||||
// contain "." or ".." components.
|
||||
virtual io::ZeroCopyInputStream* Open(const string& filename) = 0;
|
||||
|
||||
// If Open() returns NULL, calling this method immediately will return an
|
||||
// description of the error.
|
||||
// Subclasses should implement this method and return a meaningful value for
|
||||
// better error reporting.
|
||||
// TODO(xiaofeng): change this to a pure virtual function.
|
||||
virtual string GetLastErrorMessage();
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree);
|
||||
};
|
||||
|
||||
// An implementation of SourceTree which loads files from locations on disk.
|
||||
// Multiple mappings can be set up to map locations in the DiskSourceTree to
|
||||
// locations in the physical filesystem.
|
||||
class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree {
|
||||
public:
|
||||
DiskSourceTree();
|
||||
~DiskSourceTree();
|
||||
|
||||
// Map a path on disk to a location in the SourceTree. The path may be
|
||||
// either a file or a directory. If it is a directory, the entire tree
|
||||
// under it will be mapped to the given virtual location. To map a directory
|
||||
// to the root of the source tree, pass an empty string for virtual_path.
|
||||
//
|
||||
// If multiple mapped paths apply when opening a file, they will be searched
|
||||
// in order. For example, if you do:
|
||||
// MapPath("bar", "foo/bar");
|
||||
// MapPath("", "baz");
|
||||
// and then you do:
|
||||
// Open("bar/qux");
|
||||
// the DiskSourceTree will first try to open foo/bar/qux, then baz/bar/qux,
|
||||
// returning the first one that opens successfuly.
|
||||
//
|
||||
// disk_path may be an absolute path or relative to the current directory,
|
||||
// just like a path you'd pass to open().
|
||||
void MapPath(const string& virtual_path, const string& disk_path);
|
||||
|
||||
// Return type for DiskFileToVirtualFile().
|
||||
enum DiskFileToVirtualFileResult {
|
||||
SUCCESS,
|
||||
SHADOWED,
|
||||
CANNOT_OPEN,
|
||||
NO_MAPPING
|
||||
};
|
||||
|
||||
// Given a path to a file on disk, find a virtual path mapping to that
|
||||
// file. The first mapping created with MapPath() whose disk_path contains
|
||||
// the filename is used. However, that virtual path may not actually be
|
||||
// usable to open the given file. Possible return values are:
|
||||
// * SUCCESS: The mapping was found. *virtual_file is filled in so that
|
||||
// calling Open(*virtual_file) will open the file named by disk_file.
|
||||
// * SHADOWED: A mapping was found, but using Open() to open this virtual
|
||||
// path will end up returning some different file. This is because some
|
||||
// other mapping with a higher precedence also matches this virtual path
|
||||
// and maps it to a different file that exists on disk. *virtual_file
|
||||
// is filled in as it would be in the SUCCESS case. *shadowing_disk_file
|
||||
// is filled in with the disk path of the file which would be opened if
|
||||
// you were to call Open(*virtual_file).
|
||||
// * CANNOT_OPEN: The mapping was found and was not shadowed, but the
|
||||
// file specified cannot be opened. When this value is returned,
|
||||
// errno will indicate the reason the file cannot be opened. *virtual_file
|
||||
// will be set to the virtual path as in the SUCCESS case, even though
|
||||
// it is not useful.
|
||||
// * NO_MAPPING: Indicates that no mapping was found which contains this
|
||||
// file.
|
||||
DiskFileToVirtualFileResult
|
||||
DiskFileToVirtualFile(const string& disk_file,
|
||||
string* virtual_file,
|
||||
string* shadowing_disk_file);
|
||||
|
||||
// Given a virtual path, find the path to the file on disk.
|
||||
// Return true and update disk_file with the on-disk path if the file exists.
|
||||
// Return false and leave disk_file untouched if the file doesn't exist.
|
||||
bool VirtualFileToDiskFile(const string& virtual_file, string* disk_file);
|
||||
|
||||
// implements SourceTree -------------------------------------------
|
||||
virtual io::ZeroCopyInputStream* Open(const string& filename);
|
||||
|
||||
virtual string GetLastErrorMessage();
|
||||
|
||||
private:
|
||||
struct Mapping {
|
||||
string virtual_path;
|
||||
string disk_path;
|
||||
|
||||
inline Mapping(const string& virtual_path_param,
|
||||
const string& disk_path_param)
|
||||
: virtual_path(virtual_path_param), disk_path(disk_path_param) {}
|
||||
};
|
||||
vector<Mapping> mappings_;
|
||||
string last_error_message_;
|
||||
|
||||
// Like Open(), but returns the on-disk path in disk_file if disk_file is
|
||||
// non-NULL and the file could be successfully opened.
|
||||
io::ZeroCopyInputStream* OpenVirtualFile(const string& virtual_file,
|
||||
string* disk_file);
|
||||
|
||||
// Like Open() but given the actual on-disk path.
|
||||
io::ZeroCopyInputStream* OpenDiskFile(const string& filename);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DiskSourceTree);
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
|
|
@ -0,0 +1,72 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Generates Java code for a given .proto file.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace java {
|
||||
|
||||
// CodeGenerator implementation which generates Java code. If you create your
|
||||
// own protocol compiler binary and you want it to support Java output, you
|
||||
// can do so by registering an instance of this CodeGenerator with the
|
||||
// CommandLineInterface in your main() function.
|
||||
class LIBPROTOC_EXPORT JavaGenerator : public CodeGenerator {
|
||||
public:
|
||||
JavaGenerator();
|
||||
~JavaGenerator();
|
||||
|
||||
// implements CodeGenerator ----------------------------------------
|
||||
bool Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* context,
|
||||
string* error) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaGenerator);
|
||||
};
|
||||
|
||||
} // namespace java
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__
|
|
@ -0,0 +1,522 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Implements parsing of .proto files to FileDescriptorProtos.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_PARSER_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_PARSER_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/io/tokenizer.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf { class Message; }
|
||||
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
|
||||
// Defined in this file.
|
||||
class Parser;
|
||||
class SourceLocationTable;
|
||||
|
||||
// Implements parsing of protocol definitions (such as .proto files).
|
||||
//
|
||||
// Note that most users will be more interested in the Importer class.
|
||||
// Parser is a lower-level class which simply converts a single .proto file
|
||||
// to a FileDescriptorProto. It does not resolve import directives or perform
|
||||
// many other kinds of validation needed to construct a complete
|
||||
// FileDescriptor.
|
||||
class LIBPROTOBUF_EXPORT Parser {
|
||||
public:
|
||||
Parser();
|
||||
~Parser();
|
||||
|
||||
// Parse the entire input and construct a FileDescriptorProto representing
|
||||
// it. Returns true if no errors occurred, false otherwise.
|
||||
bool Parse(io::Tokenizer* input, FileDescriptorProto* file);
|
||||
|
||||
// Optional fetaures:
|
||||
|
||||
// DEPRECATED: New code should use the SourceCodeInfo embedded in the
|
||||
// FileDescriptorProto.
|
||||
//
|
||||
// Requests that locations of certain definitions be recorded to the given
|
||||
// SourceLocationTable while parsing. This can be used to look up exact line
|
||||
// and column numbers for errors reported by DescriptorPool during validation.
|
||||
// Set to NULL (the default) to discard source location information.
|
||||
void RecordSourceLocationsTo(SourceLocationTable* location_table) {
|
||||
source_location_table_ = location_table;
|
||||
}
|
||||
|
||||
// Requests that errors be recorded to the given ErrorCollector while
|
||||
// parsing. Set to NULL (the default) to discard error messages.
|
||||
void RecordErrorsTo(io::ErrorCollector* error_collector) {
|
||||
error_collector_ = error_collector;
|
||||
}
|
||||
|
||||
// Returns the identifier used in the "syntax = " declaration, if one was
|
||||
// seen during the last call to Parse(), or the empty string otherwise.
|
||||
const string& GetSyntaxIdentifier() { return syntax_identifier_; }
|
||||
|
||||
// If set true, input files will be required to begin with a syntax
|
||||
// identifier. Otherwise, files may omit this. If a syntax identifier
|
||||
// is provided, it must be 'syntax = "proto2";' and must appear at the
|
||||
// top of this file regardless of whether or not it was required.
|
||||
void SetRequireSyntaxIdentifier(bool value) {
|
||||
require_syntax_identifier_ = value;
|
||||
}
|
||||
|
||||
// Call SetStopAfterSyntaxIdentifier(true) to tell the parser to stop
|
||||
// parsing as soon as it has seen the syntax identifier, or lack thereof.
|
||||
// This is useful for quickly identifying the syntax of the file without
|
||||
// parsing the whole thing. If this is enabled, no error will be recorded
|
||||
// if the syntax identifier is something other than "proto2" (since
|
||||
// presumably the caller intends to deal with that), but other kinds of
|
||||
// errors (e.g. parse errors) will still be reported. When this is enabled,
|
||||
// you may pass a NULL FileDescriptorProto to Parse().
|
||||
void SetStopAfterSyntaxIdentifier(bool value) {
|
||||
stop_after_syntax_identifier_ = value;
|
||||
}
|
||||
|
||||
private:
|
||||
class LocationRecorder;
|
||||
|
||||
// =================================================================
|
||||
// Error recovery helpers
|
||||
|
||||
// Consume the rest of the current statement. This consumes tokens
|
||||
// until it sees one of:
|
||||
// ';' Consumes the token and returns.
|
||||
// '{' Consumes the brace then calls SkipRestOfBlock().
|
||||
// '}' Returns without consuming.
|
||||
// EOF Returns (can't consume).
|
||||
// The Parser often calls SkipStatement() after encountering a syntax
|
||||
// error. This allows it to go on parsing the following lines, allowing
|
||||
// it to report more than just one error in the file.
|
||||
void SkipStatement();
|
||||
|
||||
// Consume the rest of the current block, including nested blocks,
|
||||
// ending after the closing '}' is encountered and consumed, or at EOF.
|
||||
void SkipRestOfBlock();
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Single-token consuming helpers
|
||||
//
|
||||
// These make parsing code more readable.
|
||||
|
||||
// True if the current token is TYPE_END.
|
||||
inline bool AtEnd();
|
||||
|
||||
// True if the next token matches the given text.
|
||||
inline bool LookingAt(const char* text);
|
||||
// True if the next token is of the given type.
|
||||
inline bool LookingAtType(io::Tokenizer::TokenType token_type);
|
||||
|
||||
// If the next token exactly matches the text given, consume it and return
|
||||
// true. Otherwise, return false without logging an error.
|
||||
bool TryConsume(const char* text);
|
||||
|
||||
// These attempt to read some kind of token from the input. If successful,
|
||||
// they return true. Otherwise they return false and add the given error
|
||||
// to the error list.
|
||||
|
||||
// Consume a token with the exact text given.
|
||||
bool Consume(const char* text, const char* error);
|
||||
// Same as above, but automatically generates the error "Expected \"text\".",
|
||||
// where "text" is the expected token text.
|
||||
bool Consume(const char* text);
|
||||
// Consume a token of type IDENTIFIER and store its text in "output".
|
||||
bool ConsumeIdentifier(string* output, const char* error);
|
||||
// Consume an integer and store its value in "output".
|
||||
bool ConsumeInteger(int* output, const char* error);
|
||||
// Consume a signed integer and store its value in "output".
|
||||
bool ConsumeSignedInteger(int* output, const char* error);
|
||||
// Consume a 64-bit integer and store its value in "output". If the value
|
||||
// is greater than max_value, an error will be reported.
|
||||
bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error);
|
||||
// Consume a number and store its value in "output". This will accept
|
||||
// tokens of either INTEGER or FLOAT type.
|
||||
bool ConsumeNumber(double* output, const char* error);
|
||||
// Consume a string literal and store its (unescaped) value in "output".
|
||||
bool ConsumeString(string* output, const char* error);
|
||||
|
||||
// Consume a token representing the end of the statement. Comments between
|
||||
// this token and the next will be harvested for documentation. The given
|
||||
// LocationRecorder should refer to the declaration that was just parsed;
|
||||
// it will be populated with these comments.
|
||||
//
|
||||
// TODO(kenton): The LocationRecorder is const because historically locations
|
||||
// have been passed around by const reference, for no particularly good
|
||||
// reason. We should probably go through and change them all to mutable
|
||||
// pointer to make this more intuitive.
|
||||
bool TryConsumeEndOfDeclaration(const char* text,
|
||||
const LocationRecorder* location);
|
||||
bool ConsumeEndOfDeclaration(const char* text,
|
||||
const LocationRecorder* location);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Error logging helpers
|
||||
|
||||
// Invokes error_collector_->AddError(), if error_collector_ is not NULL.
|
||||
void AddError(int line, int column, const string& error);
|
||||
|
||||
// Invokes error_collector_->AddError() with the line and column number
|
||||
// of the current token.
|
||||
void AddError(const string& error);
|
||||
|
||||
// Records a location in the SourceCodeInfo.location table (see
|
||||
// descriptor.proto). We use RAII to ensure that the start and end locations
|
||||
// are recorded -- the constructor records the start location and the
|
||||
// destructor records the end location. Since the parser is
|
||||
// recursive-descent, this works out beautifully.
|
||||
class LIBPROTOBUF_EXPORT LocationRecorder {
|
||||
public:
|
||||
// Construct the file's "root" location.
|
||||
LocationRecorder(Parser* parser);
|
||||
|
||||
// Construct a location that represents a declaration nested within the
|
||||
// given parent. E.g. a field's location is nested within the location
|
||||
// for a message type. The parent's path will be copied, so you should
|
||||
// call AddPath() only to add the path components leading from the parent
|
||||
// to the child (as opposed to leading from the root to the child).
|
||||
LocationRecorder(const LocationRecorder& parent);
|
||||
|
||||
// Convenience constructors that call AddPath() one or two times.
|
||||
LocationRecorder(const LocationRecorder& parent, int path1);
|
||||
LocationRecorder(const LocationRecorder& parent, int path1, int path2);
|
||||
|
||||
~LocationRecorder();
|
||||
|
||||
// Add a path component. See SourceCodeInfo.Location.path in
|
||||
// descriptor.proto.
|
||||
void AddPath(int path_component);
|
||||
|
||||
// By default the location is considered to start at the current token at
|
||||
// the time the LocationRecorder is created. StartAt() sets the start
|
||||
// location to the given token instead.
|
||||
void StartAt(const io::Tokenizer::Token& token);
|
||||
|
||||
// Start at the same location as some other LocationRecorder.
|
||||
void StartAt(const LocationRecorder& other);
|
||||
|
||||
// By default the location is considered to end at the previous token at
|
||||
// the time the LocationRecorder is destroyed. EndAt() sets the end
|
||||
// location to the given token instead.
|
||||
void EndAt(const io::Tokenizer::Token& token);
|
||||
|
||||
// Records the start point of this location to the SourceLocationTable that
|
||||
// was passed to RecordSourceLocationsTo(), if any. SourceLocationTable
|
||||
// is an older way of keeping track of source locations which is still
|
||||
// used in some places.
|
||||
void RecordLegacyLocation(const Message* descriptor,
|
||||
DescriptorPool::ErrorCollector::ErrorLocation location);
|
||||
|
||||
// Attaches leading and trailing comments to the location. The two strings
|
||||
// will be swapped into place, so after this is called *leading and
|
||||
// *trailing will be empty.
|
||||
//
|
||||
// TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for
|
||||
// why this is const.
|
||||
void AttachComments(string* leading, string* trailing) const;
|
||||
|
||||
private:
|
||||
Parser* parser_;
|
||||
SourceCodeInfo::Location* location_;
|
||||
|
||||
void Init(const LocationRecorder& parent);
|
||||
};
|
||||
|
||||
// =================================================================
|
||||
// Parsers for various language constructs
|
||||
|
||||
// Parses the "syntax = \"proto2\";" line at the top of the file. Returns
|
||||
// false if it failed to parse or if the syntax identifier was not
|
||||
// recognized.
|
||||
bool ParseSyntaxIdentifier();
|
||||
|
||||
// These methods parse various individual bits of code. They return
|
||||
// false if they completely fail to parse the construct. In this case,
|
||||
// it is probably necessary to skip the rest of the statement to recover.
|
||||
// However, if these methods return true, it does NOT mean that there
|
||||
// were no errors; only that there were no *syntax* errors. For instance,
|
||||
// if a service method is defined using proper syntax but uses a primitive
|
||||
// type as its input or output, ParseMethodField() still returns true
|
||||
// and only reports the error by calling AddError(). In practice, this
|
||||
// makes logic much simpler for the caller.
|
||||
|
||||
// Parse a top-level message, enum, service, etc.
|
||||
bool ParseTopLevelStatement(FileDescriptorProto* file,
|
||||
const LocationRecorder& root_location);
|
||||
|
||||
// Parse various language high-level language construrcts.
|
||||
bool ParseMessageDefinition(DescriptorProto* message,
|
||||
const LocationRecorder& message_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseEnumDefinition(EnumDescriptorProto* enum_type,
|
||||
const LocationRecorder& enum_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseServiceDefinition(ServiceDescriptorProto* service,
|
||||
const LocationRecorder& service_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParsePackage(FileDescriptorProto* file,
|
||||
const LocationRecorder& root_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseImport(RepeatedPtrField<string>* dependency,
|
||||
RepeatedField<int32>* public_dependency,
|
||||
RepeatedField<int32>* weak_dependency,
|
||||
const LocationRecorder& root_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseOption(Message* options,
|
||||
const LocationRecorder& options_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// These methods parse the contents of a message, enum, or service type and
|
||||
// add them to the given object. They consume the entire block including
|
||||
// the beginning and ending brace.
|
||||
bool ParseMessageBlock(DescriptorProto* message,
|
||||
const LocationRecorder& message_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseEnumBlock(EnumDescriptorProto* enum_type,
|
||||
const LocationRecorder& enum_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseServiceBlock(ServiceDescriptorProto* service,
|
||||
const LocationRecorder& service_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse one statement within a message, enum, or service block, inclunding
|
||||
// final semicolon.
|
||||
bool ParseMessageStatement(DescriptorProto* message,
|
||||
const LocationRecorder& message_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseEnumStatement(EnumDescriptorProto* message,
|
||||
const LocationRecorder& enum_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
bool ParseServiceStatement(ServiceDescriptorProto* message,
|
||||
const LocationRecorder& service_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a field of a message. If the field is a group, its type will be
|
||||
// added to "messages".
|
||||
//
|
||||
// parent_location and location_field_number_for_nested_type are needed when
|
||||
// parsing groups -- we need to generate a nested message type within the
|
||||
// parent and record its location accordingly. Since the parent could be
|
||||
// either a FileDescriptorProto or a DescriptorProto, we must pass in the
|
||||
// correct field number to use.
|
||||
bool ParseMessageField(FieldDescriptorProto* field,
|
||||
RepeatedPtrField<DescriptorProto>* messages,
|
||||
const LocationRecorder& parent_location,
|
||||
int location_field_number_for_nested_type,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Like ParseMessageField() but expects the label has already been filled in
|
||||
// by the caller.
|
||||
bool ParseMessageFieldNoLabel(FieldDescriptorProto* field,
|
||||
RepeatedPtrField<DescriptorProto>* messages,
|
||||
const LocationRecorder& parent_location,
|
||||
int location_field_number_for_nested_type,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse an "extensions" declaration.
|
||||
bool ParseExtensions(DescriptorProto* message,
|
||||
const LocationRecorder& extensions_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse an "extend" declaration. (See also comments for
|
||||
// ParseMessageField().)
|
||||
bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
|
||||
RepeatedPtrField<DescriptorProto>* messages,
|
||||
const LocationRecorder& parent_location,
|
||||
int location_field_number_for_nested_type,
|
||||
const LocationRecorder& extend_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a "oneof" declaration. The caller is responsible for setting
|
||||
// oneof_decl->label() since it will have had to parse the label before it
|
||||
// knew it was parsing a oneof.
|
||||
bool ParseOneof(OneofDescriptorProto* oneof_decl,
|
||||
DescriptorProto* containing_type,
|
||||
int oneof_index,
|
||||
const LocationRecorder& oneof_location,
|
||||
const LocationRecorder& containing_type_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a single enum value within an enum block.
|
||||
bool ParseEnumConstant(EnumValueDescriptorProto* enum_value,
|
||||
const LocationRecorder& enum_value_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse enum constant options, i.e. the list in square brackets at the end
|
||||
// of the enum constant value definition.
|
||||
bool ParseEnumConstantOptions(EnumValueDescriptorProto* value,
|
||||
const LocationRecorder& enum_value_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a single method within a service definition.
|
||||
bool ParseServiceMethod(MethodDescriptorProto* method,
|
||||
const LocationRecorder& method_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
|
||||
// Parse options of a single method or stream.
|
||||
bool ParseOptions(const LocationRecorder& parent_location,
|
||||
const FileDescriptorProto* containing_file,
|
||||
const int optionsFieldNumber,
|
||||
Message* mutable_options);
|
||||
|
||||
// Parse "required", "optional", or "repeated" and fill in "label"
|
||||
// with the value.
|
||||
bool ParseLabel(FieldDescriptorProto::Label* label,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse a type name and fill in "type" (if it is a primitive) or
|
||||
// "type_name" (if it is not) with the type parsed.
|
||||
bool ParseType(FieldDescriptorProto::Type* type,
|
||||
string* type_name);
|
||||
// Parse a user-defined type and fill in "type_name" with the name.
|
||||
// If a primitive type is named, it is treated as an error.
|
||||
bool ParseUserDefinedType(string* type_name);
|
||||
|
||||
// Parses field options, i.e. the stuff in square brackets at the end
|
||||
// of a field definition. Also parses default value.
|
||||
bool ParseFieldOptions(FieldDescriptorProto* field,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parse the "default" option. This needs special handling because its
|
||||
// type is the field's type.
|
||||
bool ParseDefaultAssignment(FieldDescriptorProto* field,
|
||||
const LocationRecorder& field_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
enum OptionStyle {
|
||||
OPTION_ASSIGNMENT, // just "name = value"
|
||||
OPTION_STATEMENT // "option name = value;"
|
||||
};
|
||||
|
||||
// Parse a single option name/value pair, e.g. "ctype = CORD". The name
|
||||
// identifies a field of the given Message, and the value of that field
|
||||
// is set to the parsed value.
|
||||
bool ParseOption(Message* options,
|
||||
const LocationRecorder& options_location,
|
||||
const FileDescriptorProto* containing_file,
|
||||
OptionStyle style);
|
||||
|
||||
// Parses a single part of a multipart option name. A multipart name consists
|
||||
// of names separated by dots. Each name is either an identifier or a series
|
||||
// of identifiers separated by dots and enclosed in parentheses. E.g.,
|
||||
// "foo.(bar.baz).qux".
|
||||
bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
|
||||
const LocationRecorder& part_location,
|
||||
const FileDescriptorProto* containing_file);
|
||||
|
||||
// Parses a string surrounded by balanced braces. Strips off the outer
|
||||
// braces and stores the enclosed string in *value.
|
||||
// E.g.,
|
||||
// { foo } *value gets 'foo'
|
||||
// { foo { bar: box } } *value gets 'foo { bar: box }'
|
||||
// {} *value gets ''
|
||||
//
|
||||
// REQUIRES: LookingAt("{")
|
||||
// When finished successfully, we are looking at the first token past
|
||||
// the ending brace.
|
||||
bool ParseUninterpretedBlock(string* value);
|
||||
|
||||
// =================================================================
|
||||
|
||||
io::Tokenizer* input_;
|
||||
io::ErrorCollector* error_collector_;
|
||||
SourceCodeInfo* source_code_info_;
|
||||
SourceLocationTable* source_location_table_; // legacy
|
||||
bool had_errors_;
|
||||
bool require_syntax_identifier_;
|
||||
bool stop_after_syntax_identifier_;
|
||||
string syntax_identifier_;
|
||||
|
||||
// Leading doc comments for the next declaration. These are not complete
|
||||
// yet; use ConsumeEndOfDeclaration() to get the complete comments.
|
||||
string upcoming_doc_comments_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
|
||||
};
|
||||
|
||||
// A table mapping (descriptor, ErrorLocation) pairs -- as reported by
|
||||
// DescriptorPool when validating descriptors -- to line and column numbers
|
||||
// within the original source code.
|
||||
//
|
||||
// This is semi-obsolete: FileDescriptorProto.source_code_info now contains
|
||||
// far more complete information about source locations. However, as of this
|
||||
// writing you still need to use SourceLocationTable when integrating with
|
||||
// DescriptorPool.
|
||||
class LIBPROTOBUF_EXPORT SourceLocationTable {
|
||||
public:
|
||||
SourceLocationTable();
|
||||
~SourceLocationTable();
|
||||
|
||||
// Finds the precise location of the given error and fills in *line and
|
||||
// *column with the line and column numbers. If not found, sets *line to
|
||||
// -1 and *column to 0 (since line = -1 is used to mean "error has no exact
|
||||
// location" in the ErrorCollector interface). Returns true if found, false
|
||||
// otherwise.
|
||||
bool Find(const Message* descriptor,
|
||||
DescriptorPool::ErrorCollector::ErrorLocation location,
|
||||
int* line, int* column) const;
|
||||
|
||||
// Adds a location to the table.
|
||||
void Add(const Message* descriptor,
|
||||
DescriptorPool::ErrorCollector::ErrorLocation location,
|
||||
int line, int column);
|
||||
|
||||
// Clears the contents of the table.
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
typedef map<
|
||||
pair<const Message*, DescriptorPool::ErrorCollector::ErrorLocation>,
|
||||
pair<int, int> > LocationMap;
|
||||
LocationMap location_map_;
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_PARSER_H__
|
|
@ -0,0 +1,72 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// Front-end for protoc code generator plugins written in C++.
|
||||
//
|
||||
// To implement a protoc plugin in C++, simply write an implementation of
|
||||
// CodeGenerator, then create a main() function like:
|
||||
// int main(int argc, char* argv[]) {
|
||||
// MyCodeGenerator generator;
|
||||
// return google::protobuf::compiler::PluginMain(argc, argv, &generator);
|
||||
// }
|
||||
// You must link your plugin against libprotobuf and libprotoc.
|
||||
//
|
||||
// To get protoc to use the plugin, do one of the following:
|
||||
// * Place the plugin binary somewhere in the PATH and give it the name
|
||||
// "protoc-gen-NAME" (replacing "NAME" with the name of your plugin). If you
|
||||
// then invoke protoc with the parameter --NAME_out=OUT_DIR (again, replace
|
||||
// "NAME" with your plugin's name), protoc will invoke your plugin to generate
|
||||
// the output, which will be placed in OUT_DIR.
|
||||
// * Place the plugin binary anywhere, with any name, and pass the --plugin
|
||||
// parameter to protoc to direct it to your plugin like so:
|
||||
// protoc --plugin=protoc-gen-NAME=path/to/mybinary --NAME_out=OUT_DIR
|
||||
// On Windows, make sure to include the .exe suffix:
|
||||
// protoc --plugin=protoc-gen-NAME=path/to/mybinary.exe --NAME_out=OUT_DIR
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
|
||||
class CodeGenerator; // code_generator.h
|
||||
|
||||
// Implements main() for a protoc plugin exposing the given code generator.
|
||||
LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
|
|
@ -0,0 +1,166 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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: robinson@google.com (Will Robinson)
|
||||
//
|
||||
// Generates Python code for a given .proto file.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Descriptor;
|
||||
class EnumDescriptor;
|
||||
class EnumValueDescriptor;
|
||||
class FieldDescriptor;
|
||||
class ServiceDescriptor;
|
||||
|
||||
namespace io { class Printer; }
|
||||
|
||||
namespace compiler {
|
||||
namespace python {
|
||||
|
||||
// CodeGenerator implementation for generated Python protocol buffer classes.
|
||||
// If you create your own protocol compiler binary and you want it to support
|
||||
// Python output, you can do so by registering an instance of this
|
||||
// CodeGenerator with the CommandLineInterface in your main() function.
|
||||
class LIBPROTOC_EXPORT Generator : public CodeGenerator {
|
||||
public:
|
||||
Generator();
|
||||
virtual ~Generator();
|
||||
|
||||
// CodeGenerator methods.
|
||||
virtual bool Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const;
|
||||
|
||||
private:
|
||||
void PrintImports() const;
|
||||
void PrintFileDescriptor() const;
|
||||
void PrintTopLevelEnums() const;
|
||||
void PrintAllNestedEnumsInFile() const;
|
||||
void PrintNestedEnums(const Descriptor& descriptor) const;
|
||||
void PrintEnum(const EnumDescriptor& enum_descriptor) const;
|
||||
|
||||
void PrintTopLevelExtensions() const;
|
||||
|
||||
void PrintFieldDescriptor(
|
||||
const FieldDescriptor& field, bool is_extension) const;
|
||||
void PrintFieldDescriptorsInDescriptor(
|
||||
const Descriptor& message_descriptor,
|
||||
bool is_extension,
|
||||
const string& list_variable_name,
|
||||
int (Descriptor::*CountFn)() const,
|
||||
const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const;
|
||||
void PrintFieldsInDescriptor(const Descriptor& message_descriptor) const;
|
||||
void PrintExtensionsInDescriptor(const Descriptor& message_descriptor) const;
|
||||
void PrintMessageDescriptors() const;
|
||||
void PrintDescriptor(const Descriptor& message_descriptor) const;
|
||||
void PrintNestedDescriptors(const Descriptor& containing_descriptor) const;
|
||||
|
||||
void PrintMessages() const;
|
||||
void PrintMessage(const Descriptor& message_descriptor, const string& prefix,
|
||||
vector<string>* to_register) const;
|
||||
void PrintNestedMessages(const Descriptor& containing_descriptor,
|
||||
const string& prefix,
|
||||
vector<string>* to_register) const;
|
||||
|
||||
void FixForeignFieldsInDescriptors() const;
|
||||
void FixForeignFieldsInDescriptor(
|
||||
const Descriptor& descriptor,
|
||||
const Descriptor* containing_descriptor) const;
|
||||
void FixForeignFieldsInField(const Descriptor* containing_type,
|
||||
const FieldDescriptor& field,
|
||||
const string& python_dict_name) const;
|
||||
void AddMessageToFileDescriptor(const Descriptor& descriptor) const;
|
||||
void AddEnumToFileDescriptor(const EnumDescriptor& descriptor) const;
|
||||
void AddExtensionToFileDescriptor(const FieldDescriptor& descriptor) const;
|
||||
string FieldReferencingExpression(const Descriptor* containing_type,
|
||||
const FieldDescriptor& field,
|
||||
const string& python_dict_name) const;
|
||||
template <typename DescriptorT>
|
||||
void FixContainingTypeInDescriptor(
|
||||
const DescriptorT& descriptor,
|
||||
const Descriptor* containing_descriptor) const;
|
||||
|
||||
void FixForeignFieldsInExtensions() const;
|
||||
void FixForeignFieldsInExtension(
|
||||
const FieldDescriptor& extension_field) const;
|
||||
void FixForeignFieldsInNestedExtensions(const Descriptor& descriptor) const;
|
||||
|
||||
void PrintServices() const;
|
||||
void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const;
|
||||
void PrintServiceClass(const ServiceDescriptor& descriptor) const;
|
||||
void PrintServiceStub(const ServiceDescriptor& descriptor) const;
|
||||
|
||||
void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const;
|
||||
string OptionsValue(const string& class_name,
|
||||
const string& serialized_options) const;
|
||||
bool GeneratingDescriptorProto() const;
|
||||
|
||||
template <typename DescriptorT>
|
||||
string ModuleLevelDescriptorName(const DescriptorT& descriptor) const;
|
||||
string ModuleLevelMessageName(const Descriptor& descriptor) const;
|
||||
string ModuleLevelServiceDescriptorName(
|
||||
const ServiceDescriptor& descriptor) const;
|
||||
|
||||
template <typename DescriptorT, typename DescriptorProtoT>
|
||||
void PrintSerializedPbInterval(
|
||||
const DescriptorT& descriptor, DescriptorProtoT& proto) const;
|
||||
|
||||
void FixAllDescriptorOptions() const;
|
||||
void FixOptionsForField(const FieldDescriptor& field) const;
|
||||
void FixOptionsForEnum(const EnumDescriptor& descriptor) const;
|
||||
void FixOptionsForMessage(const Descriptor& descriptor) const;
|
||||
|
||||
// Very coarse-grained lock to ensure that Generate() is reentrant.
|
||||
// Guards file_, printer_ and file_descriptor_serialized_.
|
||||
mutable Mutex mutex_;
|
||||
mutable const FileDescriptor* file_; // Set in Generate(). Under mutex_.
|
||||
mutable string file_descriptor_serialized_;
|
||||
mutable io::Printer* printer_; // Set in Generate(). Under mutex_.
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator);
|
||||
};
|
||||
|
||||
} // namespace python
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,369 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Interface for manipulating databases of descriptors.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
|
||||
#define GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Defined in this file.
|
||||
class DescriptorDatabase;
|
||||
class SimpleDescriptorDatabase;
|
||||
class EncodedDescriptorDatabase;
|
||||
class DescriptorPoolDatabase;
|
||||
class MergedDescriptorDatabase;
|
||||
|
||||
// Abstract interface for a database of descriptors.
|
||||
//
|
||||
// This is useful if you want to create a DescriptorPool which loads
|
||||
// descriptors on-demand from some sort of large database. If the database
|
||||
// is large, it may be inefficient to enumerate every .proto file inside it
|
||||
// calling DescriptorPool::BuildFile() for each one. Instead, a DescriptorPool
|
||||
// can be created which wraps a DescriptorDatabase and only builds particular
|
||||
// descriptors when they are needed.
|
||||
class LIBPROTOBUF_EXPORT DescriptorDatabase {
|
||||
public:
|
||||
inline DescriptorDatabase() {}
|
||||
virtual ~DescriptorDatabase();
|
||||
|
||||
// Find a file by file name. Fills in in *output and returns true if found.
|
||||
// Otherwise, returns false, leaving the contents of *output undefined.
|
||||
virtual bool FindFileByName(const string& filename,
|
||||
FileDescriptorProto* output) = 0;
|
||||
|
||||
// Find the file that declares the given fully-qualified symbol name.
|
||||
// If found, fills in *output and returns true, otherwise returns false
|
||||
// and leaves *output undefined.
|
||||
virtual bool FindFileContainingSymbol(const string& symbol_name,
|
||||
FileDescriptorProto* output) = 0;
|
||||
|
||||
// Find the file which defines an extension extending the given message type
|
||||
// with the given field number. If found, fills in *output and returns true,
|
||||
// otherwise returns false and leaves *output undefined. containing_type
|
||||
// must be a fully-qualified type name.
|
||||
virtual bool FindFileContainingExtension(const string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output) = 0;
|
||||
|
||||
// Finds the tag numbers used by all known extensions of
|
||||
// extendee_type, and appends them to output in an undefined
|
||||
// order. This method is best-effort: it's not guaranteed that the
|
||||
// database will find all extensions, and it's not guaranteed that
|
||||
// FindFileContainingExtension will return true on all of the found
|
||||
// numbers. Returns true if the search was successful, otherwise
|
||||
// returns false and leaves output unchanged.
|
||||
//
|
||||
// This method has a default implementation that always returns
|
||||
// false.
|
||||
virtual bool FindAllExtensionNumbers(const string& /* extendee_type */,
|
||||
vector<int>* /* output */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase);
|
||||
};
|
||||
|
||||
// A DescriptorDatabase into which you can insert files manually.
|
||||
//
|
||||
// FindFileContainingSymbol() is fully-implemented. When you add a file, its
|
||||
// symbols will be indexed for this purpose. Note that the implementation
|
||||
// may return false positives, but only if it isn't possible for the symbol
|
||||
// to be defined in any other file. In particular, if a file defines a symbol
|
||||
// "Foo", then searching for "Foo.[anything]" will match that file. This way,
|
||||
// the database does not need to aggressively index all children of a symbol.
|
||||
//
|
||||
// FindFileContainingExtension() is mostly-implemented. It works if and only
|
||||
// if the original FieldDescriptorProto defining the extension has a
|
||||
// fully-qualified type name in its "extendee" field (i.e. starts with a '.').
|
||||
// If the extendee is a relative name, SimpleDescriptorDatabase will not
|
||||
// attempt to resolve the type, so it will not know what type the extension is
|
||||
// extending. Therefore, calling FindFileContainingExtension() with the
|
||||
// extension's containing type will never actually find that extension. Note
|
||||
// that this is an unlikely problem, as all FileDescriptorProtos created by the
|
||||
// protocol compiler (as well as ones created by calling
|
||||
// FileDescriptor::CopyTo()) will always use fully-qualified names for all
|
||||
// types. You only need to worry if you are constructing FileDescriptorProtos
|
||||
// yourself, or are calling compiler::Parser directly.
|
||||
class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
SimpleDescriptorDatabase();
|
||||
~SimpleDescriptorDatabase();
|
||||
|
||||
// Adds the FileDescriptorProto to the database, making a copy. The object
|
||||
// can be deleted after Add() returns. Returns false if the file conflicted
|
||||
// with a file already in the database, in which case an error will have
|
||||
// been written to GOOGLE_LOG(ERROR).
|
||||
bool Add(const FileDescriptorProto& file);
|
||||
|
||||
// Adds the FileDescriptorProto to the database and takes ownership of it.
|
||||
bool AddAndOwn(const FileDescriptorProto* file);
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const string& filename,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingSymbol(const string& symbol_name,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingExtension(const string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output);
|
||||
bool FindAllExtensionNumbers(const string& extendee_type,
|
||||
vector<int>* output);
|
||||
|
||||
private:
|
||||
// So that it can use DescriptorIndex.
|
||||
friend class EncodedDescriptorDatabase;
|
||||
|
||||
// An index mapping file names, symbol names, and extension numbers to
|
||||
// some sort of values.
|
||||
template <typename Value>
|
||||
class DescriptorIndex {
|
||||
public:
|
||||
// Helpers to recursively add particular descriptors and all their contents
|
||||
// to the index.
|
||||
bool AddFile(const FileDescriptorProto& file,
|
||||
Value value);
|
||||
bool AddSymbol(const string& name, Value value);
|
||||
bool AddNestedExtensions(const DescriptorProto& message_type,
|
||||
Value value);
|
||||
bool AddExtension(const FieldDescriptorProto& field,
|
||||
Value value);
|
||||
|
||||
Value FindFile(const string& filename);
|
||||
Value FindSymbol(const string& name);
|
||||
Value FindExtension(const string& containing_type, int field_number);
|
||||
bool FindAllExtensionNumbers(const string& containing_type,
|
||||
vector<int>* output);
|
||||
|
||||
private:
|
||||
map<string, Value> by_name_;
|
||||
map<string, Value> by_symbol_;
|
||||
map<pair<string, int>, Value> by_extension_;
|
||||
|
||||
// Invariant: The by_symbol_ map does not contain any symbols which are
|
||||
// prefixes of other symbols in the map. For example, "foo.bar" is a
|
||||
// prefix of "foo.bar.baz" (but is not a prefix of "foo.barbaz").
|
||||
//
|
||||
// This invariant is important because it means that given a symbol name,
|
||||
// we can find a key in the map which is a prefix of the symbol in O(lg n)
|
||||
// time, and we know that there is at most one such key.
|
||||
//
|
||||
// The prefix lookup algorithm works like so:
|
||||
// 1) Find the last key in the map which is less than or equal to the
|
||||
// search key.
|
||||
// 2) If the found key is a prefix of the search key, then return it.
|
||||
// Otherwise, there is no match.
|
||||
//
|
||||
// I am sure this algorithm has been described elsewhere, but since I
|
||||
// wasn't able to find it quickly I will instead prove that it works
|
||||
// myself. The key to the algorithm is that if a match exists, step (1)
|
||||
// will find it. Proof:
|
||||
// 1) Define the "search key" to be the key we are looking for, the "found
|
||||
// key" to be the key found in step (1), and the "match key" to be the
|
||||
// key which actually matches the serach key (i.e. the key we're trying
|
||||
// to find).
|
||||
// 2) The found key must be less than or equal to the search key by
|
||||
// definition.
|
||||
// 3) The match key must also be less than or equal to the search key
|
||||
// (because it is a prefix).
|
||||
// 4) The match key cannot be greater than the found key, because if it
|
||||
// were, then step (1) of the algorithm would have returned the match
|
||||
// key instead (since it finds the *greatest* key which is less than or
|
||||
// equal to the search key).
|
||||
// 5) Therefore, the found key must be between the match key and the search
|
||||
// key, inclusive.
|
||||
// 6) Since the search key must be a sub-symbol of the match key, if it is
|
||||
// not equal to the match key, then search_key[match_key.size()] must
|
||||
// be '.'.
|
||||
// 7) Since '.' sorts before any other character that is valid in a symbol
|
||||
// name, then if the found key is not equal to the match key, then
|
||||
// found_key[match_key.size()] must also be '.', because any other value
|
||||
// would make it sort after the search key.
|
||||
// 8) Therefore, if the found key is not equal to the match key, then the
|
||||
// found key must be a sub-symbol of the match key. However, this would
|
||||
// contradict our map invariant which says that no symbol in the map is
|
||||
// a sub-symbol of any other.
|
||||
// 9) Therefore, the found key must match the match key.
|
||||
//
|
||||
// The above proof assumes the match key exists. In the case that the
|
||||
// match key does not exist, then step (1) will return some other symbol.
|
||||
// That symbol cannot be a super-symbol of the search key since if it were,
|
||||
// then it would be a match, and we're assuming the match key doesn't exist.
|
||||
// Therefore, step 2 will correctly return no match.
|
||||
|
||||
// Find the last entry in the by_symbol_ map whose key is less than or
|
||||
// equal to the given name.
|
||||
typename map<string, Value>::iterator FindLastLessOrEqual(
|
||||
const string& name);
|
||||
|
||||
// True if either the arguments are equal or super_symbol identifies a
|
||||
// parent symbol of sub_symbol (e.g. "foo.bar" is a parent of
|
||||
// "foo.bar.baz", but not a parent of "foo.barbaz").
|
||||
bool IsSubSymbol(const string& sub_symbol, const string& super_symbol);
|
||||
|
||||
// Returns true if and only if all characters in the name are alphanumerics,
|
||||
// underscores, or periods.
|
||||
bool ValidateSymbolName(const string& name);
|
||||
};
|
||||
|
||||
|
||||
DescriptorIndex<const FileDescriptorProto*> index_;
|
||||
vector<const FileDescriptorProto*> files_to_delete_;
|
||||
|
||||
// If file is non-NULL, copy it into *output and return true, otherwise
|
||||
// return false.
|
||||
bool MaybeCopy(const FileDescriptorProto* file,
|
||||
FileDescriptorProto* output);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleDescriptorDatabase);
|
||||
};
|
||||
|
||||
// Very similar to SimpleDescriptorDatabase, but stores all the descriptors
|
||||
// as raw bytes and generally tries to use as little memory as possible.
|
||||
//
|
||||
// The same caveats regarding FindFileContainingExtension() apply as with
|
||||
// SimpleDescriptorDatabase.
|
||||
class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
EncodedDescriptorDatabase();
|
||||
~EncodedDescriptorDatabase();
|
||||
|
||||
// Adds the FileDescriptorProto to the database. The descriptor is provided
|
||||
// in encoded form. The database does not make a copy of the bytes, nor
|
||||
// does it take ownership; it's up to the caller to make sure the bytes
|
||||
// remain valid for the life of the database. Returns false and logs an error
|
||||
// if the bytes are not a valid FileDescriptorProto or if the file conflicted
|
||||
// with a file already in the database.
|
||||
bool Add(const void* encoded_file_descriptor, int size);
|
||||
|
||||
// Like Add(), but makes a copy of the data, so that the caller does not
|
||||
// need to keep it around.
|
||||
bool AddCopy(const void* encoded_file_descriptor, int size);
|
||||
|
||||
// Like FindFileContainingSymbol but returns only the name of the file.
|
||||
bool FindNameOfFileContainingSymbol(const string& symbol_name,
|
||||
string* output);
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const string& filename,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingSymbol(const string& symbol_name,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingExtension(const string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output);
|
||||
bool FindAllExtensionNumbers(const string& extendee_type,
|
||||
vector<int>* output);
|
||||
|
||||
private:
|
||||
SimpleDescriptorDatabase::DescriptorIndex<pair<const void*, int> > index_;
|
||||
vector<void*> files_to_delete_;
|
||||
|
||||
// If encoded_file.first is non-NULL, parse the data into *output and return
|
||||
// true, otherwise return false.
|
||||
bool MaybeParse(pair<const void*, int> encoded_file,
|
||||
FileDescriptorProto* output);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EncodedDescriptorDatabase);
|
||||
};
|
||||
|
||||
// A DescriptorDatabase that fetches files from a given pool.
|
||||
class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
DescriptorPoolDatabase(const DescriptorPool& pool);
|
||||
~DescriptorPoolDatabase();
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const string& filename,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingSymbol(const string& symbol_name,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingExtension(const string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output);
|
||||
bool FindAllExtensionNumbers(const string& extendee_type,
|
||||
vector<int>* output);
|
||||
|
||||
private:
|
||||
const DescriptorPool& pool_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPoolDatabase);
|
||||
};
|
||||
|
||||
// A DescriptorDatabase that wraps two or more others. It first searches the
|
||||
// first database and, if that fails, tries the second, and so on.
|
||||
class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
|
||||
public:
|
||||
// Merge just two databases. The sources remain property of the caller.
|
||||
MergedDescriptorDatabase(DescriptorDatabase* source1,
|
||||
DescriptorDatabase* source2);
|
||||
// Merge more than two databases. The sources remain property of the caller.
|
||||
// The vector may be deleted after the constructor returns but the
|
||||
// DescriptorDatabases need to stick around.
|
||||
MergedDescriptorDatabase(const vector<DescriptorDatabase*>& sources);
|
||||
~MergedDescriptorDatabase();
|
||||
|
||||
// implements DescriptorDatabase -----------------------------------
|
||||
bool FindFileByName(const string& filename,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingSymbol(const string& symbol_name,
|
||||
FileDescriptorProto* output);
|
||||
bool FindFileContainingExtension(const string& containing_type,
|
||||
int field_number,
|
||||
FileDescriptorProto* output);
|
||||
// Merges the results of calling all databases. Returns true iff any
|
||||
// of the databases returned true.
|
||||
bool FindAllExtensionNumbers(const string& extendee_type,
|
||||
vector<int>* output);
|
||||
|
||||
|
||||
private:
|
||||
vector<DescriptorDatabase*> sources_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MergedDescriptorDatabase);
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
|
|
@ -0,0 +1,148 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Defines an implementation of Message which can emulate types which are not
|
||||
// known at compile-time.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
|
||||
#define GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Defined in other files.
|
||||
class Descriptor; // descriptor.h
|
||||
class DescriptorPool; // descriptor.h
|
||||
|
||||
// Constructs implementations of Message which can emulate types which are not
|
||||
// known at compile-time.
|
||||
//
|
||||
// Sometimes you want to be able to manipulate protocol types that you don't
|
||||
// know about at compile time. It would be nice to be able to construct
|
||||
// a Message object which implements the message type given by any arbitrary
|
||||
// Descriptor. DynamicMessage provides this.
|
||||
//
|
||||
// As it turns out, a DynamicMessage needs to construct extra
|
||||
// information about its type in order to operate. Most of this information
|
||||
// can be shared between all DynamicMessages of the same type. But, caching
|
||||
// this information in some sort of global map would be a bad idea, since
|
||||
// the cached information for a particular descriptor could outlive the
|
||||
// descriptor itself. To avoid this problem, DynamicMessageFactory
|
||||
// encapsulates this "cache". All DynamicMessages of the same type created
|
||||
// from the same factory will share the same support data. Any Descriptors
|
||||
// used with a particular factory must outlive the factory.
|
||||
class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
|
||||
public:
|
||||
// Construct a DynamicMessageFactory that will search for extensions in
|
||||
// the DescriptorPool in which the extendee is defined.
|
||||
DynamicMessageFactory();
|
||||
|
||||
// Construct a DynamicMessageFactory that will search for extensions in
|
||||
// the given DescriptorPool.
|
||||
//
|
||||
// DEPRECATED: Use CodedInputStream::SetExtensionRegistry() to tell the
|
||||
// parser to look for extensions in an alternate pool. However, note that
|
||||
// this is almost never what you want to do. Almost all users should use
|
||||
// the zero-arg constructor.
|
||||
DynamicMessageFactory(const DescriptorPool* pool);
|
||||
|
||||
~DynamicMessageFactory();
|
||||
|
||||
// Call this to tell the DynamicMessageFactory that if it is given a
|
||||
// Descriptor d for which:
|
||||
// d->file()->pool() == DescriptorPool::generated_pool(),
|
||||
// then it should delegate to MessageFactory::generated_factory() instead
|
||||
// of constructing a dynamic implementation of the message. In theory there
|
||||
// is no down side to doing this, so it may become the default in the future.
|
||||
void SetDelegateToGeneratedFactory(bool enable) {
|
||||
delegate_to_generated_factory_ = enable;
|
||||
}
|
||||
|
||||
// implements MessageFactory ---------------------------------------
|
||||
|
||||
// Given a Descriptor, constructs the default (prototype) Message of that
|
||||
// type. You can then call that message's New() method to construct a
|
||||
// mutable message of that type.
|
||||
//
|
||||
// Calling this method twice with the same Descriptor returns the same
|
||||
// object. The returned object remains property of the factory and will
|
||||
// be destroyed when the factory is destroyed. Also, any objects created
|
||||
// by calling the prototype's New() method share some data with the
|
||||
// prototype, so these must be destroyed before the DynamicMessageFactory
|
||||
// is destroyed.
|
||||
//
|
||||
// The given descriptor must outlive the returned message, and hence must
|
||||
// outlive the DynamicMessageFactory.
|
||||
//
|
||||
// The method is thread-safe.
|
||||
const Message* GetPrototype(const Descriptor* type);
|
||||
|
||||
private:
|
||||
const DescriptorPool* pool_;
|
||||
bool delegate_to_generated_factory_;
|
||||
|
||||
// This struct just contains a hash_map. We can't #include <google/protobuf/stubs/hash.h> from
|
||||
// this header due to hacks needed for hash_map portability in the open source
|
||||
// release. Namely, stubs/hash.h, which defines hash_map portably, is not a
|
||||
// public header (for good reason), but dynamic_message.h is, and public
|
||||
// headers may only #include other public headers.
|
||||
struct PrototypeMap;
|
||||
scoped_ptr<PrototypeMap> prototypes_;
|
||||
mutable Mutex prototypes_mutex_;
|
||||
|
||||
friend class DynamicMessage;
|
||||
const Message* GetPrototypeNoLock(const Descriptor* type);
|
||||
|
||||
// Construct default oneof instance for reflection usage if oneof
|
||||
// is defined.
|
||||
static void ConstructDefaultOneofInstance(const Descriptor* type,
|
||||
const int offsets[],
|
||||
void* default_oneof_instance);
|
||||
// Delete default oneof instance. Called by ~DynamicMessageFactory.
|
||||
static void DeleteDefaultOneofInstance(const Descriptor* type,
|
||||
const int offsets[],
|
||||
void* default_oneof_instance);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory);
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,91 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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: jasonh@google.com (Jason Hsueh)
|
||||
//
|
||||
// This header is logically internal, but is made public because it is used
|
||||
// from protocol-compiler-generated code, which may reside in other components.
|
||||
// It provides reflection support for generated enums, and is included in
|
||||
// generated .pb.h files and should have minimal dependencies. The methods are
|
||||
// implemented in generated_message_reflection.cc.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/template_util.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class EnumDescriptor;
|
||||
} // namespace protobuf
|
||||
|
||||
namespace protobuf {
|
||||
|
||||
// This type trait can be used to cause templates to only match proto2 enum
|
||||
// types.
|
||||
template <typename T> struct is_proto_enum : ::google::protobuf::internal::false_type {};
|
||||
|
||||
// Returns the EnumDescriptor for enum type E, which must be a
|
||||
// proto-declared enum type. Code generated by the protocol compiler
|
||||
// will include specializations of this template for each enum type declared.
|
||||
template <typename E>
|
||||
const EnumDescriptor* GetEnumDescriptor();
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Helper for EnumType_Parse functions: try to parse the string 'name' as an
|
||||
// enum name of the given type, returning true and filling in value on success,
|
||||
// or returning false and leaving value unchanged on failure.
|
||||
LIBPROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor,
|
||||
const string& name,
|
||||
int* value);
|
||||
|
||||
template<typename EnumType>
|
||||
bool ParseNamedEnum(const EnumDescriptor* descriptor,
|
||||
const string& name,
|
||||
EnumType* value) {
|
||||
int tmp;
|
||||
if (!ParseNamedEnum(descriptor, name, &tmp)) return false;
|
||||
*value = static_cast<EnumType>(tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Just a wrapper around printing the name of a value. The main point of this
|
||||
// function is not to be inlined, so that you can do this without including
|
||||
// descriptor.h.
|
||||
LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
|
|
@ -0,0 +1,504 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// This header is logically internal, but is made public because it is used
|
||||
// from protocol-compiler-generated code, which may reside in other components.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
// TODO(jasonh): Remove this once the compiler change to directly include this
|
||||
// is released to components.
|
||||
#include <google/protobuf/generated_enum_reflection.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace upb {
|
||||
namespace google_opensource {
|
||||
class GMR_Handlers;
|
||||
} // namespace google_opensource
|
||||
} // namespace upb
|
||||
|
||||
namespace protobuf {
|
||||
class DescriptorPool;
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
class DefaultEmptyOneof;
|
||||
|
||||
// Defined in this file.
|
||||
class GeneratedMessageReflection;
|
||||
|
||||
// Defined in other files.
|
||||
class ExtensionSet; // extension_set.h
|
||||
|
||||
// THIS CLASS IS NOT INTENDED FOR DIRECT USE. It is intended for use
|
||||
// by generated code. This class is just a big hack that reduces code
|
||||
// size.
|
||||
//
|
||||
// A GeneratedMessageReflection is an implementation of Reflection
|
||||
// which expects all fields to be backed by simple variables located in
|
||||
// memory. The locations are given using a base pointer and a set of
|
||||
// offsets.
|
||||
//
|
||||
// It is required that the user represents fields of each type in a standard
|
||||
// way, so that GeneratedMessageReflection can cast the void* pointer to
|
||||
// the appropriate type. For primitive fields and string fields, each field
|
||||
// should be represented using the obvious C++ primitive type. Enums and
|
||||
// Messages are different:
|
||||
// - Singular Message fields are stored as a pointer to a Message. These
|
||||
// should start out NULL, except for in the default instance where they
|
||||
// should start out pointing to other default instances.
|
||||
// - Enum fields are stored as an int. This int must always contain
|
||||
// a valid value, such that EnumDescriptor::FindValueByNumber() would
|
||||
// not return NULL.
|
||||
// - Repeated fields are stored as RepeatedFields or RepeatedPtrFields
|
||||
// of whatever type the individual field would be. Strings and
|
||||
// Messages use RepeatedPtrFields while everything else uses
|
||||
// RepeatedFields.
|
||||
class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
|
||||
public:
|
||||
// Constructs a GeneratedMessageReflection.
|
||||
// Parameters:
|
||||
// descriptor: The descriptor for the message type being implemented.
|
||||
// default_instance: The default instance of the message. This is only
|
||||
// used to obtain pointers to default instances of embedded
|
||||
// messages, which GetMessage() will return if the particular
|
||||
// sub-message has not been initialized yet. (Thus, all
|
||||
// embedded message fields *must* have non-NULL pointers
|
||||
// in the default instance.)
|
||||
// offsets: An array of ints giving the byte offsets, relative to
|
||||
// the start of the message object, of each field. These can
|
||||
// be computed at compile time using the
|
||||
// GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET() macro, defined
|
||||
// below.
|
||||
// has_bits_offset: Offset in the message of an array of uint32s of size
|
||||
// descriptor->field_count()/32, rounded up. This is a
|
||||
// bitfield where each bit indicates whether or not the
|
||||
// corresponding field of the message has been initialized.
|
||||
// The bit for field index i is obtained by the expression:
|
||||
// has_bits[i / 32] & (1 << (i % 32))
|
||||
// unknown_fields_offset: Offset in the message of the UnknownFieldSet for
|
||||
// the message.
|
||||
// extensions_offset: Offset in the message of the ExtensionSet for the
|
||||
// message, or -1 if the message type has no extension
|
||||
// ranges.
|
||||
// pool: DescriptorPool to search for extension definitions. Only
|
||||
// used by FindKnownExtensionByName() and
|
||||
// FindKnownExtensionByNumber().
|
||||
// factory: MessageFactory to use to construct extension messages.
|
||||
// object_size: The size of a message object of this type, as measured
|
||||
// by sizeof().
|
||||
GeneratedMessageReflection(const Descriptor* descriptor,
|
||||
const Message* default_instance,
|
||||
const int offsets[],
|
||||
int has_bits_offset,
|
||||
int unknown_fields_offset,
|
||||
int extensions_offset,
|
||||
const DescriptorPool* pool,
|
||||
MessageFactory* factory,
|
||||
int object_size);
|
||||
|
||||
// Similar with the construction above. Call this construction if the
|
||||
// message has oneof definition.
|
||||
// Parameters:
|
||||
// offsets: An array of ints giving the byte offsets.
|
||||
// For each oneof field, the offset is relative to the
|
||||
// default_oneof_instance. These can be computed at compile
|
||||
// time using the
|
||||
// PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET() macro.
|
||||
// For each none oneof field, the offset is related to
|
||||
// the start of the message object. These can be computed
|
||||
// at compile time using the
|
||||
// GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET() macro.
|
||||
// Besides offsets for all fields, this array also contains
|
||||
// offsets for oneof unions. The offset of the i-th oneof
|
||||
// union is offsets[descriptor->field_count() + i].
|
||||
// default_oneof_instance: The default instance of the oneofs. It is a
|
||||
// struct holding the default value of all oneof fields
|
||||
// for this message. It is only used to obtain pointers
|
||||
// to default instances of oneof fields, which Get
|
||||
// methods will return if the field is not set.
|
||||
// oneof_case_offset: Offset in the message of an array of uint32s of
|
||||
// size descriptor->oneof_decl_count(). Each uint32
|
||||
// indicates what field is set for each oneof.
|
||||
// other parameters are the same with the construction above.
|
||||
GeneratedMessageReflection(const Descriptor* descriptor,
|
||||
const Message* default_instance,
|
||||
const int offsets[],
|
||||
int has_bits_offset,
|
||||
int unknown_fields_offset,
|
||||
int extensions_offset,
|
||||
const void* default_oneof_instance,
|
||||
int oneof_case_offset,
|
||||
const DescriptorPool* pool,
|
||||
MessageFactory* factory,
|
||||
int object_size);
|
||||
~GeneratedMessageReflection();
|
||||
|
||||
// implements Reflection -------------------------------------------
|
||||
|
||||
const UnknownFieldSet& GetUnknownFields(const Message& message) const;
|
||||
UnknownFieldSet* MutableUnknownFields(Message* message) const;
|
||||
|
||||
int SpaceUsed(const Message& message) const;
|
||||
|
||||
bool HasField(const Message& message, const FieldDescriptor* field) const;
|
||||
int FieldSize(const Message& message, const FieldDescriptor* field) const;
|
||||
void ClearField(Message* message, const FieldDescriptor* field) const;
|
||||
bool HasOneof(const Message& message,
|
||||
const OneofDescriptor* oneof_descriptor) const;
|
||||
void ClearOneof(Message* message, const OneofDescriptor* field) const;
|
||||
void RemoveLast(Message* message, const FieldDescriptor* field) const;
|
||||
Message* ReleaseLast(Message* message, const FieldDescriptor* field) const;
|
||||
void Swap(Message* message1, Message* message2) const;
|
||||
void SwapFields(Message* message1, Message* message2,
|
||||
const vector<const FieldDescriptor*>& fields) const;
|
||||
void SwapElements(Message* message, const FieldDescriptor* field,
|
||||
int index1, int index2) const;
|
||||
void ListFields(const Message& message,
|
||||
vector<const FieldDescriptor*>* output) const;
|
||||
|
||||
int32 GetInt32 (const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
int64 GetInt64 (const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
uint32 GetUInt32(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
uint64 GetUInt64(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
float GetFloat (const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
double GetDouble(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
bool GetBool (const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
string GetString(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
const string& GetStringReference(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
string* scratch) const;
|
||||
const EnumValueDescriptor* GetEnum(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
const Message& GetMessage(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const;
|
||||
|
||||
const FieldDescriptor* GetOneofFieldDescriptor(
|
||||
const Message& message,
|
||||
const OneofDescriptor* oneof_descriptor) const;
|
||||
|
||||
public:
|
||||
void SetInt32 (Message* message,
|
||||
const FieldDescriptor* field, int32 value) const;
|
||||
void SetInt64 (Message* message,
|
||||
const FieldDescriptor* field, int64 value) const;
|
||||
void SetUInt32(Message* message,
|
||||
const FieldDescriptor* field, uint32 value) const;
|
||||
void SetUInt64(Message* message,
|
||||
const FieldDescriptor* field, uint64 value) const;
|
||||
void SetFloat (Message* message,
|
||||
const FieldDescriptor* field, float value) const;
|
||||
void SetDouble(Message* message,
|
||||
const FieldDescriptor* field, double value) const;
|
||||
void SetBool (Message* message,
|
||||
const FieldDescriptor* field, bool value) const;
|
||||
void SetString(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
const string& value) const;
|
||||
void SetEnum (Message* message, const FieldDescriptor* field,
|
||||
const EnumValueDescriptor* value) const;
|
||||
Message* MutableMessage(Message* message, const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const;
|
||||
void SetAllocatedMessage(Message* message,
|
||||
Message* sub_message,
|
||||
const FieldDescriptor* field) const;
|
||||
Message* ReleaseMessage(Message* message, const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const;
|
||||
|
||||
int32 GetRepeatedInt32 (const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
int64 GetRepeatedInt64 (const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
uint32 GetRepeatedUInt32(const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
uint64 GetRepeatedUInt64(const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
float GetRepeatedFloat (const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
double GetRepeatedDouble(const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
bool GetRepeatedBool (const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
string GetRepeatedString(const Message& message,
|
||||
const FieldDescriptor* field, int index) const;
|
||||
const string& GetRepeatedStringReference(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index, string* scratch) const;
|
||||
const EnumValueDescriptor* GetRepeatedEnum(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
const Message& GetRepeatedMessage(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
|
||||
// Set the value of a field.
|
||||
void SetRepeatedInt32 (Message* message,
|
||||
const FieldDescriptor* field, int index, int32 value) const;
|
||||
void SetRepeatedInt64 (Message* message,
|
||||
const FieldDescriptor* field, int index, int64 value) const;
|
||||
void SetRepeatedUInt32(Message* message,
|
||||
const FieldDescriptor* field, int index, uint32 value) const;
|
||||
void SetRepeatedUInt64(Message* message,
|
||||
const FieldDescriptor* field, int index, uint64 value) const;
|
||||
void SetRepeatedFloat (Message* message,
|
||||
const FieldDescriptor* field, int index, float value) const;
|
||||
void SetRepeatedDouble(Message* message,
|
||||
const FieldDescriptor* field, int index, double value) const;
|
||||
void SetRepeatedBool (Message* message,
|
||||
const FieldDescriptor* field, int index, bool value) const;
|
||||
void SetRepeatedString(Message* message,
|
||||
const FieldDescriptor* field, int index,
|
||||
const string& value) const;
|
||||
void SetRepeatedEnum(Message* message, const FieldDescriptor* field,
|
||||
int index, const EnumValueDescriptor* value) const;
|
||||
// Get a mutable pointer to a field with a message type.
|
||||
Message* MutableRepeatedMessage(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
|
||||
void AddInt32 (Message* message,
|
||||
const FieldDescriptor* field, int32 value) const;
|
||||
void AddInt64 (Message* message,
|
||||
const FieldDescriptor* field, int64 value) const;
|
||||
void AddUInt32(Message* message,
|
||||
const FieldDescriptor* field, uint32 value) const;
|
||||
void AddUInt64(Message* message,
|
||||
const FieldDescriptor* field, uint64 value) const;
|
||||
void AddFloat (Message* message,
|
||||
const FieldDescriptor* field, float value) const;
|
||||
void AddDouble(Message* message,
|
||||
const FieldDescriptor* field, double value) const;
|
||||
void AddBool (Message* message,
|
||||
const FieldDescriptor* field, bool value) const;
|
||||
void AddString(Message* message,
|
||||
const FieldDescriptor* field, const string& value) const;
|
||||
void AddEnum(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
const EnumValueDescriptor* value) const;
|
||||
Message* AddMessage(Message* message, const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const;
|
||||
|
||||
const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
|
||||
const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
|
||||
|
||||
protected:
|
||||
virtual void* MutableRawRepeatedField(
|
||||
Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
|
||||
int ctype, const Descriptor* desc) const;
|
||||
|
||||
private:
|
||||
friend class GeneratedMessage;
|
||||
|
||||
// To parse directly into a proto2 generated class, the class GMR_Handlers
|
||||
// needs access to member offsets and hasbits.
|
||||
friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers;
|
||||
|
||||
const Descriptor* descriptor_;
|
||||
const Message* default_instance_;
|
||||
const void* default_oneof_instance_;
|
||||
const int* offsets_;
|
||||
|
||||
int has_bits_offset_;
|
||||
int oneof_case_offset_;
|
||||
int unknown_fields_offset_;
|
||||
int extensions_offset_;
|
||||
int object_size_;
|
||||
|
||||
const DescriptorPool* descriptor_pool_;
|
||||
MessageFactory* message_factory_;
|
||||
|
||||
template <typename Type>
|
||||
inline const Type& GetRaw(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
template <typename Type>
|
||||
inline Type* MutableRaw(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
template <typename Type>
|
||||
inline const Type& DefaultRaw(const FieldDescriptor* field) const;
|
||||
template <typename Type>
|
||||
inline const Type& DefaultOneofRaw(const FieldDescriptor* field) const;
|
||||
|
||||
inline const uint32* GetHasBits(const Message& message) const;
|
||||
inline uint32* MutableHasBits(Message* message) const;
|
||||
inline uint32 GetOneofCase(
|
||||
const Message& message,
|
||||
const OneofDescriptor* oneof_descriptor) const;
|
||||
inline uint32* MutableOneofCase(
|
||||
Message* message,
|
||||
const OneofDescriptor* oneof_descriptor) const;
|
||||
inline const ExtensionSet& GetExtensionSet(const Message& message) const;
|
||||
inline ExtensionSet* MutableExtensionSet(Message* message) const;
|
||||
|
||||
inline bool HasBit(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
inline void SetBit(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
inline void ClearBit(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
inline void SwapBit(Message* message1,
|
||||
Message* message2,
|
||||
const FieldDescriptor* field) const;
|
||||
|
||||
// This function only swaps the field. Should swap corresponding has_bit
|
||||
// before or after using this function.
|
||||
void SwapField(Message* message1,
|
||||
Message* message2,
|
||||
const FieldDescriptor* field) const;
|
||||
|
||||
void SwapOneofField(Message* message1,
|
||||
Message* message2,
|
||||
const OneofDescriptor* oneof_descriptor) const;
|
||||
|
||||
inline bool HasOneofField(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
inline void SetOneofCase(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
inline void ClearOneofField(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
|
||||
template <typename Type>
|
||||
inline const Type& GetField(const Message& message,
|
||||
const FieldDescriptor* field) const;
|
||||
template <typename Type>
|
||||
inline void SetField(Message* message,
|
||||
const FieldDescriptor* field, const Type& value) const;
|
||||
template <typename Type>
|
||||
inline Type* MutableField(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
template <typename Type>
|
||||
inline const Type& GetRepeatedField(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
template <typename Type>
|
||||
inline const Type& GetRepeatedPtrField(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
template <typename Type>
|
||||
inline void SetRepeatedField(Message* message,
|
||||
const FieldDescriptor* field, int index,
|
||||
Type value) const;
|
||||
template <typename Type>
|
||||
inline Type* MutableRepeatedField(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
template <typename Type>
|
||||
inline void AddField(Message* message,
|
||||
const FieldDescriptor* field, const Type& value) const;
|
||||
template <typename Type>
|
||||
inline Type* AddField(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
|
||||
int GetExtensionNumberOrDie(const Descriptor* type) const;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratedMessageReflection);
|
||||
};
|
||||
|
||||
// Returns the offset of the given field within the given aggregate type.
|
||||
// This is equivalent to the ANSI C offsetof() macro. However, according
|
||||
// to the C++ standard, offsetof() only works on POD types, and GCC
|
||||
// enforces this requirement with a warning. In practice, this rule is
|
||||
// unnecessarily strict; there is probably no compiler or platform on
|
||||
// which the offsets of the direct fields of a class are non-constant.
|
||||
// Fields inherited from superclasses *can* have non-constant offsets,
|
||||
// but that's not what this macro will be used for.
|
||||
//
|
||||
// Note that we calculate relative to the pointer value 16 here since if we
|
||||
// just use zero, GCC complains about dereferencing a NULL pointer. We
|
||||
// choose 16 rather than some other number just in case the compiler would
|
||||
// be confused by an unaligned pointer.
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD) \
|
||||
static_cast<int>( \
|
||||
reinterpret_cast<const char*>( \
|
||||
&reinterpret_cast<const TYPE*>(16)->FIELD) - \
|
||||
reinterpret_cast<const char*>(16))
|
||||
|
||||
#define PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(ONEOF, FIELD) \
|
||||
static_cast<int>( \
|
||||
reinterpret_cast<const char*>(&(ONEOF->FIELD)) \
|
||||
- reinterpret_cast<const char*>(ONEOF))
|
||||
|
||||
// There are some places in proto2 where dynamic_cast would be useful as an
|
||||
// optimization. For example, take Message::MergeFrom(const Message& other).
|
||||
// For a given generated message FooMessage, we generate these two methods:
|
||||
// void MergeFrom(const FooMessage& other);
|
||||
// void MergeFrom(const Message& other);
|
||||
// The former method can be implemented directly in terms of FooMessage's
|
||||
// inline accessors, but the latter method must work with the reflection
|
||||
// interface. However, if the parameter to the latter method is actually of
|
||||
// type FooMessage, then we'd like to be able to just call the other method
|
||||
// as an optimization. So, we use dynamic_cast to check this.
|
||||
//
|
||||
// That said, dynamic_cast requires RTTI, which many people like to disable
|
||||
// for performance and code size reasons. When RTTI is not available, we
|
||||
// still need to produce correct results. So, in this case we have to fall
|
||||
// back to using reflection, which is what we would have done anyway if the
|
||||
// objects were not of the exact same class.
|
||||
//
|
||||
// dynamic_cast_if_available() implements this logic. If RTTI is
|
||||
// enabled, it does a dynamic_cast. If RTTI is disabled, it just returns
|
||||
// NULL.
|
||||
//
|
||||
// If you need to compile without RTTI, simply #define GOOGLE_PROTOBUF_NO_RTTI.
|
||||
// On MSVC, this should be detected automatically.
|
||||
template<typename To, typename From>
|
||||
inline To dynamic_cast_if_available(From from) {
|
||||
#if defined(GOOGLE_PROTOBUF_NO_RTTI) || (defined(_MSC_VER)&&!defined(_CPPRTTI))
|
||||
return NULL;
|
||||
#else
|
||||
return dynamic_cast<To>(from);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
|
|
@ -0,0 +1,113 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// This file contains miscellaneous helper code used by generated code --
|
||||
// including lite types -- but which should not be used directly by users.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
|
||||
// Annotation for the compiler to emit a deprecation message if a field marked
|
||||
// with option 'deprecated=true' is used in the code, or for other things in
|
||||
// generated code which are deprecated.
|
||||
//
|
||||
// For internal use in the pb.cc files, deprecation warnings are suppressed
|
||||
// there.
|
||||
#undef DEPRECATED_PROTOBUF_FIELD
|
||||
#define PROTOBUF_DEPRECATED
|
||||
|
||||
|
||||
// Constants for special floating point values.
|
||||
LIBPROTOBUF_EXPORT double Infinity();
|
||||
LIBPROTOBUF_EXPORT double NaN();
|
||||
|
||||
// TODO(jieluo): Change to template. We have tried to use template,
|
||||
// but it causes net/rpc/python:rpcutil_test fail (the empty string will
|
||||
// init twice). It may related to swig. Change to template after we
|
||||
// found the solution.
|
||||
|
||||
// Default empty string object. Don't use the pointer directly. Instead, call
|
||||
// GetEmptyString() to get the reference.
|
||||
LIBPROTOBUF_EXPORT extern const ::std::string* empty_string_;
|
||||
LIBPROTOBUF_EXPORT extern ProtobufOnceType empty_string_once_init_;
|
||||
LIBPROTOBUF_EXPORT void InitEmptyString();
|
||||
|
||||
|
||||
LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyStringAlreadyInited() {
|
||||
assert(empty_string_ != NULL);
|
||||
return *empty_string_;
|
||||
}
|
||||
LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() {
|
||||
::google::protobuf::GoogleOnceInit(&empty_string_once_init_, &InitEmptyString);
|
||||
return GetEmptyStringAlreadyInited();
|
||||
}
|
||||
|
||||
// Defined in generated_message_reflection.cc -- not actually part of the lite
|
||||
// library.
|
||||
//
|
||||
// TODO(jasonh): The various callers get this declaration from a variety of
|
||||
// places: probably in most cases repeated_field.h. Clean these up so they all
|
||||
// get the declaration from this file.
|
||||
LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
|
||||
|
||||
|
||||
// True if IsInitialized() is true for all elements of t. Type is expected
|
||||
// to be a RepeatedPtrField<some message type>. It's useful to have this
|
||||
// helper here to keep the protobuf compiler from ever having to emit loops in
|
||||
// IsInitialized() methods. We want the C++ compiler to inline this or not
|
||||
// as it sees fit.
|
||||
template <class Type> bool AllAreInitialized(const Type& t) {
|
||||
for (int i = t.size(); --i >= 0; ) {
|
||||
if (!t.Get(i).IsInitialized()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,209 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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: brianolson@google.com (Brian Olson)
|
||||
//
|
||||
// This file contains the definition for classes GzipInputStream and
|
||||
// GzipOutputStream.
|
||||
//
|
||||
// GzipInputStream decompresses data from an underlying
|
||||
// ZeroCopyInputStream and provides the decompressed data as a
|
||||
// ZeroCopyInputStream.
|
||||
//
|
||||
// GzipOutputStream is an ZeroCopyOutputStream that compresses data to
|
||||
// an underlying ZeroCopyOutputStream.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
||||
#define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// A ZeroCopyInputStream that reads compressed data through zlib
|
||||
class LIBPROTOBUF_EXPORT GzipInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Format key for constructor
|
||||
enum Format {
|
||||
// zlib will autodetect gzip header or deflate stream
|
||||
AUTO = 0,
|
||||
|
||||
// GZIP streams have some extra header data for file attributes.
|
||||
GZIP = 1,
|
||||
|
||||
// Simpler zlib stream format.
|
||||
ZLIB = 2,
|
||||
};
|
||||
|
||||
// buffer_size and format may be -1 for default of 64kB and GZIP format
|
||||
explicit GzipInputStream(
|
||||
ZeroCopyInputStream* sub_stream,
|
||||
Format format = AUTO,
|
||||
int buffer_size = -1);
|
||||
virtual ~GzipInputStream();
|
||||
|
||||
// Return last error message or NULL if no error.
|
||||
inline const char* ZlibErrorMessage() const {
|
||||
return zcontext_.msg;
|
||||
}
|
||||
inline int ZlibErrorCode() const {
|
||||
return zerror_;
|
||||
}
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
Format format_;
|
||||
|
||||
ZeroCopyInputStream* sub_stream_;
|
||||
|
||||
z_stream zcontext_;
|
||||
int zerror_;
|
||||
|
||||
void* output_buffer_;
|
||||
void* output_position_;
|
||||
size_t output_buffer_length_;
|
||||
|
||||
int Inflate(int flush);
|
||||
void DoNextOutput(const void** data, int* size);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipInputStream);
|
||||
};
|
||||
|
||||
|
||||
class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Format key for constructor
|
||||
enum Format {
|
||||
// GZIP streams have some extra header data for file attributes.
|
||||
GZIP = 1,
|
||||
|
||||
// Simpler zlib stream format.
|
||||
ZLIB = 2,
|
||||
};
|
||||
|
||||
struct Options {
|
||||
// Defaults to GZIP.
|
||||
Format format;
|
||||
|
||||
// What size buffer to use internally. Defaults to 64kB.
|
||||
int buffer_size;
|
||||
|
||||
// A number between 0 and 9, where 0 is no compression and 9 is best
|
||||
// compression. Defaults to Z_DEFAULT_COMPRESSION (see zlib.h).
|
||||
int compression_level;
|
||||
|
||||
// Defaults to Z_DEFAULT_STRATEGY. Can also be set to Z_FILTERED,
|
||||
// Z_HUFFMAN_ONLY, or Z_RLE. See the documentation for deflateInit2 in
|
||||
// zlib.h for definitions of these constants.
|
||||
int compression_strategy;
|
||||
|
||||
Options(); // Initializes with default values.
|
||||
};
|
||||
|
||||
// Create a GzipOutputStream with default options.
|
||||
explicit GzipOutputStream(ZeroCopyOutputStream* sub_stream);
|
||||
|
||||
// Create a GzipOutputStream with the given options.
|
||||
GzipOutputStream(
|
||||
ZeroCopyOutputStream* sub_stream,
|
||||
const Options& options);
|
||||
|
||||
virtual ~GzipOutputStream();
|
||||
|
||||
// Return last error message or NULL if no error.
|
||||
inline const char* ZlibErrorMessage() const {
|
||||
return zcontext_.msg;
|
||||
}
|
||||
inline int ZlibErrorCode() const {
|
||||
return zerror_;
|
||||
}
|
||||
|
||||
// Flushes data written so far to zipped data in the underlying stream.
|
||||
// It is the caller's responsibility to flush the underlying stream if
|
||||
// necessary.
|
||||
// Compression may be less efficient stopping and starting around flushes.
|
||||
// Returns true if no error.
|
||||
//
|
||||
// Please ensure that block size is > 6. Here is an excerpt from the zlib
|
||||
// doc that explains why:
|
||||
//
|
||||
// In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out
|
||||
// is greater than six to avoid repeated flush markers due to
|
||||
// avail_out == 0 on return.
|
||||
bool Flush();
|
||||
|
||||
// Writes out all data and closes the gzip stream.
|
||||
// It is the caller's responsibility to close the underlying stream if
|
||||
// necessary.
|
||||
// Returns true if no error.
|
||||
bool Close();
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
ZeroCopyOutputStream* sub_stream_;
|
||||
// Result from calling Next() on sub_stream_
|
||||
void* sub_data_;
|
||||
int sub_data_size_;
|
||||
|
||||
z_stream zcontext_;
|
||||
int zerror_;
|
||||
void* input_buffer_;
|
||||
size_t input_buffer_length_;
|
||||
|
||||
// Shared constructor code.
|
||||
void Init(ZeroCopyOutputStream* sub_stream, const Options& options);
|
||||
|
||||
// Do some compression.
|
||||
// Takes zlib flush mode.
|
||||
// Returns zlib error code.
|
||||
int Deflate(int flush);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipOutputStream);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
|
@ -0,0 +1,136 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Utility class for writing text to a ZeroCopyOutputStream.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
#define GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
class ZeroCopyOutputStream; // zero_copy_stream.h
|
||||
|
||||
// This simple utility class assists in code generation. It basically
|
||||
// allows the caller to define a set of variables and then output some
|
||||
// text with variable substitutions. Example usage:
|
||||
//
|
||||
// Printer printer(output, '$');
|
||||
// map<string, string> vars;
|
||||
// vars["name"] = "Bob";
|
||||
// printer.Print(vars, "My name is $name$.");
|
||||
//
|
||||
// The above writes "My name is Bob." to the output stream.
|
||||
//
|
||||
// Printer aggressively enforces correct usage, crashing (with assert failures)
|
||||
// in the case of undefined variables in debug builds. This helps greatly in
|
||||
// debugging code which uses it.
|
||||
class LIBPROTOBUF_EXPORT Printer {
|
||||
public:
|
||||
// Create a printer that writes text to the given output stream. Use the
|
||||
// given character as the delimiter for variables.
|
||||
Printer(ZeroCopyOutputStream* output, char variable_delimiter);
|
||||
~Printer();
|
||||
|
||||
// Print some text after applying variable substitutions. If a particular
|
||||
// variable in the text is not defined, this will crash. Variables to be
|
||||
// substituted are identified by their names surrounded by delimiter
|
||||
// characters (as given to the constructor). The variable bindings are
|
||||
// defined by the given map.
|
||||
void Print(const map<string, string>& variables, const char* text);
|
||||
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable, const string& value);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3);
|
||||
// TODO(kenton): Overloaded versions with more variables? Three seems
|
||||
// to be enough.
|
||||
|
||||
// Indent text by two spaces. After calling Indent(), two spaces will be
|
||||
// inserted at the beginning of each line of text. Indent() may be called
|
||||
// multiple times to produce deeper indents.
|
||||
void Indent();
|
||||
|
||||
// Reduces the current indent level by two spaces, or crashes if the indent
|
||||
// level is zero.
|
||||
void Outdent();
|
||||
|
||||
// Write a string to the output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void PrintRaw(const string& data);
|
||||
|
||||
// Write a zero-delimited string to output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void PrintRaw(const char* data);
|
||||
|
||||
// Write some bytes to the output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void WriteRaw(const char* data, int size);
|
||||
|
||||
// True if any write to the underlying stream failed. (We don't just
|
||||
// crash in this case because this is an I/O failure, not a programming
|
||||
// error.)
|
||||
bool failed() const { return failed_; }
|
||||
|
||||
private:
|
||||
const char variable_delimiter_;
|
||||
|
||||
ZeroCopyOutputStream* const output_;
|
||||
char* buffer_;
|
||||
int buffer_size_;
|
||||
|
||||
string indent_;
|
||||
bool at_start_of_line_;
|
||||
bool failed_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_PRINTER_H__
|
|
@ -0,0 +1,50 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
|
||||
// A locale-independent version of strtod(), used to parse floating
|
||||
// point default values in .proto files, where the decimal separator
|
||||
// is always a dot.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_STRTOD_H__
|
||||
#define GOOGLE_PROTOBUF_IO_STRTOD_H__
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// A locale-independent version of the standard strtod(), which always
|
||||
// uses a dot as the decimal separator.
|
||||
double NoLocaleStrtod(const char* str, char** endptr);
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_STRTOD_H__
|
|
@ -0,0 +1,402 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Class for parsing tokenized text from a ZeroCopyInputStream.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_TOKENIZER_H__
|
||||
#define GOOGLE_PROTOBUF_IO_TOKENIZER_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
class ZeroCopyInputStream; // zero_copy_stream.h
|
||||
|
||||
// Defined in this file.
|
||||
class ErrorCollector;
|
||||
class Tokenizer;
|
||||
|
||||
// Abstract interface for an object which collects the errors that occur
|
||||
// during parsing. A typical implementation might simply print the errors
|
||||
// to stdout.
|
||||
class LIBPROTOBUF_EXPORT ErrorCollector {
|
||||
public:
|
||||
inline ErrorCollector() {}
|
||||
virtual ~ErrorCollector();
|
||||
|
||||
// Indicates that there was an error in the input at the given line and
|
||||
// column numbers. The numbers are zero-based, so you may want to add
|
||||
// 1 to each before printing them.
|
||||
virtual void AddError(int line, int column, const string& message) = 0;
|
||||
|
||||
// Indicates that there was a warning in the input at the given line and
|
||||
// column numbers. The numbers are zero-based, so you may want to add
|
||||
// 1 to each before printing them.
|
||||
virtual void AddWarning(int /* line */, int /* column */,
|
||||
const string& /* message */) { }
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
|
||||
};
|
||||
|
||||
// This class converts a stream of raw text into a stream of tokens for
|
||||
// the protocol definition parser to parse. The tokens recognized are
|
||||
// similar to those that make up the C language; see the TokenType enum for
|
||||
// precise descriptions. Whitespace and comments are skipped. By default,
|
||||
// C- and C++-style comments are recognized, but other styles can be used by
|
||||
// calling set_comment_style().
|
||||
class LIBPROTOBUF_EXPORT Tokenizer {
|
||||
public:
|
||||
// Construct a Tokenizer that reads and tokenizes text from the given
|
||||
// input stream and writes errors to the given error_collector.
|
||||
// The caller keeps ownership of input and error_collector.
|
||||
Tokenizer(ZeroCopyInputStream* input, ErrorCollector* error_collector);
|
||||
~Tokenizer();
|
||||
|
||||
enum TokenType {
|
||||
TYPE_START, // Next() has not yet been called.
|
||||
TYPE_END, // End of input reached. "text" is empty.
|
||||
|
||||
TYPE_IDENTIFIER, // A sequence of letters, digits, and underscores, not
|
||||
// starting with a digit. It is an error for a number
|
||||
// to be followed by an identifier with no space in
|
||||
// between.
|
||||
TYPE_INTEGER, // A sequence of digits representing an integer. Normally
|
||||
// the digits are decimal, but a prefix of "0x" indicates
|
||||
// a hex number and a leading zero indicates octal, just
|
||||
// like with C numeric literals. A leading negative sign
|
||||
// is NOT included in the token; it's up to the parser to
|
||||
// interpret the unary minus operator on its own.
|
||||
TYPE_FLOAT, // A floating point literal, with a fractional part and/or
|
||||
// an exponent. Always in decimal. Again, never
|
||||
// negative.
|
||||
TYPE_STRING, // A quoted sequence of escaped characters. Either single
|
||||
// or double quotes can be used, but they must match.
|
||||
// A string literal cannot cross a line break.
|
||||
TYPE_SYMBOL, // Any other printable character, like '!' or '+'.
|
||||
// Symbols are always a single character, so "!+$%" is
|
||||
// four tokens.
|
||||
};
|
||||
|
||||
// Structure representing a token read from the token stream.
|
||||
struct Token {
|
||||
TokenType type;
|
||||
string text; // The exact text of the token as it appeared in
|
||||
// the input. e.g. tokens of TYPE_STRING will still
|
||||
// be escaped and in quotes.
|
||||
|
||||
// "line" and "column" specify the position of the first character of
|
||||
// the token within the input stream. They are zero-based.
|
||||
int line;
|
||||
int column;
|
||||
int end_column;
|
||||
};
|
||||
|
||||
// Get the current token. This is updated when Next() is called. Before
|
||||
// the first call to Next(), current() has type TYPE_START and no contents.
|
||||
const Token& current();
|
||||
|
||||
// Return the previous token -- i.e. what current() returned before the
|
||||
// previous call to Next().
|
||||
const Token& previous();
|
||||
|
||||
// Advance to the next token. Returns false if the end of the input is
|
||||
// reached.
|
||||
bool Next();
|
||||
|
||||
// Like Next(), but also collects comments which appear between the previous
|
||||
// and next tokens.
|
||||
//
|
||||
// Comments which appear to be attached to the previous token are stored
|
||||
// in *prev_tailing_comments. Comments which appear to be attached to the
|
||||
// next token are stored in *next_leading_comments. Comments appearing in
|
||||
// between which do not appear to be attached to either will be added to
|
||||
// detached_comments. Any of these parameters can be NULL to simply discard
|
||||
// the comments.
|
||||
//
|
||||
// A series of line comments appearing on consecutive lines, with no other
|
||||
// tokens appearing on those lines, will be treated as a single comment.
|
||||
//
|
||||
// Only the comment content is returned; comment markers (e.g. //) are
|
||||
// stripped out. For block comments, leading whitespace and an asterisk will
|
||||
// be stripped from the beginning of each line other than the first. Newlines
|
||||
// are included in the output.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// optional int32 foo = 1; // Comment attached to foo.
|
||||
// // Comment attached to bar.
|
||||
// optional int32 bar = 2;
|
||||
//
|
||||
// optional string baz = 3;
|
||||
// // Comment attached to baz.
|
||||
// // Another line attached to baz.
|
||||
//
|
||||
// // Comment attached to qux.
|
||||
// //
|
||||
// // Another line attached to qux.
|
||||
// optional double qux = 4;
|
||||
//
|
||||
// // Detached comment. This is not attached to qux or corge
|
||||
// // because there are blank lines separating it from both.
|
||||
//
|
||||
// optional string corge = 5;
|
||||
// /* Block comment attached
|
||||
// * to corge. Leading asterisks
|
||||
// * will be removed. */
|
||||
// /* Block comment attached to
|
||||
// * grault. */
|
||||
// optional int32 grault = 6;
|
||||
bool NextWithComments(string* prev_trailing_comments,
|
||||
vector<string>* detached_comments,
|
||||
string* next_leading_comments);
|
||||
|
||||
// Parse helpers ---------------------------------------------------
|
||||
|
||||
// Parses a TYPE_FLOAT token. This never fails, so long as the text actually
|
||||
// comes from a TYPE_FLOAT token parsed by Tokenizer. If it doesn't, the
|
||||
// result is undefined (possibly an assert failure).
|
||||
static double ParseFloat(const string& text);
|
||||
|
||||
// Parses a TYPE_STRING token. This never fails, so long as the text actually
|
||||
// comes from a TYPE_STRING token parsed by Tokenizer. If it doesn't, the
|
||||
// result is undefined (possibly an assert failure).
|
||||
static void ParseString(const string& text, string* output);
|
||||
|
||||
// Identical to ParseString, but appends to output.
|
||||
static void ParseStringAppend(const string& text, string* output);
|
||||
|
||||
// Parses a TYPE_INTEGER token. Returns false if the result would be
|
||||
// greater than max_value. Otherwise, returns true and sets *output to the
|
||||
// result. If the text is not from a Token of type TYPE_INTEGER originally
|
||||
// parsed by a Tokenizer, the result is undefined (possibly an assert
|
||||
// failure).
|
||||
static bool ParseInteger(const string& text, uint64 max_value,
|
||||
uint64* output);
|
||||
|
||||
// Options ---------------------------------------------------------
|
||||
|
||||
// Set true to allow floats to be suffixed with the letter 'f'. Tokens
|
||||
// which would otherwise be integers but which have the 'f' suffix will be
|
||||
// forced to be interpreted as floats. For all other purposes, the 'f' is
|
||||
// ignored.
|
||||
void set_allow_f_after_float(bool value) { allow_f_after_float_ = value; }
|
||||
|
||||
// Valid values for set_comment_style().
|
||||
enum CommentStyle {
|
||||
// Line comments begin with "//", block comments are delimited by "/*" and
|
||||
// "*/".
|
||||
CPP_COMMENT_STYLE,
|
||||
// Line comments begin with "#". No way to write block comments.
|
||||
SH_COMMENT_STYLE
|
||||
};
|
||||
|
||||
// Sets the comment style.
|
||||
void set_comment_style(CommentStyle style) { comment_style_ = style; }
|
||||
|
||||
// Whether to require whitespace between a number and a field name.
|
||||
// Default is true. Do not use this; for Google-internal cleanup only.
|
||||
void set_require_space_after_number(bool require) {
|
||||
require_space_after_number_ = require;
|
||||
}
|
||||
|
||||
// Whether to allow string literals to span multiple lines. Default is false.
|
||||
// Do not use this; for Google-internal cleanup only.
|
||||
void set_allow_multiline_strings(bool allow) {
|
||||
allow_multiline_strings_ = allow;
|
||||
}
|
||||
|
||||
// External helper: validate an identifier.
|
||||
static bool IsIdentifier(const string& text);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer);
|
||||
|
||||
Token current_; // Returned by current().
|
||||
Token previous_; // Returned by previous().
|
||||
|
||||
ZeroCopyInputStream* input_;
|
||||
ErrorCollector* error_collector_;
|
||||
|
||||
char current_char_; // == buffer_[buffer_pos_], updated by NextChar().
|
||||
const char* buffer_; // Current buffer returned from input_.
|
||||
int buffer_size_; // Size of buffer_.
|
||||
int buffer_pos_; // Current position within the buffer.
|
||||
bool read_error_; // Did we previously encounter a read error?
|
||||
|
||||
// Line and column number of current_char_ within the whole input stream.
|
||||
int line_;
|
||||
int column_;
|
||||
|
||||
// String to which text should be appended as we advance through it.
|
||||
// Call RecordTo(&str) to start recording and StopRecording() to stop.
|
||||
// E.g. StartToken() calls RecordTo(¤t_.text). record_start_ is the
|
||||
// position within the current buffer where recording started.
|
||||
string* record_target_;
|
||||
int record_start_;
|
||||
|
||||
// Options.
|
||||
bool allow_f_after_float_;
|
||||
CommentStyle comment_style_;
|
||||
bool require_space_after_number_;
|
||||
bool allow_multiline_strings_;
|
||||
|
||||
// Since we count columns we need to interpret tabs somehow. We'll take
|
||||
// the standard 8-character definition for lack of any way to do better.
|
||||
static const int kTabWidth = 8;
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Helper methods.
|
||||
|
||||
// Consume this character and advance to the next one.
|
||||
void NextChar();
|
||||
|
||||
// Read a new buffer from the input.
|
||||
void Refresh();
|
||||
|
||||
inline void RecordTo(string* target);
|
||||
inline void StopRecording();
|
||||
|
||||
// Called when the current character is the first character of a new
|
||||
// token (not including whitespace or comments).
|
||||
inline void StartToken();
|
||||
// Called when the current character is the first character after the
|
||||
// end of the last token. After this returns, current_.text will
|
||||
// contain all text consumed since StartToken() was called.
|
||||
inline void EndToken();
|
||||
|
||||
// Convenience method to add an error at the current line and column.
|
||||
void AddError(const string& message) {
|
||||
error_collector_->AddError(line_, column_, message);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// The following four methods are used to consume tokens of specific
|
||||
// types. They are actually used to consume all characters *after*
|
||||
// the first, since the calling function consumes the first character
|
||||
// in order to decide what kind of token is being read.
|
||||
|
||||
// Read and consume a string, ending when the given delimiter is
|
||||
// consumed.
|
||||
void ConsumeString(char delimiter);
|
||||
|
||||
// Read and consume a number, returning TYPE_FLOAT or TYPE_INTEGER
|
||||
// depending on what was read. This needs to know if the first
|
||||
// character was a zero in order to correctly recognize hex and octal
|
||||
// numbers.
|
||||
// It also needs to know if the first characted was a . to parse floating
|
||||
// point correctly.
|
||||
TokenType ConsumeNumber(bool started_with_zero, bool started_with_dot);
|
||||
|
||||
// Consume the rest of a line.
|
||||
void ConsumeLineComment(string* content);
|
||||
// Consume until "*/".
|
||||
void ConsumeBlockComment(string* content);
|
||||
|
||||
enum NextCommentStatus {
|
||||
// Started a line comment.
|
||||
LINE_COMMENT,
|
||||
|
||||
// Started a block comment.
|
||||
BLOCK_COMMENT,
|
||||
|
||||
// Consumed a slash, then realized it wasn't a comment. current_ has
|
||||
// been filled in with a slash token. The caller should return it.
|
||||
SLASH_NOT_COMMENT,
|
||||
|
||||
// We do not appear to be starting a comment here.
|
||||
NO_COMMENT
|
||||
};
|
||||
|
||||
// If we're at the start of a new comment, consume it and return what kind
|
||||
// of comment it is.
|
||||
NextCommentStatus TryConsumeCommentStart();
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// These helper methods make the parsing code more readable. The
|
||||
// "character classes" refered to are defined at the top of the .cc file.
|
||||
// Basically it is a C++ class with one method:
|
||||
// static bool InClass(char c);
|
||||
// The method returns true if c is a member of this "class", like "Letter"
|
||||
// or "Digit".
|
||||
|
||||
// Returns true if the current character is of the given character
|
||||
// class, but does not consume anything.
|
||||
template<typename CharacterClass>
|
||||
inline bool LookingAt();
|
||||
|
||||
// If the current character is in the given class, consume it and return
|
||||
// true. Otherwise return false.
|
||||
// e.g. TryConsumeOne<Letter>()
|
||||
template<typename CharacterClass>
|
||||
inline bool TryConsumeOne();
|
||||
|
||||
// Like above, but try to consume the specific character indicated.
|
||||
inline bool TryConsume(char c);
|
||||
|
||||
// Consume zero or more of the given character class.
|
||||
template<typename CharacterClass>
|
||||
inline void ConsumeZeroOrMore();
|
||||
|
||||
// Consume one or more of the given character class or log the given
|
||||
// error message.
|
||||
// e.g. ConsumeOneOrMore<Digit>("Expected digits.");
|
||||
template<typename CharacterClass>
|
||||
inline void ConsumeOneOrMore(const char* error);
|
||||
};
|
||||
|
||||
// inline methods ====================================================
|
||||
inline const Tokenizer::Token& Tokenizer::current() {
|
||||
return current_;
|
||||
}
|
||||
|
||||
inline const Tokenizer::Token& Tokenizer::previous() {
|
||||
return previous_;
|
||||
}
|
||||
|
||||
inline void Tokenizer::ParseString(const string& text, string* output) {
|
||||
output->clear();
|
||||
ParseStringAppend(text, output);
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_TOKENIZER_H__
|
|
@ -0,0 +1,248 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// This file contains the ZeroCopyInputStream and ZeroCopyOutputStream
|
||||
// interfaces, which represent abstract I/O streams to and from which
|
||||
// protocol buffers can be read and written. For a few simple
|
||||
// implementations of these interfaces, see zero_copy_stream_impl.h.
|
||||
//
|
||||
// These interfaces are different from classic I/O streams in that they
|
||||
// try to minimize the amount of data copying that needs to be done.
|
||||
// To accomplish this, responsibility for allocating buffers is moved to
|
||||
// the stream object, rather than being the responsibility of the caller.
|
||||
// So, the stream can return a buffer which actually points directly into
|
||||
// the final data structure where the bytes are to be stored, and the caller
|
||||
// can interact directly with that buffer, eliminating an intermediate copy
|
||||
// operation.
|
||||
//
|
||||
// As an example, consider the common case in which you are reading bytes
|
||||
// from an array that is already in memory (or perhaps an mmap()ed file).
|
||||
// With classic I/O streams, you would do something like:
|
||||
// char buffer[BUFFER_SIZE];
|
||||
// input->Read(buffer, BUFFER_SIZE);
|
||||
// DoSomething(buffer, BUFFER_SIZE);
|
||||
// Then, the stream basically just calls memcpy() to copy the data from
|
||||
// the array into your buffer. With a ZeroCopyInputStream, you would do
|
||||
// this instead:
|
||||
// const void* buffer;
|
||||
// int size;
|
||||
// input->Next(&buffer, &size);
|
||||
// DoSomething(buffer, size);
|
||||
// Here, no copy is performed. The input stream returns a pointer directly
|
||||
// into the backing array, and the caller ends up reading directly from it.
|
||||
//
|
||||
// If you want to be able to read the old-fashion way, you can create
|
||||
// a CodedInputStream or CodedOutputStream wrapping these objects and use
|
||||
// their ReadRaw()/WriteRaw() methods. These will, of course, add a copy
|
||||
// step, but Coded*Stream will handle buffering so at least it will be
|
||||
// reasonably efficient.
|
||||
//
|
||||
// ZeroCopyInputStream example:
|
||||
// // Read in a file and print its contents to stdout.
|
||||
// int fd = open("myfile", O_RDONLY);
|
||||
// ZeroCopyInputStream* input = new FileInputStream(fd);
|
||||
//
|
||||
// const void* buffer;
|
||||
// int size;
|
||||
// while (input->Next(&buffer, &size)) {
|
||||
// cout.write(buffer, size);
|
||||
// }
|
||||
//
|
||||
// delete input;
|
||||
// close(fd);
|
||||
//
|
||||
// ZeroCopyOutputStream example:
|
||||
// // Copy the contents of "infile" to "outfile", using plain read() for
|
||||
// // "infile" but a ZeroCopyOutputStream for "outfile".
|
||||
// int infd = open("infile", O_RDONLY);
|
||||
// int outfd = open("outfile", O_WRONLY);
|
||||
// ZeroCopyOutputStream* output = new FileOutputStream(outfd);
|
||||
//
|
||||
// void* buffer;
|
||||
// int size;
|
||||
// while (output->Next(&buffer, &size)) {
|
||||
// int bytes = read(infd, buffer, size);
|
||||
// if (bytes < size) {
|
||||
// // Reached EOF.
|
||||
// output->BackUp(size - bytes);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// delete output;
|
||||
// close(infd);
|
||||
// close(outfd);
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// Defined in this file.
|
||||
class ZeroCopyInputStream;
|
||||
class ZeroCopyOutputStream;
|
||||
|
||||
// Abstract interface similar to an input stream but designed to minimize
|
||||
// copying.
|
||||
class LIBPROTOBUF_EXPORT ZeroCopyInputStream {
|
||||
public:
|
||||
inline ZeroCopyInputStream() {}
|
||||
virtual ~ZeroCopyInputStream();
|
||||
|
||||
// Obtains a chunk of data from the stream.
|
||||
//
|
||||
// Preconditions:
|
||||
// * "size" and "data" are not NULL.
|
||||
//
|
||||
// Postconditions:
|
||||
// * If the returned value is false, there is no more data to return or
|
||||
// an error occurred. All errors are permanent.
|
||||
// * Otherwise, "size" points to the actual number of bytes read and "data"
|
||||
// points to a pointer to a buffer containing these bytes.
|
||||
// * Ownership of this buffer remains with the stream, and the buffer
|
||||
// remains valid only until some other method of the stream is called
|
||||
// or the stream is destroyed.
|
||||
// * It is legal for the returned buffer to have zero size, as long
|
||||
// as repeatedly calling Next() eventually yields a buffer with non-zero
|
||||
// size.
|
||||
virtual bool Next(const void** data, int* size) = 0;
|
||||
|
||||
// Backs up a number of bytes, so that the next call to Next() returns
|
||||
// data again that was already returned by the last call to Next(). This
|
||||
// is useful when writing procedures that are only supposed to read up
|
||||
// to a certain point in the input, then return. If Next() returns a
|
||||
// buffer that goes beyond what you wanted to read, you can use BackUp()
|
||||
// to return to the point where you intended to finish.
|
||||
//
|
||||
// Preconditions:
|
||||
// * The last method called must have been Next().
|
||||
// * count must be less than or equal to the size of the last buffer
|
||||
// returned by Next().
|
||||
//
|
||||
// Postconditions:
|
||||
// * The last "count" bytes of the last buffer returned by Next() will be
|
||||
// pushed back into the stream. Subsequent calls to Next() will return
|
||||
// the same data again before producing new data.
|
||||
virtual void BackUp(int count) = 0;
|
||||
|
||||
// Skips a number of bytes. Returns false if the end of the stream is
|
||||
// reached or some input error occurred. In the end-of-stream case, the
|
||||
// stream is advanced to the end of the stream (so ByteCount() will return
|
||||
// the total size of the stream).
|
||||
virtual bool Skip(int count) = 0;
|
||||
|
||||
// Returns the total number of bytes read since this object was created.
|
||||
virtual int64 ByteCount() const = 0;
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream);
|
||||
};
|
||||
|
||||
// Abstract interface similar to an output stream but designed to minimize
|
||||
// copying.
|
||||
class LIBPROTOBUF_EXPORT ZeroCopyOutputStream {
|
||||
public:
|
||||
inline ZeroCopyOutputStream() {}
|
||||
virtual ~ZeroCopyOutputStream();
|
||||
|
||||
// Obtains a buffer into which data can be written. Any data written
|
||||
// into this buffer will eventually (maybe instantly, maybe later on)
|
||||
// be written to the output.
|
||||
//
|
||||
// Preconditions:
|
||||
// * "size" and "data" are not NULL.
|
||||
//
|
||||
// Postconditions:
|
||||
// * If the returned value is false, an error occurred. All errors are
|
||||
// permanent.
|
||||
// * Otherwise, "size" points to the actual number of bytes in the buffer
|
||||
// and "data" points to the buffer.
|
||||
// * Ownership of this buffer remains with the stream, and the buffer
|
||||
// remains valid only until some other method of the stream is called
|
||||
// or the stream is destroyed.
|
||||
// * Any data which the caller stores in this buffer will eventually be
|
||||
// written to the output (unless BackUp() is called).
|
||||
// * It is legal for the returned buffer to have zero size, as long
|
||||
// as repeatedly calling Next() eventually yields a buffer with non-zero
|
||||
// size.
|
||||
virtual bool Next(void** data, int* size) = 0;
|
||||
|
||||
// Backs up a number of bytes, so that the end of the last buffer returned
|
||||
// by Next() is not actually written. This is needed when you finish
|
||||
// writing all the data you want to write, but the last buffer was bigger
|
||||
// than you needed. You don't want to write a bunch of garbage after the
|
||||
// end of your data, so you use BackUp() to back up.
|
||||
//
|
||||
// Preconditions:
|
||||
// * The last method called must have been Next().
|
||||
// * count must be less than or equal to the size of the last buffer
|
||||
// returned by Next().
|
||||
// * The caller must not have written anything to the last "count" bytes
|
||||
// of that buffer.
|
||||
//
|
||||
// Postconditions:
|
||||
// * The last "count" bytes of the last buffer returned by Next() will be
|
||||
// ignored.
|
||||
virtual void BackUp(int count) = 0;
|
||||
|
||||
// Returns the total number of bytes written since this object was created.
|
||||
virtual int64 ByteCount() const = 0;
|
||||
|
||||
// Write a given chunk of data to the output. Some output streams may
|
||||
// implement this in a way that avoids copying. Check AllowsAliasing() before
|
||||
// calling WriteAliasedRaw(). It will GOOGLE_CHECK fail if WriteAliasedRaw() is
|
||||
// called on a stream that does not allow aliasing.
|
||||
//
|
||||
// NOTE: It is caller's responsibility to ensure that the chunk of memory
|
||||
// remains live until all of the data has been consumed from the stream.
|
||||
virtual bool WriteAliasedRaw(const void* data, int size);
|
||||
virtual bool AllowsAliasing() const { return false; }
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
|
@ -0,0 +1,358 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// This file contains common implementations of the interfaces defined in
|
||||
// zero_copy_stream.h which are only included in the full (non-lite)
|
||||
// protobuf library. These implementations include Unix file descriptors
|
||||
// and C++ iostreams. See also: zero_copy_stream_impl_lite.h
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from a file descriptor.
|
||||
//
|
||||
// FileInputStream is preferred over using an ifstream with IstreamInputStream.
|
||||
// The latter will introduce an extra layer of buffering, harming performance.
|
||||
// Also, it's conceivable that FileInputStream could someday be enhanced
|
||||
// to use zero-copy file descriptors on OSs which support them.
|
||||
class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
// should be read and returned with each call to Next(). Otherwise,
|
||||
// a reasonable default is used.
|
||||
explicit FileInputStream(int file_descriptor, int block_size = -1);
|
||||
~FileInputStream();
|
||||
|
||||
// Flushes any buffers and closes the underlying file. Returns false if
|
||||
// an error occurs during the process; use GetErrno() to examine the error.
|
||||
// Even if an error occurs, the file descriptor is closed when this returns.
|
||||
bool Close();
|
||||
|
||||
// By default, the file descriptor is not closed when the stream is
|
||||
// destroyed. Call SetCloseOnDelete(true) to change that. WARNING:
|
||||
// This leaves no way for the caller to detect if close() fails. If
|
||||
// detecting close() errors is important to you, you should arrange
|
||||
// to close the descriptor yourself.
|
||||
void SetCloseOnDelete(bool value) { copying_input_.SetCloseOnDelete(value); }
|
||||
|
||||
// If an I/O error has occurred on this file descriptor, this is the
|
||||
// errno from that error. Otherwise, this is zero. Once an error
|
||||
// occurs, the stream is broken and all subsequent operations will
|
||||
// fail.
|
||||
int GetErrno() { return copying_input_.GetErrno(); }
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT CopyingFileInputStream : public CopyingInputStream {
|
||||
public:
|
||||
CopyingFileInputStream(int file_descriptor);
|
||||
~CopyingFileInputStream();
|
||||
|
||||
bool Close();
|
||||
void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
|
||||
int GetErrno() { return errno_; }
|
||||
|
||||
// implements CopyingInputStream ---------------------------------
|
||||
int Read(void* buffer, int size);
|
||||
int Skip(int count);
|
||||
|
||||
private:
|
||||
// The file descriptor.
|
||||
const int file_;
|
||||
bool close_on_delete_;
|
||||
bool is_closed_;
|
||||
|
||||
// The errno of the I/O error, if one has occurred. Otherwise, zero.
|
||||
int errno_;
|
||||
|
||||
// Did we try to seek once and fail? If so, we assume this file descriptor
|
||||
// doesn't support seeking and won't try again.
|
||||
bool previous_seek_failed_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileInputStream);
|
||||
};
|
||||
|
||||
CopyingFileInputStream copying_input_;
|
||||
CopyingInputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which writes to a file descriptor.
|
||||
//
|
||||
// FileOutputStream is preferred over using an ofstream with
|
||||
// OstreamOutputStream. The latter will introduce an extra layer of buffering,
|
||||
// harming performance. Also, it's conceivable that FileOutputStream could
|
||||
// someday be enhanced to use zero-copy file descriptors on OSs which
|
||||
// support them.
|
||||
class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Creates a stream that writes to the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit FileOutputStream(int file_descriptor, int block_size = -1);
|
||||
~FileOutputStream();
|
||||
|
||||
// Flushes any buffers and closes the underlying file. Returns false if
|
||||
// an error occurs during the process; use GetErrno() to examine the error.
|
||||
// Even if an error occurs, the file descriptor is closed when this returns.
|
||||
bool Close();
|
||||
|
||||
// Flushes FileOutputStream's buffers but does not close the
|
||||
// underlying file. No special measures are taken to ensure that
|
||||
// underlying operating system file object is synchronized to disk.
|
||||
bool Flush();
|
||||
|
||||
// By default, the file descriptor is not closed when the stream is
|
||||
// destroyed. Call SetCloseOnDelete(true) to change that. WARNING:
|
||||
// This leaves no way for the caller to detect if close() fails. If
|
||||
// detecting close() errors is important to you, you should arrange
|
||||
// to close the descriptor yourself.
|
||||
void SetCloseOnDelete(bool value) { copying_output_.SetCloseOnDelete(value); }
|
||||
|
||||
// If an I/O error has occurred on this file descriptor, this is the
|
||||
// errno from that error. Otherwise, this is zero. Once an error
|
||||
// occurs, the stream is broken and all subsequent operations will
|
||||
// fail.
|
||||
int GetErrno() { return copying_output_.GetErrno(); }
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream {
|
||||
public:
|
||||
CopyingFileOutputStream(int file_descriptor);
|
||||
~CopyingFileOutputStream();
|
||||
|
||||
bool Close();
|
||||
void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
|
||||
int GetErrno() { return errno_; }
|
||||
|
||||
// implements CopyingOutputStream --------------------------------
|
||||
bool Write(const void* buffer, int size);
|
||||
|
||||
private:
|
||||
// The file descriptor.
|
||||
const int file_;
|
||||
bool close_on_delete_;
|
||||
bool is_closed_;
|
||||
|
||||
// The errno of the I/O error, if one has occurred. Otherwise, zero.
|
||||
int errno_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileOutputStream);
|
||||
};
|
||||
|
||||
CopyingFileOutputStream copying_output_;
|
||||
CopyingOutputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from a C++ istream.
|
||||
//
|
||||
// Note that for reading files (or anything represented by a file descriptor),
|
||||
// FileInputStream is more efficient.
|
||||
class LIBPROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given C++ istream.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
// should be read and returned with each call to Next(). Otherwise,
|
||||
// a reasonable default is used.
|
||||
explicit IstreamInputStream(istream* stream, int block_size = -1);
|
||||
~IstreamInputStream();
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT CopyingIstreamInputStream : public CopyingInputStream {
|
||||
public:
|
||||
CopyingIstreamInputStream(istream* input);
|
||||
~CopyingIstreamInputStream();
|
||||
|
||||
// implements CopyingInputStream ---------------------------------
|
||||
int Read(void* buffer, int size);
|
||||
// (We use the default implementation of Skip().)
|
||||
|
||||
private:
|
||||
// The stream.
|
||||
istream* input_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingIstreamInputStream);
|
||||
};
|
||||
|
||||
CopyingIstreamInputStream copying_input_;
|
||||
CopyingInputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(IstreamInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which writes to a C++ ostream.
|
||||
//
|
||||
// Note that for writing files (or anything represented by a file descriptor),
|
||||
// FileOutputStream is more efficient.
|
||||
class LIBPROTOBUF_EXPORT OstreamOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Creates a stream that writes to the given C++ ostream.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit OstreamOutputStream(ostream* stream, int block_size = -1);
|
||||
~OstreamOutputStream();
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT CopyingOstreamOutputStream : public CopyingOutputStream {
|
||||
public:
|
||||
CopyingOstreamOutputStream(ostream* output);
|
||||
~CopyingOstreamOutputStream();
|
||||
|
||||
// implements CopyingOutputStream --------------------------------
|
||||
bool Write(const void* buffer, int size);
|
||||
|
||||
private:
|
||||
// The stream.
|
||||
ostream* output_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOstreamOutputStream);
|
||||
};
|
||||
|
||||
CopyingOstreamOutputStream copying_output_;
|
||||
CopyingOutputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OstreamOutputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from several other streams in sequence.
|
||||
// ConcatenatingInputStream is unable to distinguish between end-of-stream
|
||||
// and read errors in the underlying streams, so it assumes any errors mean
|
||||
// end-of-stream. So, if the underlying streams fail for any other reason,
|
||||
// ConcatenatingInputStream may do odd things. It is suggested that you do
|
||||
// not use ConcatenatingInputStream on streams that might produce read errors
|
||||
// other than end-of-stream.
|
||||
class LIBPROTOBUF_EXPORT ConcatenatingInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// All streams passed in as well as the array itself must remain valid
|
||||
// until the ConcatenatingInputStream is destroyed.
|
||||
ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count);
|
||||
~ConcatenatingInputStream();
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
|
||||
private:
|
||||
// As streams are retired, streams_ is incremented and count_ is
|
||||
// decremented.
|
||||
ZeroCopyInputStream* const* streams_;
|
||||
int stream_count_;
|
||||
int64 bytes_retired_; // Bytes read from previous streams.
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ConcatenatingInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which wraps some other stream and limits it to
|
||||
// a particular byte count.
|
||||
class LIBPROTOBUF_EXPORT LimitingInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
LimitingInputStream(ZeroCopyInputStream* input, int64 limit);
|
||||
~LimitingInputStream();
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
|
||||
private:
|
||||
ZeroCopyInputStream* input_;
|
||||
int64 limit_; // Decreases as we go, becomes negative if we overshoot.
|
||||
int64 prior_bytes_read_; // Bytes read on underlying stream at construction
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
|
@ -0,0 +1,354 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// This file contains common implementations of the interfaces defined in
|
||||
// zero_copy_stream.h which are included in the "lite" protobuf library.
|
||||
// These implementations cover I/O on raw arrays and strings, as well as
|
||||
// adaptors which make it easy to implement streams based on traditional
|
||||
// streams. Of course, many users will probably want to write their own
|
||||
// implementations of these interfaces specific to the particular I/O
|
||||
// abstractions they prefer to use, but these should cover the most common
|
||||
// cases.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream backed by an in-memory array of bytes.
|
||||
class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Create an InputStream that returns the bytes pointed to by "data".
|
||||
// "data" remains the property of the caller but must remain valid until
|
||||
// the stream is destroyed. If a block_size is given, calls to Next()
|
||||
// will return data blocks no larger than the given size. Otherwise, the
|
||||
// first call to Next() returns the entire array. block_size is mainly
|
||||
// useful for testing; in production you would probably never want to set
|
||||
// it.
|
||||
ArrayInputStream(const void* data, int size, int block_size = -1);
|
||||
~ArrayInputStream();
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
|
||||
private:
|
||||
const uint8* const data_; // The byte array.
|
||||
const int size_; // Total size of the array.
|
||||
const int block_size_; // How many bytes to return at a time.
|
||||
|
||||
int position_;
|
||||
int last_returned_size_; // How many bytes we returned last time Next()
|
||||
// was called (used for error checking only).
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream backed by an in-memory array of bytes.
|
||||
class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Create an OutputStream that writes to the bytes pointed to by "data".
|
||||
// "data" remains the property of the caller but must remain valid until
|
||||
// the stream is destroyed. If a block_size is given, calls to Next()
|
||||
// will return data blocks no larger than the given size. Otherwise, the
|
||||
// first call to Next() returns the entire array. block_size is mainly
|
||||
// useful for testing; in production you would probably never want to set
|
||||
// it.
|
||||
ArrayOutputStream(void* data, int size, int block_size = -1);
|
||||
~ArrayOutputStream();
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
uint8* const data_; // The byte array.
|
||||
const int size_; // Total size of the array.
|
||||
const int block_size_; // How many bytes to return at a time.
|
||||
|
||||
int position_;
|
||||
int last_returned_size_; // How many bytes we returned last time Next()
|
||||
// was called (used for error checking only).
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which appends bytes to a string.
|
||||
class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Create a StringOutputStream which appends bytes to the given string.
|
||||
// The string remains property of the caller, but it MUST NOT be accessed
|
||||
// in any way until the stream is destroyed.
|
||||
//
|
||||
// Hint: If you call target->reserve(n) before creating the stream,
|
||||
// the first call to Next() will return at least n bytes of buffer
|
||||
// space.
|
||||
explicit StringOutputStream(string* target);
|
||||
~StringOutputStream();
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
static const int kMinimumSize = 16;
|
||||
|
||||
string* target_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
|
||||
};
|
||||
|
||||
// Note: There is no StringInputStream. Instead, just create an
|
||||
// ArrayInputStream as follows:
|
||||
// ArrayInputStream input(str.data(), str.size());
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A generic traditional input stream interface.
|
||||
//
|
||||
// Lots of traditional input streams (e.g. file descriptors, C stdio
|
||||
// streams, and C++ iostreams) expose an interface where every read
|
||||
// involves copying bytes into a buffer. If you want to take such an
|
||||
// interface and make a ZeroCopyInputStream based on it, simply implement
|
||||
// CopyingInputStream and then use CopyingInputStreamAdaptor.
|
||||
//
|
||||
// CopyingInputStream implementations should avoid buffering if possible.
|
||||
// CopyingInputStreamAdaptor does its own buffering and will read data
|
||||
// in large blocks.
|
||||
class LIBPROTOBUF_EXPORT CopyingInputStream {
|
||||
public:
|
||||
virtual ~CopyingInputStream();
|
||||
|
||||
// Reads up to "size" bytes into the given buffer. Returns the number of
|
||||
// bytes read. Read() waits until at least one byte is available, or
|
||||
// returns zero if no bytes will ever become available (EOF), or -1 if a
|
||||
// permanent read error occurred.
|
||||
virtual int Read(void* buffer, int size) = 0;
|
||||
|
||||
// Skips the next "count" bytes of input. Returns the number of bytes
|
||||
// actually skipped. This will always be exactly equal to "count" unless
|
||||
// EOF was reached or a permanent read error occurred.
|
||||
//
|
||||
// The default implementation just repeatedly calls Read() into a scratch
|
||||
// buffer.
|
||||
virtual int Skip(int count);
|
||||
};
|
||||
|
||||
// A ZeroCopyInputStream which reads from a CopyingInputStream. This is
|
||||
// useful for implementing ZeroCopyInputStreams that read from traditional
|
||||
// streams. Note that this class is not really zero-copy.
|
||||
//
|
||||
// If you want to read from file descriptors or C++ istreams, this is
|
||||
// already implemented for you: use FileInputStream or IstreamInputStream
|
||||
// respectively.
|
||||
class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given CopyingInputStream.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
// should be read and returned with each call to Next(). Otherwise,
|
||||
// a reasonable default is used. The caller retains ownership of
|
||||
// copying_stream unless SetOwnsCopyingStream(true) is called.
|
||||
explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream,
|
||||
int block_size = -1);
|
||||
~CopyingInputStreamAdaptor();
|
||||
|
||||
// Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to
|
||||
// delete the underlying CopyingInputStream when it is destroyed.
|
||||
void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
// Insures that buffer_ is not NULL.
|
||||
void AllocateBufferIfNeeded();
|
||||
// Frees the buffer and resets buffer_used_.
|
||||
void FreeBuffer();
|
||||
|
||||
// The underlying copying stream.
|
||||
CopyingInputStream* copying_stream_;
|
||||
bool owns_copying_stream_;
|
||||
|
||||
// True if we have seen a permenant error from the underlying stream.
|
||||
bool failed_;
|
||||
|
||||
// The current position of copying_stream_, relative to the point where
|
||||
// we started reading.
|
||||
int64 position_;
|
||||
|
||||
// Data is read into this buffer. It may be NULL if no buffer is currently
|
||||
// in use. Otherwise, it points to an array of size buffer_size_.
|
||||
scoped_array<uint8> buffer_;
|
||||
const int buffer_size_;
|
||||
|
||||
// Number of valid bytes currently in the buffer (i.e. the size last
|
||||
// returned by Next()). 0 <= buffer_used_ <= buffer_size_.
|
||||
int buffer_used_;
|
||||
|
||||
// Number of bytes in the buffer which were backed up over by a call to
|
||||
// BackUp(). These need to be returned again.
|
||||
// 0 <= backup_bytes_ <= buffer_used_
|
||||
int backup_bytes_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A generic traditional output stream interface.
|
||||
//
|
||||
// Lots of traditional output streams (e.g. file descriptors, C stdio
|
||||
// streams, and C++ iostreams) expose an interface where every write
|
||||
// involves copying bytes from a buffer. If you want to take such an
|
||||
// interface and make a ZeroCopyOutputStream based on it, simply implement
|
||||
// CopyingOutputStream and then use CopyingOutputStreamAdaptor.
|
||||
//
|
||||
// CopyingOutputStream implementations should avoid buffering if possible.
|
||||
// CopyingOutputStreamAdaptor does its own buffering and will write data
|
||||
// in large blocks.
|
||||
class LIBPROTOBUF_EXPORT CopyingOutputStream {
|
||||
public:
|
||||
virtual ~CopyingOutputStream();
|
||||
|
||||
// Writes "size" bytes from the given buffer to the output. Returns true
|
||||
// if successful, false on a write error.
|
||||
virtual bool Write(const void* buffer, int size) = 0;
|
||||
};
|
||||
|
||||
// A ZeroCopyOutputStream which writes to a CopyingOutputStream. This is
|
||||
// useful for implementing ZeroCopyOutputStreams that write to traditional
|
||||
// streams. Note that this class is not really zero-copy.
|
||||
//
|
||||
// If you want to write to file descriptors or C++ ostreams, this is
|
||||
// already implemented for you: use FileOutputStream or OstreamOutputStream
|
||||
// respectively.
|
||||
class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Creates a stream that writes to the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream,
|
||||
int block_size = -1);
|
||||
~CopyingOutputStreamAdaptor();
|
||||
|
||||
// Writes all pending data to the underlying stream. Returns false if a
|
||||
// write error occurred on the underlying stream. (The underlying
|
||||
// stream itself is not necessarily flushed.)
|
||||
bool Flush();
|
||||
|
||||
// Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to
|
||||
// delete the underlying CopyingOutputStream when it is destroyed.
|
||||
void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
// Write the current buffer, if it is present.
|
||||
bool WriteBuffer();
|
||||
// Insures that buffer_ is not NULL.
|
||||
void AllocateBufferIfNeeded();
|
||||
// Frees the buffer.
|
||||
void FreeBuffer();
|
||||
|
||||
// The underlying copying stream.
|
||||
CopyingOutputStream* copying_stream_;
|
||||
bool owns_copying_stream_;
|
||||
|
||||
// True if we have seen a permenant error from the underlying stream.
|
||||
bool failed_;
|
||||
|
||||
// The current position of copying_stream_, relative to the point where
|
||||
// we started writing.
|
||||
int64 position_;
|
||||
|
||||
// Data is written from this buffer. It may be NULL if no buffer is
|
||||
// currently in use. Otherwise, it points to an array of size buffer_size_.
|
||||
scoped_array<uint8> buffer_;
|
||||
const int buffer_size_;
|
||||
|
||||
// Number of valid bytes currently in the buffer (i.e. the size last
|
||||
// returned by Next()). When BackUp() is called, we just reduce this.
|
||||
// 0 <= buffer_used_ <= buffer_size_.
|
||||
int buffer_used_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// Return a pointer to mutable characters underlying the given string. The
|
||||
// return value is valid until the next time the string is resized. We
|
||||
// trust the caller to treat the return value as an array of length s->size().
|
||||
inline char* mutable_string_data(string* s) {
|
||||
#ifdef LANG_CXX11
|
||||
// This should be simpler & faster than string_as_array() because the latter
|
||||
// is guaranteed to return NULL when *s is empty, so it has to check for that.
|
||||
return &(*s)[0];
|
||||
#else
|
||||
return string_as_array(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
|
@ -0,0 +1,866 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Defines Message, the abstract interface implemented by non-lite
|
||||
// protocol message objects. Although it's possible to implement this
|
||||
// interface manually, most users will use the protocol compiler to
|
||||
// generate implementations.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// Say you have a message defined as:
|
||||
//
|
||||
// message Foo {
|
||||
// optional string text = 1;
|
||||
// repeated int32 numbers = 2;
|
||||
// }
|
||||
//
|
||||
// Then, if you used the protocol compiler to generate a class from the above
|
||||
// definition, you could use it like so:
|
||||
//
|
||||
// string data; // Will store a serialized version of the message.
|
||||
//
|
||||
// {
|
||||
// // Create a message and serialize it.
|
||||
// Foo foo;
|
||||
// foo.set_text("Hello World!");
|
||||
// foo.add_numbers(1);
|
||||
// foo.add_numbers(5);
|
||||
// foo.add_numbers(42);
|
||||
//
|
||||
// foo.SerializeToString(&data);
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// // Parse the serialized message and check that it contains the
|
||||
// // correct data.
|
||||
// Foo foo;
|
||||
// foo.ParseFromString(data);
|
||||
//
|
||||
// assert(foo.text() == "Hello World!");
|
||||
// assert(foo.numbers_size() == 3);
|
||||
// assert(foo.numbers(0) == 1);
|
||||
// assert(foo.numbers(1) == 5);
|
||||
// assert(foo.numbers(2) == 42);
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// // Same as the last block, but do it dynamically via the Message
|
||||
// // reflection interface.
|
||||
// Message* foo = new Foo;
|
||||
// const Descriptor* descriptor = foo->GetDescriptor();
|
||||
//
|
||||
// // Get the descriptors for the fields we're interested in and verify
|
||||
// // their types.
|
||||
// const FieldDescriptor* text_field = descriptor->FindFieldByName("text");
|
||||
// assert(text_field != NULL);
|
||||
// assert(text_field->type() == FieldDescriptor::TYPE_STRING);
|
||||
// assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL);
|
||||
// const FieldDescriptor* numbers_field = descriptor->
|
||||
// FindFieldByName("numbers");
|
||||
// assert(numbers_field != NULL);
|
||||
// assert(numbers_field->type() == FieldDescriptor::TYPE_INT32);
|
||||
// assert(numbers_field->label() == FieldDescriptor::LABEL_REPEATED);
|
||||
//
|
||||
// // Parse the message.
|
||||
// foo->ParseFromString(data);
|
||||
//
|
||||
// // Use the reflection interface to examine the contents.
|
||||
// const Reflection* reflection = foo->GetReflection();
|
||||
// assert(reflection->GetString(foo, text_field) == "Hello World!");
|
||||
// assert(reflection->FieldSize(foo, numbers_field) == 3);
|
||||
// assert(reflection->GetRepeatedInt32(foo, numbers_field, 0) == 1);
|
||||
// assert(reflection->GetRepeatedInt32(foo, numbers_field, 1) == 5);
|
||||
// assert(reflection->GetRepeatedInt32(foo, numbers_field, 2) == 42);
|
||||
//
|
||||
// delete foo;
|
||||
// }
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MESSAGE_H__
|
||||
#define GOOGLE_PROTOBUF_MESSAGE_H__
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/message_lite.h>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
|
||||
#define GOOGLE_PROTOBUF_HAS_ONEOF
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Defined in this file.
|
||||
class Message;
|
||||
class Reflection;
|
||||
class MessageFactory;
|
||||
|
||||
// Defined in other files.
|
||||
class UnknownFieldSet; // unknown_field_set.h
|
||||
namespace io {
|
||||
class ZeroCopyInputStream; // zero_copy_stream.h
|
||||
class ZeroCopyOutputStream; // zero_copy_stream.h
|
||||
class CodedInputStream; // coded_stream.h
|
||||
class CodedOutputStream; // coded_stream.h
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
class RepeatedField; // repeated_field.h
|
||||
|
||||
template<typename T>
|
||||
class RepeatedPtrField; // repeated_field.h
|
||||
|
||||
// A container to hold message metadata.
|
||||
struct Metadata {
|
||||
const Descriptor* descriptor;
|
||||
const Reflection* reflection;
|
||||
};
|
||||
|
||||
// Abstract interface for protocol messages.
|
||||
//
|
||||
// See also MessageLite, which contains most every-day operations. Message
|
||||
// adds descriptors and reflection on top of that.
|
||||
//
|
||||
// The methods of this class that are virtual but not pure-virtual have
|
||||
// default implementations based on reflection. Message classes which are
|
||||
// optimized for speed will want to override these with faster implementations,
|
||||
// but classes optimized for code size may be happy with keeping them. See
|
||||
// the optimize_for option in descriptor.proto.
|
||||
class LIBPROTOBUF_EXPORT Message : public MessageLite {
|
||||
public:
|
||||
inline Message() {}
|
||||
virtual ~Message();
|
||||
|
||||
// Basic Operations ------------------------------------------------
|
||||
|
||||
// Construct a new instance of the same type. Ownership is passed to the
|
||||
// caller. (This is also defined in MessageLite, but is defined again here
|
||||
// for return-type covariance.)
|
||||
virtual Message* New() const = 0;
|
||||
|
||||
// Make this message into a copy of the given message. The given message
|
||||
// must have the same descriptor, but need not necessarily be the same class.
|
||||
// By default this is just implemented as "Clear(); MergeFrom(from);".
|
||||
virtual void CopyFrom(const Message& from);
|
||||
|
||||
// Merge the fields from the given message into this message. Singular
|
||||
// fields will be overwritten, if specified in from, except for embedded
|
||||
// messages which will be merged. Repeated fields will be concatenated.
|
||||
// The given message must be of the same type as this message (i.e. the
|
||||
// exact same class).
|
||||
virtual void MergeFrom(const Message& from);
|
||||
|
||||
// Verifies that IsInitialized() returns true. GOOGLE_CHECK-fails otherwise, with
|
||||
// a nice error message.
|
||||
void CheckInitialized() const;
|
||||
|
||||
// Slowly build a list of all required fields that are not set.
|
||||
// This is much, much slower than IsInitialized() as it is implemented
|
||||
// purely via reflection. Generally, you should not call this unless you
|
||||
// have already determined that an error exists by calling IsInitialized().
|
||||
void FindInitializationErrors(vector<string>* errors) const;
|
||||
|
||||
// Like FindInitializationErrors, but joins all the strings, delimited by
|
||||
// commas, and returns them.
|
||||
string InitializationErrorString() const;
|
||||
|
||||
// Clears all unknown fields from this message and all embedded messages.
|
||||
// Normally, if unknown tag numbers are encountered when parsing a message,
|
||||
// the tag and value are stored in the message's UnknownFieldSet and
|
||||
// then written back out when the message is serialized. This allows servers
|
||||
// which simply route messages to other servers to pass through messages
|
||||
// that have new field definitions which they don't yet know about. However,
|
||||
// this behavior can have security implications. To avoid it, call this
|
||||
// method after parsing.
|
||||
//
|
||||
// See Reflection::GetUnknownFields() for more on unknown fields.
|
||||
virtual void DiscardUnknownFields();
|
||||
|
||||
// Computes (an estimate of) the total number of bytes currently used for
|
||||
// storing the message in memory. The default implementation calls the
|
||||
// Reflection object's SpaceUsed() method.
|
||||
virtual int SpaceUsed() const;
|
||||
|
||||
// Debugging & Testing----------------------------------------------
|
||||
|
||||
// Generates a human readable form of this message, useful for debugging
|
||||
// and other purposes.
|
||||
string DebugString() const;
|
||||
// Like DebugString(), but with less whitespace.
|
||||
string ShortDebugString() const;
|
||||
// Like DebugString(), but do not escape UTF-8 byte sequences.
|
||||
string Utf8DebugString() const;
|
||||
// Convenience function useful in GDB. Prints DebugString() to stdout.
|
||||
void PrintDebugString() const;
|
||||
|
||||
// Heavy I/O -------------------------------------------------------
|
||||
// Additional parsing and serialization methods not implemented by
|
||||
// MessageLite because they are not supported by the lite library.
|
||||
|
||||
// Parse a protocol buffer from a file descriptor. If successful, the entire
|
||||
// input will be consumed.
|
||||
bool ParseFromFileDescriptor(int file_descriptor);
|
||||
// Like ParseFromFileDescriptor(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromFileDescriptor(int file_descriptor);
|
||||
// Parse a protocol buffer from a C++ istream. If successful, the entire
|
||||
// input will be consumed.
|
||||
bool ParseFromIstream(istream* input);
|
||||
// Like ParseFromIstream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromIstream(istream* input);
|
||||
|
||||
// Serialize the message and write it to the given file descriptor. All
|
||||
// required fields must be set.
|
||||
bool SerializeToFileDescriptor(int file_descriptor) const;
|
||||
// Like SerializeToFileDescriptor(), but allows missing required fields.
|
||||
bool SerializePartialToFileDescriptor(int file_descriptor) const;
|
||||
// Serialize the message and write it to the given C++ ostream. All
|
||||
// required fields must be set.
|
||||
bool SerializeToOstream(ostream* output) const;
|
||||
// Like SerializeToOstream(), but allows missing required fields.
|
||||
bool SerializePartialToOstream(ostream* output) const;
|
||||
|
||||
|
||||
// Reflection-based methods ----------------------------------------
|
||||
// These methods are pure-virtual in MessageLite, but Message provides
|
||||
// reflection-based default implementations.
|
||||
|
||||
virtual string GetTypeName() const;
|
||||
virtual void Clear();
|
||||
virtual bool IsInitialized() const;
|
||||
virtual void CheckTypeAndMergeFrom(const MessageLite& other);
|
||||
virtual bool MergePartialFromCodedStream(io::CodedInputStream* input);
|
||||
virtual int ByteSize() const;
|
||||
virtual void SerializeWithCachedSizes(io::CodedOutputStream* output) const;
|
||||
|
||||
private:
|
||||
// This is called only by the default implementation of ByteSize(), to
|
||||
// update the cached size. If you override ByteSize(), you do not need
|
||||
// to override this. If you do not override ByteSize(), you MUST override
|
||||
// this; the default implementation will crash.
|
||||
//
|
||||
// The method is private because subclasses should never call it; only
|
||||
// override it. Yes, C++ lets you do that. Crazy, huh?
|
||||
virtual void SetCachedSize(int size) const;
|
||||
|
||||
public:
|
||||
|
||||
// Introspection ---------------------------------------------------
|
||||
|
||||
// Typedef for backwards-compatibility.
|
||||
typedef google::protobuf::Reflection Reflection;
|
||||
|
||||
// Get a Descriptor for this message's type. This describes what
|
||||
// fields the message contains, the types of those fields, etc.
|
||||
const Descriptor* GetDescriptor() const { return GetMetadata().descriptor; }
|
||||
|
||||
// Get the Reflection interface for this Message, which can be used to
|
||||
// read and modify the fields of the Message dynamically (in other words,
|
||||
// without knowing the message type at compile time). This object remains
|
||||
// property of the Message.
|
||||
//
|
||||
// This method remains virtual in case a subclass does not implement
|
||||
// reflection and wants to override the default behavior.
|
||||
virtual const Reflection* GetReflection() const {
|
||||
return GetMetadata().reflection;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Get a struct containing the metadata for the Message. Most subclasses only
|
||||
// need to implement this method, rather than the GetDescriptor() and
|
||||
// GetReflection() wrappers.
|
||||
virtual Metadata GetMetadata() const = 0;
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message);
|
||||
};
|
||||
|
||||
// This interface contains methods that can be used to dynamically access
|
||||
// and modify the fields of a protocol message. Their semantics are
|
||||
// similar to the accessors the protocol compiler generates.
|
||||
//
|
||||
// To get the Reflection for a given Message, call Message::GetReflection().
|
||||
//
|
||||
// This interface is separate from Message only for efficiency reasons;
|
||||
// the vast majority of implementations of Message will share the same
|
||||
// implementation of Reflection (GeneratedMessageReflection,
|
||||
// defined in generated_message.h), and all Messages of a particular class
|
||||
// should share the same Reflection object (though you should not rely on
|
||||
// the latter fact).
|
||||
//
|
||||
// There are several ways that these methods can be used incorrectly. For
|
||||
// example, any of the following conditions will lead to undefined
|
||||
// results (probably assertion failures):
|
||||
// - The FieldDescriptor is not a field of this message type.
|
||||
// - The method called is not appropriate for the field's type. For
|
||||
// each field type in FieldDescriptor::TYPE_*, there is only one
|
||||
// Get*() method, one Set*() method, and one Add*() method that is
|
||||
// valid for that type. It should be obvious which (except maybe
|
||||
// for TYPE_BYTES, which are represented using strings in C++).
|
||||
// - A Get*() or Set*() method for singular fields is called on a repeated
|
||||
// field.
|
||||
// - GetRepeated*(), SetRepeated*(), or Add*() is called on a non-repeated
|
||||
// field.
|
||||
// - The Message object passed to any method is not of the right type for
|
||||
// this Reflection object (i.e. message.GetReflection() != reflection).
|
||||
//
|
||||
// You might wonder why there is not any abstract representation for a field
|
||||
// of arbitrary type. E.g., why isn't there just a "GetField()" method that
|
||||
// returns "const Field&", where "Field" is some class with accessors like
|
||||
// "GetInt32Value()". The problem is that someone would have to deal with
|
||||
// allocating these Field objects. For generated message classes, having to
|
||||
// allocate space for an additional object to wrap every field would at least
|
||||
// double the message's memory footprint, probably worse. Allocating the
|
||||
// objects on-demand, on the other hand, would be expensive and prone to
|
||||
// memory leaks. So, instead we ended up with this flat interface.
|
||||
//
|
||||
// TODO(kenton): Create a utility class which callers can use to read and
|
||||
// write fields from a Reflection without paying attention to the type.
|
||||
class LIBPROTOBUF_EXPORT Reflection {
|
||||
public:
|
||||
inline Reflection() {}
|
||||
virtual ~Reflection();
|
||||
|
||||
// Get the UnknownFieldSet for the message. This contains fields which
|
||||
// were seen when the Message was parsed but were not recognized according
|
||||
// to the Message's definition.
|
||||
virtual const UnknownFieldSet& GetUnknownFields(
|
||||
const Message& message) const = 0;
|
||||
// Get a mutable pointer to the UnknownFieldSet for the message. This
|
||||
// contains fields which were seen when the Message was parsed but were not
|
||||
// recognized according to the Message's definition.
|
||||
virtual UnknownFieldSet* MutableUnknownFields(Message* message) const = 0;
|
||||
|
||||
// Estimate the amount of memory used by the message object.
|
||||
virtual int SpaceUsed(const Message& message) const = 0;
|
||||
|
||||
// Check if the given non-repeated field is set.
|
||||
virtual bool HasField(const Message& message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
|
||||
// Get the number of elements of a repeated field.
|
||||
virtual int FieldSize(const Message& message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
|
||||
// Clear the value of a field, so that HasField() returns false or
|
||||
// FieldSize() returns zero.
|
||||
virtual void ClearField(Message* message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
|
||||
// Check if the oneof is set. Returns ture if any field in oneof
|
||||
// is set, false otherwise.
|
||||
// TODO(jieluo) - make it pure virtual after updating all
|
||||
// the subclasses.
|
||||
virtual bool HasOneof(const Message& message,
|
||||
const OneofDescriptor* oneof_descriptor) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void ClearOneof(Message* message,
|
||||
const OneofDescriptor* oneof_descriptor) const {}
|
||||
|
||||
// Returns the field descriptor if the oneof is set. NULL otherwise.
|
||||
// TODO(jieluo) - make it pure virtual.
|
||||
virtual const FieldDescriptor* GetOneofFieldDescriptor(
|
||||
const Message& message,
|
||||
const OneofDescriptor* oneof_descriptor) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Removes the last element of a repeated field.
|
||||
// We don't provide a way to remove any element other than the last
|
||||
// because it invites inefficient use, such as O(n^2) filtering loops
|
||||
// that should have been O(n). If you want to remove an element other
|
||||
// than the last, the best way to do it is to re-arrange the elements
|
||||
// (using Swap()) so that the one you want removed is at the end, then
|
||||
// call RemoveLast().
|
||||
virtual void RemoveLast(Message* message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
// Removes the last element of a repeated message field, and returns the
|
||||
// pointer to the caller. Caller takes ownership of the returned pointer.
|
||||
virtual Message* ReleaseLast(Message* message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
|
||||
// Swap the complete contents of two messages.
|
||||
virtual void Swap(Message* message1, Message* message2) const = 0;
|
||||
|
||||
// Swap fields listed in fields vector of two messages.
|
||||
virtual void SwapFields(Message* message1,
|
||||
Message* message2,
|
||||
const vector<const FieldDescriptor*>& fields)
|
||||
const = 0;
|
||||
|
||||
// Swap two elements of a repeated field.
|
||||
virtual void SwapElements(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index1,
|
||||
int index2) const = 0;
|
||||
|
||||
// List all fields of the message which are currently set. This includes
|
||||
// extensions. Singular fields will only be listed if HasField(field) would
|
||||
// return true and repeated fields will only be listed if FieldSize(field)
|
||||
// would return non-zero. Fields (both normal fields and extension fields)
|
||||
// will be listed ordered by field number.
|
||||
virtual void ListFields(const Message& message,
|
||||
vector<const FieldDescriptor*>* output) const = 0;
|
||||
|
||||
// Singular field getters ------------------------------------------
|
||||
// These get the value of a non-repeated field. They return the default
|
||||
// value for fields that aren't set.
|
||||
|
||||
virtual int32 GetInt32 (const Message& message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
virtual int64 GetInt64 (const Message& message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
virtual uint32 GetUInt32(const Message& message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
virtual uint64 GetUInt64(const Message& message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
virtual float GetFloat (const Message& message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
virtual double GetDouble(const Message& message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
virtual bool GetBool (const Message& message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
virtual string GetString(const Message& message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
virtual const EnumValueDescriptor* GetEnum(
|
||||
const Message& message, const FieldDescriptor* field) const = 0;
|
||||
// See MutableMessage() for the meaning of the "factory" parameter.
|
||||
virtual const Message& GetMessage(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const = 0;
|
||||
|
||||
// Get a string value without copying, if possible.
|
||||
//
|
||||
// GetString() necessarily returns a copy of the string. This can be
|
||||
// inefficient when the string is already stored in a string object in the
|
||||
// underlying message. GetStringReference() will return a reference to the
|
||||
// underlying string in this case. Otherwise, it will copy the string into
|
||||
// *scratch and return that.
|
||||
//
|
||||
// Note: It is perfectly reasonable and useful to write code like:
|
||||
// str = reflection->GetStringReference(field, &str);
|
||||
// This line would ensure that only one copy of the string is made
|
||||
// regardless of the field's underlying representation. When initializing
|
||||
// a newly-constructed string, though, it's just as fast and more readable
|
||||
// to use code like:
|
||||
// string str = reflection->GetString(field);
|
||||
virtual const string& GetStringReference(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
string* scratch) const = 0;
|
||||
|
||||
|
||||
// Singular field mutators -----------------------------------------
|
||||
// These mutate the value of a non-repeated field.
|
||||
|
||||
virtual void SetInt32 (Message* message,
|
||||
const FieldDescriptor* field, int32 value) const = 0;
|
||||
virtual void SetInt64 (Message* message,
|
||||
const FieldDescriptor* field, int64 value) const = 0;
|
||||
virtual void SetUInt32(Message* message,
|
||||
const FieldDescriptor* field, uint32 value) const = 0;
|
||||
virtual void SetUInt64(Message* message,
|
||||
const FieldDescriptor* field, uint64 value) const = 0;
|
||||
virtual void SetFloat (Message* message,
|
||||
const FieldDescriptor* field, float value) const = 0;
|
||||
virtual void SetDouble(Message* message,
|
||||
const FieldDescriptor* field, double value) const = 0;
|
||||
virtual void SetBool (Message* message,
|
||||
const FieldDescriptor* field, bool value) const = 0;
|
||||
virtual void SetString(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
const string& value) const = 0;
|
||||
virtual void SetEnum (Message* message,
|
||||
const FieldDescriptor* field,
|
||||
const EnumValueDescriptor* value) const = 0;
|
||||
// Get a mutable pointer to a field with a message type. If a MessageFactory
|
||||
// is provided, it will be used to construct instances of the sub-message;
|
||||
// otherwise, the default factory is used. If the field is an extension that
|
||||
// does not live in the same pool as the containing message's descriptor (e.g.
|
||||
// it lives in an overlay pool), then a MessageFactory must be provided.
|
||||
// If you have no idea what that meant, then you probably don't need to worry
|
||||
// about it (don't provide a MessageFactory). WARNING: If the
|
||||
// FieldDescriptor is for a compiled-in extension, then
|
||||
// factory->GetPrototype(field->message_type() MUST return an instance of the
|
||||
// compiled-in class for this type, NOT DynamicMessage.
|
||||
virtual Message* MutableMessage(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const = 0;
|
||||
// Replaces the message specified by 'field' with the already-allocated object
|
||||
// sub_message, passing ownership to the message. If the field contained a
|
||||
// message, that message is deleted. If sub_message is NULL, the field is
|
||||
// cleared.
|
||||
virtual void SetAllocatedMessage(Message* message,
|
||||
Message* sub_message,
|
||||
const FieldDescriptor* field) const = 0;
|
||||
// Releases the message specified by 'field' and returns the pointer,
|
||||
// ReleaseMessage() will return the message the message object if it exists.
|
||||
// Otherwise, it may or may not return NULL. In any case, if the return value
|
||||
// is non-NULL, the caller takes ownership of the pointer.
|
||||
// If the field existed (HasField() is true), then the returned pointer will
|
||||
// be the same as the pointer returned by MutableMessage().
|
||||
// This function has the same effect as ClearField().
|
||||
virtual Message* ReleaseMessage(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const = 0;
|
||||
|
||||
|
||||
// Repeated field getters ------------------------------------------
|
||||
// These get the value of one element of a repeated field.
|
||||
|
||||
virtual int32 GetRepeatedInt32 (const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const = 0;
|
||||
virtual int64 GetRepeatedInt64 (const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const = 0;
|
||||
virtual uint32 GetRepeatedUInt32(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const = 0;
|
||||
virtual uint64 GetRepeatedUInt64(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const = 0;
|
||||
virtual float GetRepeatedFloat (const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const = 0;
|
||||
virtual double GetRepeatedDouble(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const = 0;
|
||||
virtual bool GetRepeatedBool (const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const = 0;
|
||||
virtual string GetRepeatedString(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const = 0;
|
||||
virtual const EnumValueDescriptor* GetRepeatedEnum(
|
||||
const Message& message,
|
||||
const FieldDescriptor* field, int index) const = 0;
|
||||
virtual const Message& GetRepeatedMessage(
|
||||
const Message& message,
|
||||
const FieldDescriptor* field, int index) const = 0;
|
||||
|
||||
// See GetStringReference(), above.
|
||||
virtual const string& GetRepeatedStringReference(
|
||||
const Message& message, const FieldDescriptor* field,
|
||||
int index, string* scratch) const = 0;
|
||||
|
||||
|
||||
// Repeated field mutators -----------------------------------------
|
||||
// These mutate the value of one element of a repeated field.
|
||||
|
||||
virtual void SetRepeatedInt32 (Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index, int32 value) const = 0;
|
||||
virtual void SetRepeatedInt64 (Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index, int64 value) const = 0;
|
||||
virtual void SetRepeatedUInt32(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index, uint32 value) const = 0;
|
||||
virtual void SetRepeatedUInt64(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index, uint64 value) const = 0;
|
||||
virtual void SetRepeatedFloat (Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index, float value) const = 0;
|
||||
virtual void SetRepeatedDouble(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index, double value) const = 0;
|
||||
virtual void SetRepeatedBool (Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index, bool value) const = 0;
|
||||
virtual void SetRepeatedString(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index, const string& value) const = 0;
|
||||
virtual void SetRepeatedEnum(Message* message,
|
||||
const FieldDescriptor* field, int index,
|
||||
const EnumValueDescriptor* value) const = 0;
|
||||
// Get a mutable pointer to an element of a repeated field with a message
|
||||
// type.
|
||||
virtual Message* MutableRepeatedMessage(
|
||||
Message* message, const FieldDescriptor* field, int index) const = 0;
|
||||
|
||||
|
||||
// Repeated field adders -------------------------------------------
|
||||
// These add an element to a repeated field.
|
||||
|
||||
virtual void AddInt32 (Message* message,
|
||||
const FieldDescriptor* field, int32 value) const = 0;
|
||||
virtual void AddInt64 (Message* message,
|
||||
const FieldDescriptor* field, int64 value) const = 0;
|
||||
virtual void AddUInt32(Message* message,
|
||||
const FieldDescriptor* field, uint32 value) const = 0;
|
||||
virtual void AddUInt64(Message* message,
|
||||
const FieldDescriptor* field, uint64 value) const = 0;
|
||||
virtual void AddFloat (Message* message,
|
||||
const FieldDescriptor* field, float value) const = 0;
|
||||
virtual void AddDouble(Message* message,
|
||||
const FieldDescriptor* field, double value) const = 0;
|
||||
virtual void AddBool (Message* message,
|
||||
const FieldDescriptor* field, bool value) const = 0;
|
||||
virtual void AddString(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
const string& value) const = 0;
|
||||
virtual void AddEnum (Message* message,
|
||||
const FieldDescriptor* field,
|
||||
const EnumValueDescriptor* value) const = 0;
|
||||
// See MutableMessage() for comments on the "factory" parameter.
|
||||
virtual Message* AddMessage(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
MessageFactory* factory = NULL) const = 0;
|
||||
|
||||
|
||||
// Repeated field accessors -------------------------------------------------
|
||||
// The methods above, e.g. GetRepeatedInt32(msg, fd, index), provide singular
|
||||
// access to the data in a RepeatedField. The methods below provide aggregate
|
||||
// access by exposing the RepeatedField object itself with the Message.
|
||||
// Applying these templates to inappropriate types will lead to an undefined
|
||||
// reference at link time (e.g. GetRepeatedField<***double>), or possibly a
|
||||
// template matching error at compile time (e.g. GetRepeatedPtrField<File>).
|
||||
//
|
||||
// Usage example: my_doubs = refl->GetRepeatedField<double>(msg, fd);
|
||||
|
||||
// for T = Cord and all protobuf scalar types except enums.
|
||||
template<typename T>
|
||||
const RepeatedField<T>& GetRepeatedField(
|
||||
const Message&, const FieldDescriptor*) const;
|
||||
|
||||
// for T = Cord and all protobuf scalar types except enums.
|
||||
template<typename T>
|
||||
RepeatedField<T>* MutableRepeatedField(
|
||||
Message*, const FieldDescriptor*) const;
|
||||
|
||||
// for T = string, google::protobuf::internal::StringPieceField
|
||||
// google::protobuf::Message & descendants.
|
||||
template<typename T>
|
||||
const RepeatedPtrField<T>& GetRepeatedPtrField(
|
||||
const Message&, const FieldDescriptor*) const;
|
||||
|
||||
// for T = string, google::protobuf::internal::StringPieceField
|
||||
// google::protobuf::Message & descendants.
|
||||
template<typename T>
|
||||
RepeatedPtrField<T>* MutableRepeatedPtrField(
|
||||
Message*, const FieldDescriptor*) const;
|
||||
|
||||
// Extensions ----------------------------------------------------------------
|
||||
|
||||
// Try to find an extension of this message type by fully-qualified field
|
||||
// name. Returns NULL if no extension is known for this name or number.
|
||||
virtual const FieldDescriptor* FindKnownExtensionByName(
|
||||
const string& name) const = 0;
|
||||
|
||||
// Try to find an extension of this message type by field number.
|
||||
// Returns NULL if no extension is known for this name or number.
|
||||
virtual const FieldDescriptor* FindKnownExtensionByNumber(
|
||||
int number) const = 0;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
protected:
|
||||
// Obtain a pointer to a Repeated Field Structure and do some type checking:
|
||||
// on field->cpp_type(),
|
||||
// on field->field_option().ctype() (if ctype >= 0)
|
||||
// of field->message_type() (if message_type != NULL).
|
||||
// We use 1 routine rather than 4 (const vs mutable) x (scalar vs pointer).
|
||||
virtual void* MutableRawRepeatedField(
|
||||
Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
|
||||
int ctype, const Descriptor* message_type) const = 0;
|
||||
|
||||
private:
|
||||
// Special version for specialized implementations of string. We can't call
|
||||
// MutableRawRepeatedField directly here because we don't have access to
|
||||
// FieldOptions::* which are defined in descriptor.pb.h. Including that
|
||||
// file here is not possible because it would cause a circular include cycle.
|
||||
void* MutableRawRepeatedString(
|
||||
Message* message, const FieldDescriptor* field, bool is_string) const;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection);
|
||||
};
|
||||
|
||||
// Abstract interface for a factory for message objects.
|
||||
class LIBPROTOBUF_EXPORT MessageFactory {
|
||||
public:
|
||||
inline MessageFactory() {}
|
||||
virtual ~MessageFactory();
|
||||
|
||||
// Given a Descriptor, gets or constructs the default (prototype) Message
|
||||
// of that type. You can then call that message's New() method to construct
|
||||
// a mutable message of that type.
|
||||
//
|
||||
// Calling this method twice with the same Descriptor returns the same
|
||||
// object. The returned object remains property of the factory. Also, any
|
||||
// objects created by calling the prototype's New() method share some data
|
||||
// with the prototype, so these must be destroyed before the MessageFactory
|
||||
// is destroyed.
|
||||
//
|
||||
// The given descriptor must outlive the returned message, and hence must
|
||||
// outlive the MessageFactory.
|
||||
//
|
||||
// Some implementations do not support all types. GetPrototype() will
|
||||
// return NULL if the descriptor passed in is not supported.
|
||||
//
|
||||
// This method may or may not be thread-safe depending on the implementation.
|
||||
// Each implementation should document its own degree thread-safety.
|
||||
virtual const Message* GetPrototype(const Descriptor* type) = 0;
|
||||
|
||||
// Gets a MessageFactory which supports all generated, compiled-in messages.
|
||||
// In other words, for any compiled-in type FooMessage, the following is true:
|
||||
// MessageFactory::generated_factory()->GetPrototype(
|
||||
// FooMessage::descriptor()) == FooMessage::default_instance()
|
||||
// This factory supports all types which are found in
|
||||
// DescriptorPool::generated_pool(). If given a descriptor from any other
|
||||
// pool, GetPrototype() will return NULL. (You can also check if a
|
||||
// descriptor is for a generated message by checking if
|
||||
// descriptor->file()->pool() == DescriptorPool::generated_pool().)
|
||||
//
|
||||
// This factory is 100% thread-safe; calling GetPrototype() does not modify
|
||||
// any shared data.
|
||||
//
|
||||
// This factory is a singleton. The caller must not delete the object.
|
||||
static MessageFactory* generated_factory();
|
||||
|
||||
// For internal use only: Registers a .proto file at static initialization
|
||||
// time, to be placed in generated_factory. The first time GetPrototype()
|
||||
// is called with a descriptor from this file, |register_messages| will be
|
||||
// called, with the file name as the parameter. It must call
|
||||
// InternalRegisterGeneratedMessage() (below) to register each message type
|
||||
// in the file. This strange mechanism is necessary because descriptors are
|
||||
// built lazily, so we can't register types by their descriptor until we
|
||||
// know that the descriptor exists. |filename| must be a permanent string.
|
||||
static void InternalRegisterGeneratedFile(
|
||||
const char* filename, void (*register_messages)(const string&));
|
||||
|
||||
// For internal use only: Registers a message type. Called only by the
|
||||
// functions which are registered with InternalRegisterGeneratedFile(),
|
||||
// above.
|
||||
static void InternalRegisterGeneratedMessage(const Descriptor* descriptor,
|
||||
const Message* prototype);
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFactory);
|
||||
};
|
||||
|
||||
#define DECLARE_GET_REPEATED_FIELD(TYPE) \
|
||||
template<> \
|
||||
LIBPROTOBUF_EXPORT \
|
||||
const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>( \
|
||||
const Message& message, const FieldDescriptor* field) const; \
|
||||
\
|
||||
template<> \
|
||||
RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>( \
|
||||
Message* message, const FieldDescriptor* field) const;
|
||||
|
||||
DECLARE_GET_REPEATED_FIELD(int32)
|
||||
DECLARE_GET_REPEATED_FIELD(int64)
|
||||
DECLARE_GET_REPEATED_FIELD(uint32)
|
||||
DECLARE_GET_REPEATED_FIELD(uint64)
|
||||
DECLARE_GET_REPEATED_FIELD(float)
|
||||
DECLARE_GET_REPEATED_FIELD(double)
|
||||
DECLARE_GET_REPEATED_FIELD(bool)
|
||||
|
||||
#undef DECLARE_GET_REPEATED_FIELD
|
||||
|
||||
// =============================================================================
|
||||
// Implementation details for {Get,Mutable}RawRepeatedPtrField. We provide
|
||||
// specializations for <string>, <StringPieceField> and <Message> and handle
|
||||
// everything else with the default template which will match any type having
|
||||
// a method with signature "static const google::protobuf::Descriptor* descriptor()".
|
||||
// Such a type presumably is a descendant of google::protobuf::Message.
|
||||
|
||||
template<>
|
||||
inline const RepeatedPtrField<string>& Reflection::GetRepeatedPtrField<string>(
|
||||
const Message& message, const FieldDescriptor* field) const {
|
||||
return *static_cast<RepeatedPtrField<string>* >(
|
||||
MutableRawRepeatedString(const_cast<Message*>(&message), field, true));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline RepeatedPtrField<string>* Reflection::MutableRepeatedPtrField<string>(
|
||||
Message* message, const FieldDescriptor* field) const {
|
||||
return static_cast<RepeatedPtrField<string>* >(
|
||||
MutableRawRepeatedString(message, field, true));
|
||||
}
|
||||
|
||||
|
||||
// -----
|
||||
|
||||
template<>
|
||||
inline const RepeatedPtrField<Message>& Reflection::GetRepeatedPtrField(
|
||||
const Message& message, const FieldDescriptor* field) const {
|
||||
return *static_cast<RepeatedPtrField<Message>* >(
|
||||
MutableRawRepeatedField(const_cast<Message*>(&message), field,
|
||||
FieldDescriptor::CPPTYPE_MESSAGE, -1,
|
||||
NULL));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline RepeatedPtrField<Message>* Reflection::MutableRepeatedPtrField(
|
||||
Message* message, const FieldDescriptor* field) const {
|
||||
return static_cast<RepeatedPtrField<Message>* >(
|
||||
MutableRawRepeatedField(message, field,
|
||||
FieldDescriptor::CPPTYPE_MESSAGE, -1,
|
||||
NULL));
|
||||
}
|
||||
|
||||
template<typename PB>
|
||||
inline const RepeatedPtrField<PB>& Reflection::GetRepeatedPtrField(
|
||||
const Message& message, const FieldDescriptor* field) const {
|
||||
return *static_cast<RepeatedPtrField<PB>* >(
|
||||
MutableRawRepeatedField(const_cast<Message*>(&message), field,
|
||||
FieldDescriptor::CPPTYPE_MESSAGE, -1,
|
||||
PB::default_instance().GetDescriptor()));
|
||||
}
|
||||
|
||||
template<typename PB>
|
||||
inline RepeatedPtrField<PB>* Reflection::MutableRepeatedPtrField(
|
||||
Message* message, const FieldDescriptor* field) const {
|
||||
return static_cast<RepeatedPtrField<PB>* >(
|
||||
MutableRawRepeatedField(message, field,
|
||||
FieldDescriptor::CPPTYPE_MESSAGE, -1,
|
||||
PB::default_instance().GetDescriptor()));
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_MESSAGE_H__
|
|
@ -0,0 +1,247 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Authors: wink@google.com (Wink Saville),
|
||||
// kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Defines MessageLite, the abstract interface implemented by all (lite
|
||||
// and non-lite) protocol message objects.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace io {
|
||||
class CodedInputStream;
|
||||
class CodedOutputStream;
|
||||
class ZeroCopyInputStream;
|
||||
class ZeroCopyOutputStream;
|
||||
}
|
||||
|
||||
// Interface to light weight protocol messages.
|
||||
//
|
||||
// This interface is implemented by all protocol message objects. Non-lite
|
||||
// messages additionally implement the Message interface, which is a
|
||||
// subclass of MessageLite. Use MessageLite instead when you only need
|
||||
// the subset of features which it supports -- namely, nothing that uses
|
||||
// descriptors or reflection. You can instruct the protocol compiler
|
||||
// to generate classes which implement only MessageLite, not the full
|
||||
// Message interface, by adding the following line to the .proto file:
|
||||
//
|
||||
// option optimize_for = LITE_RUNTIME;
|
||||
//
|
||||
// This is particularly useful on resource-constrained systems where
|
||||
// the full protocol buffers runtime library is too big.
|
||||
//
|
||||
// Note that on non-constrained systems (e.g. servers) when you need
|
||||
// to link in lots of protocol definitions, a better way to reduce
|
||||
// total code footprint is to use optimize_for = CODE_SIZE. This
|
||||
// will make the generated code smaller while still supporting all the
|
||||
// same features (at the expense of speed). optimize_for = LITE_RUNTIME
|
||||
// is best when you only have a small number of message types linked
|
||||
// into your binary, in which case the size of the protocol buffers
|
||||
// runtime itself is the biggest problem.
|
||||
class LIBPROTOBUF_EXPORT MessageLite {
|
||||
public:
|
||||
inline MessageLite() {}
|
||||
virtual ~MessageLite();
|
||||
|
||||
// Basic Operations ------------------------------------------------
|
||||
|
||||
// Get the name of this message type, e.g. "foo.bar.BazProto".
|
||||
virtual string GetTypeName() const = 0;
|
||||
|
||||
// Construct a new instance of the same type. Ownership is passed to the
|
||||
// caller.
|
||||
virtual MessageLite* New() const = 0;
|
||||
|
||||
// Clear all fields of the message and set them to their default values.
|
||||
// Clear() avoids freeing memory, assuming that any memory allocated
|
||||
// to hold parts of the message will be needed again to hold the next
|
||||
// message. If you actually want to free the memory used by a Message,
|
||||
// you must delete it.
|
||||
virtual void Clear() = 0;
|
||||
|
||||
// Quickly check if all required fields have values set.
|
||||
virtual bool IsInitialized() const = 0;
|
||||
|
||||
// This is not implemented for Lite messages -- it just returns "(cannot
|
||||
// determine missing fields for lite message)". However, it is implemented
|
||||
// for full messages. See message.h.
|
||||
virtual string InitializationErrorString() const;
|
||||
|
||||
// If |other| is the exact same class as this, calls MergeFrom(). Otherwise,
|
||||
// results are undefined (probably crash).
|
||||
virtual void CheckTypeAndMergeFrom(const MessageLite& other) = 0;
|
||||
|
||||
// Parsing ---------------------------------------------------------
|
||||
// Methods for parsing in protocol buffer format. Most of these are
|
||||
// just simple wrappers around MergeFromCodedStream(). Clear() will be called
|
||||
// before merging the input.
|
||||
|
||||
// Fill the message with a protocol buffer parsed from the given input
|
||||
// stream. Returns false on a read error or if the input is in the
|
||||
// wrong format.
|
||||
bool ParseFromCodedStream(io::CodedInputStream* input);
|
||||
// Like ParseFromCodedStream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromCodedStream(io::CodedInputStream* input);
|
||||
// Read a protocol buffer from the given zero-copy input stream. If
|
||||
// successful, the entire input will be consumed.
|
||||
bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
|
||||
// Like ParseFromZeroCopyStream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input);
|
||||
// Read a protocol buffer from the given zero-copy input stream, expecting
|
||||
// the message to be exactly "size" bytes long. If successful, exactly
|
||||
// this many bytes will have been consumed from the input.
|
||||
bool ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size);
|
||||
// Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
|
||||
// missing required fields.
|
||||
bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
|
||||
int size);
|
||||
// Parse a protocol buffer contained in a string.
|
||||
bool ParseFromString(const string& data);
|
||||
// Like ParseFromString(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromString(const string& data);
|
||||
// Parse a protocol buffer contained in an array of bytes.
|
||||
bool ParseFromArray(const void* data, int size);
|
||||
// Like ParseFromArray(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromArray(const void* data, int size);
|
||||
|
||||
|
||||
// Reads a protocol buffer from the stream and merges it into this
|
||||
// Message. Singular fields read from the input overwrite what is
|
||||
// already in the Message and repeated fields are appended to those
|
||||
// already present.
|
||||
//
|
||||
// It is the responsibility of the caller to call input->LastTagWas()
|
||||
// (for groups) or input->ConsumedEntireMessage() (for non-groups) after
|
||||
// this returns to verify that the message's end was delimited correctly.
|
||||
//
|
||||
// ParsefromCodedStream() is implemented as Clear() followed by
|
||||
// MergeFromCodedStream().
|
||||
bool MergeFromCodedStream(io::CodedInputStream* input);
|
||||
|
||||
// Like MergeFromCodedStream(), but succeeds even if required fields are
|
||||
// missing in the input.
|
||||
//
|
||||
// MergeFromCodedStream() is just implemented as MergePartialFromCodedStream()
|
||||
// followed by IsInitialized().
|
||||
virtual bool MergePartialFromCodedStream(io::CodedInputStream* input) = 0;
|
||||
|
||||
|
||||
// Serialization ---------------------------------------------------
|
||||
// Methods for serializing in protocol buffer format. Most of these
|
||||
// are just simple wrappers around ByteSize() and SerializeWithCachedSizes().
|
||||
|
||||
// Write a protocol buffer of this message to the given output. Returns
|
||||
// false on a write error. If the message is missing required fields,
|
||||
// this may GOOGLE_CHECK-fail.
|
||||
bool SerializeToCodedStream(io::CodedOutputStream* output) const;
|
||||
// Like SerializeToCodedStream(), but allows missing required fields.
|
||||
bool SerializePartialToCodedStream(io::CodedOutputStream* output) const;
|
||||
// Write the message to the given zero-copy output stream. All required
|
||||
// fields must be set.
|
||||
bool SerializeToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
|
||||
// Like SerializeToZeroCopyStream(), but allows missing required fields.
|
||||
bool SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
|
||||
// Serialize the message and store it in the given string. All required
|
||||
// fields must be set.
|
||||
bool SerializeToString(string* output) const;
|
||||
// Like SerializeToString(), but allows missing required fields.
|
||||
bool SerializePartialToString(string* output) const;
|
||||
// Serialize the message and store it in the given byte array. All required
|
||||
// fields must be set.
|
||||
bool SerializeToArray(void* data, int size) const;
|
||||
// Like SerializeToArray(), but allows missing required fields.
|
||||
bool SerializePartialToArray(void* data, int size) const;
|
||||
|
||||
// Make a string encoding the message. Is equivalent to calling
|
||||
// SerializeToString() on a string and using that. Returns the empty
|
||||
// string if SerializeToString() would have returned an error.
|
||||
// Note: If you intend to generate many such strings, you may
|
||||
// reduce heap fragmentation by instead re-using the same string
|
||||
// object with calls to SerializeToString().
|
||||
string SerializeAsString() const;
|
||||
// Like SerializeAsString(), but allows missing required fields.
|
||||
string SerializePartialAsString() const;
|
||||
|
||||
// Like SerializeToString(), but appends to the data to the string's existing
|
||||
// contents. All required fields must be set.
|
||||
bool AppendToString(string* output) const;
|
||||
// Like AppendToString(), but allows missing required fields.
|
||||
bool AppendPartialToString(string* output) const;
|
||||
|
||||
// Computes the serialized size of the message. This recursively calls
|
||||
// ByteSize() on all embedded messages. If a subclass does not override
|
||||
// this, it MUST override SetCachedSize().
|
||||
virtual int ByteSize() const = 0;
|
||||
|
||||
// Serializes the message without recomputing the size. The message must
|
||||
// not have changed since the last call to ByteSize(); if it has, the results
|
||||
// are undefined.
|
||||
virtual void SerializeWithCachedSizes(
|
||||
io::CodedOutputStream* output) const = 0;
|
||||
|
||||
// Like SerializeWithCachedSizes, but writes directly to *target, returning
|
||||
// a pointer to the byte immediately after the last byte written. "target"
|
||||
// must point at a byte array of at least ByteSize() bytes.
|
||||
virtual uint8* SerializeWithCachedSizesToArray(uint8* target) const;
|
||||
|
||||
// Returns the result of the last call to ByteSize(). An embedded message's
|
||||
// size is needed both to serialize it (because embedded messages are
|
||||
// length-delimited) and to compute the outer message's size. Caching
|
||||
// the size avoids computing it multiple times.
|
||||
//
|
||||
// ByteSize() does not automatically use the cached size when available
|
||||
// because this would require invalidating it every time the message was
|
||||
// modified, which would be too hard and expensive. (E.g. if a deeply-nested
|
||||
// sub-message is changed, all of its parents' cached sizes would need to be
|
||||
// invalidated, which is too much work for an otherwise inlined setter
|
||||
// method.)
|
||||
virtual int GetCachedSize() const = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite);
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
|
@ -0,0 +1,81 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// This header is logically internal, but is made public because it is used
|
||||
// from protocol-compiler-generated code, which may reside in other components.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_REFLECTION_OPS_H__
|
||||
#define GOOGLE_PROTOBUF_REFLECTION_OPS_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/message.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Basic operations that can be performed using reflection.
|
||||
// These can be used as a cheap way to implement the corresponding
|
||||
// methods of the Message interface, though they are likely to be
|
||||
// slower than implementations tailored for the specific message type.
|
||||
//
|
||||
// This class should stay limited to operations needed to implement
|
||||
// the Message interface.
|
||||
//
|
||||
// This class is really a namespace that contains only static methods.
|
||||
class LIBPROTOBUF_EXPORT ReflectionOps {
|
||||
public:
|
||||
static void Copy(const Message& from, Message* to);
|
||||
static void Merge(const Message& from, Message* to);
|
||||
static void Clear(Message* message);
|
||||
static bool IsInitialized(const Message& message);
|
||||
static void DiscardUnknownFields(Message* message);
|
||||
|
||||
// Finds all unset required fields in the message and adds their full
|
||||
// paths (e.g. "foo.bar[5].baz") to *names. "prefix" will be attached to
|
||||
// the front of each name.
|
||||
static void FindInitializationErrors(const Message& message,
|
||||
const string& prefix,
|
||||
vector<string>* errors);
|
||||
|
||||
private:
|
||||
// All methods are static. No need to construct.
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionOps);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_REFLECTION_OPS_H__
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,291 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// DEPRECATED: This module declares the abstract interfaces underlying proto2
|
||||
// RPC services. These are intented to be independent of any particular RPC
|
||||
// implementation, so that proto2 services can be used on top of a variety
|
||||
// of implementations. Starting with version 2.3.0, RPC implementations should
|
||||
// not try to build on these, but should instead provide code generator plugins
|
||||
// which generate code specific to the particular RPC implementation. This way
|
||||
// the generated code can be more appropriate for the implementation in use
|
||||
// and can avoid unnecessary layers of indirection.
|
||||
//
|
||||
//
|
||||
// When you use the protocol compiler to compile a service definition, it
|
||||
// generates two classes: An abstract interface for the service (with
|
||||
// methods matching the service definition) and a "stub" implementation.
|
||||
// A stub is just a type-safe wrapper around an RpcChannel which emulates a
|
||||
// local implementation of the service.
|
||||
//
|
||||
// For example, the service definition:
|
||||
// service MyService {
|
||||
// rpc Foo(MyRequest) returns(MyResponse);
|
||||
// }
|
||||
// will generate abstract interface "MyService" and class "MyService::Stub".
|
||||
// You could implement a MyService as follows:
|
||||
// class MyServiceImpl : public MyService {
|
||||
// public:
|
||||
// MyServiceImpl() {}
|
||||
// ~MyServiceImpl() {}
|
||||
//
|
||||
// // implements MyService ---------------------------------------
|
||||
//
|
||||
// void Foo(google::protobuf::RpcController* controller,
|
||||
// const MyRequest* request,
|
||||
// MyResponse* response,
|
||||
// Closure* done) {
|
||||
// // ... read request and fill in response ...
|
||||
// done->Run();
|
||||
// }
|
||||
// };
|
||||
// You would then register an instance of MyServiceImpl with your RPC server
|
||||
// implementation. (How to do that depends on the implementation.)
|
||||
//
|
||||
// To call a remote MyServiceImpl, first you need an RpcChannel connected to it.
|
||||
// How to construct a channel depends, again, on your RPC implementation.
|
||||
// Here we use a hypothentical "MyRpcChannel" as an example:
|
||||
// MyRpcChannel channel("rpc:hostname:1234/myservice");
|
||||
// MyRpcController controller;
|
||||
// MyServiceImpl::Stub stub(&channel);
|
||||
// FooRequest request;
|
||||
// FooRespnose response;
|
||||
//
|
||||
// // ... fill in request ...
|
||||
//
|
||||
// stub.Foo(&controller, request, &response, NewCallback(HandleResponse));
|
||||
//
|
||||
// On Thread-Safety:
|
||||
//
|
||||
// Different RPC implementations may make different guarantees about what
|
||||
// threads they may run callbacks on, and what threads the application is
|
||||
// allowed to use to call the RPC system. Portable software should be ready
|
||||
// for callbacks to be called on any thread, but should not try to call the
|
||||
// RPC system from any thread except for the ones on which it received the
|
||||
// callbacks. Realistically, though, simple software will probably want to
|
||||
// use a single-threaded RPC system while high-end software will want to
|
||||
// use multiple threads. RPC implementations should provide multiple
|
||||
// choices.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_SERVICE_H__
|
||||
#define GOOGLE_PROTOBUF_SERVICE_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Defined in this file.
|
||||
class Service;
|
||||
class RpcController;
|
||||
class RpcChannel;
|
||||
|
||||
// Defined in other files.
|
||||
class Descriptor; // descriptor.h
|
||||
class ServiceDescriptor; // descriptor.h
|
||||
class MethodDescriptor; // descriptor.h
|
||||
class Message; // message.h
|
||||
|
||||
// Abstract base interface for protocol-buffer-based RPC services. Services
|
||||
// themselves are abstract interfaces (implemented either by servers or as
|
||||
// stubs), but they subclass this base interface. The methods of this
|
||||
// interface can be used to call the methods of the Service without knowing
|
||||
// its exact type at compile time (analogous to Reflection).
|
||||
class LIBPROTOBUF_EXPORT Service {
|
||||
public:
|
||||
inline Service() {}
|
||||
virtual ~Service();
|
||||
|
||||
// When constructing a stub, you may pass STUB_OWNS_CHANNEL as the second
|
||||
// parameter to the constructor to tell it to delete its RpcChannel when
|
||||
// destroyed.
|
||||
enum ChannelOwnership {
|
||||
STUB_OWNS_CHANNEL,
|
||||
STUB_DOESNT_OWN_CHANNEL
|
||||
};
|
||||
|
||||
// Get the ServiceDescriptor describing this service and its methods.
|
||||
virtual const ServiceDescriptor* GetDescriptor() = 0;
|
||||
|
||||
// Call a method of the service specified by MethodDescriptor. This is
|
||||
// normally implemented as a simple switch() that calls the standard
|
||||
// definitions of the service's methods.
|
||||
//
|
||||
// Preconditions:
|
||||
// * method->service() == GetDescriptor()
|
||||
// * request and response are of the exact same classes as the objects
|
||||
// returned by GetRequestPrototype(method) and
|
||||
// GetResponsePrototype(method).
|
||||
// * After the call has started, the request must not be modified and the
|
||||
// response must not be accessed at all until "done" is called.
|
||||
// * "controller" is of the correct type for the RPC implementation being
|
||||
// used by this Service. For stubs, the "correct type" depends on the
|
||||
// RpcChannel which the stub is using. Server-side Service
|
||||
// implementations are expected to accept whatever type of RpcController
|
||||
// the server-side RPC implementation uses.
|
||||
//
|
||||
// Postconditions:
|
||||
// * "done" will be called when the method is complete. This may be
|
||||
// before CallMethod() returns or it may be at some point in the future.
|
||||
// * If the RPC succeeded, "response" contains the response returned by
|
||||
// the server.
|
||||
// * If the RPC failed, "response"'s contents are undefined. The
|
||||
// RpcController can be queried to determine if an error occurred and
|
||||
// possibly to get more information about the error.
|
||||
virtual void CallMethod(const MethodDescriptor* method,
|
||||
RpcController* controller,
|
||||
const Message* request,
|
||||
Message* response,
|
||||
Closure* done) = 0;
|
||||
|
||||
// CallMethod() requires that the request and response passed in are of a
|
||||
// particular subclass of Message. GetRequestPrototype() and
|
||||
// GetResponsePrototype() get the default instances of these required types.
|
||||
// You can then call Message::New() on these instances to construct mutable
|
||||
// objects which you can then pass to CallMethod().
|
||||
//
|
||||
// Example:
|
||||
// const MethodDescriptor* method =
|
||||
// service->GetDescriptor()->FindMethodByName("Foo");
|
||||
// Message* request = stub->GetRequestPrototype (method)->New();
|
||||
// Message* response = stub->GetResponsePrototype(method)->New();
|
||||
// request->ParseFromString(input);
|
||||
// service->CallMethod(method, *request, response, callback);
|
||||
virtual const Message& GetRequestPrototype(
|
||||
const MethodDescriptor* method) const = 0;
|
||||
virtual const Message& GetResponsePrototype(
|
||||
const MethodDescriptor* method) const = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Service);
|
||||
};
|
||||
|
||||
// An RpcController mediates a single method call. The primary purpose of
|
||||
// the controller is to provide a way to manipulate settings specific to the
|
||||
// RPC implementation and to find out about RPC-level errors.
|
||||
//
|
||||
// The methods provided by the RpcController interface are intended to be a
|
||||
// "least common denominator" set of features which we expect all
|
||||
// implementations to support. Specific implementations may provide more
|
||||
// advanced features (e.g. deadline propagation).
|
||||
class LIBPROTOBUF_EXPORT RpcController {
|
||||
public:
|
||||
inline RpcController() {}
|
||||
virtual ~RpcController();
|
||||
|
||||
// Client-side methods ---------------------------------------------
|
||||
// These calls may be made from the client side only. Their results
|
||||
// are undefined on the server side (may crash).
|
||||
|
||||
// Resets the RpcController to its initial state so that it may be reused in
|
||||
// a new call. Must not be called while an RPC is in progress.
|
||||
virtual void Reset() = 0;
|
||||
|
||||
// After a call has finished, returns true if the call failed. The possible
|
||||
// reasons for failure depend on the RPC implementation. Failed() must not
|
||||
// be called before a call has finished. If Failed() returns true, the
|
||||
// contents of the response message are undefined.
|
||||
virtual bool Failed() const = 0;
|
||||
|
||||
// If Failed() is true, returns a human-readable description of the error.
|
||||
virtual string ErrorText() const = 0;
|
||||
|
||||
// Advises the RPC system that the caller desires that the RPC call be
|
||||
// canceled. The RPC system may cancel it immediately, may wait awhile and
|
||||
// then cancel it, or may not even cancel the call at all. If the call is
|
||||
// canceled, the "done" callback will still be called and the RpcController
|
||||
// will indicate that the call failed at that time.
|
||||
virtual void StartCancel() = 0;
|
||||
|
||||
// Server-side methods ---------------------------------------------
|
||||
// These calls may be made from the server side only. Their results
|
||||
// are undefined on the client side (may crash).
|
||||
|
||||
// Causes Failed() to return true on the client side. "reason" will be
|
||||
// incorporated into the message returned by ErrorText(). If you find
|
||||
// you need to return machine-readable information about failures, you
|
||||
// should incorporate it into your response protocol buffer and should
|
||||
// NOT call SetFailed().
|
||||
virtual void SetFailed(const string& reason) = 0;
|
||||
|
||||
// If true, indicates that the client canceled the RPC, so the server may
|
||||
// as well give up on replying to it. The server should still call the
|
||||
// final "done" callback.
|
||||
virtual bool IsCanceled() const = 0;
|
||||
|
||||
// Asks that the given callback be called when the RPC is canceled. The
|
||||
// callback will always be called exactly once. If the RPC completes without
|
||||
// being canceled, the callback will be called after completion. If the RPC
|
||||
// has already been canceled when NotifyOnCancel() is called, the callback
|
||||
// will be called immediately.
|
||||
//
|
||||
// NotifyOnCancel() must be called no more than once per request.
|
||||
virtual void NotifyOnCancel(Closure* callback) = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcController);
|
||||
};
|
||||
|
||||
// Abstract interface for an RPC channel. An RpcChannel represents a
|
||||
// communication line to a Service which can be used to call that Service's
|
||||
// methods. The Service may be running on another machine. Normally, you
|
||||
// should not call an RpcChannel directly, but instead construct a stub Service
|
||||
// wrapping it. Example:
|
||||
// RpcChannel* channel = new MyRpcChannel("remotehost.example.com:1234");
|
||||
// MyService* service = new MyService::Stub(channel);
|
||||
// service->MyMethod(request, &response, callback);
|
||||
class LIBPROTOBUF_EXPORT RpcChannel {
|
||||
public:
|
||||
inline RpcChannel() {}
|
||||
virtual ~RpcChannel();
|
||||
|
||||
// Call the given method of the remote service. The signature of this
|
||||
// procedure looks the same as Service::CallMethod(), but the requirements
|
||||
// are less strict in one important way: the request and response objects
|
||||
// need not be of any specific class as long as their descriptors are
|
||||
// method->input_type() and method->output_type().
|
||||
virtual void CallMethod(const MethodDescriptor* method,
|
||||
RpcController* controller,
|
||||
const Message* request,
|
||||
Message* response,
|
||||
Closure* done) = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcChannel);
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_SERVICE_H__
|
|
@ -0,0 +1,227 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
|
||||
// The routines exported by this module are subtle. If you use them, even if
|
||||
// you get the code right, it will depend on careful reasoning about atomicity
|
||||
// and memory ordering; it will be less readable, and harder to maintain. If
|
||||
// you plan to use these routines, you should have a good reason, such as solid
|
||||
// evidence that performance would otherwise suffer, or there being no
|
||||
// alternative. You should assume only properties explicitly guaranteed by the
|
||||
// specifications in this file. You are almost certainly _not_ writing code
|
||||
// just for the x86; if you assume x86 semantics, x86 hardware bugs and
|
||||
// implementations on other archtectures will cause your code to break. If you
|
||||
// do not know what you are doing, avoid these routines, and use a Mutex.
|
||||
//
|
||||
// It is incorrect to make direct assignments to/from an atomic variable.
|
||||
// You should use one of the Load or Store routines. The NoBarrier
|
||||
// versions are provided when no barriers are needed:
|
||||
// NoBarrier_Store()
|
||||
// NoBarrier_Load()
|
||||
// Although there are currently no compiler enforcement, you are encouraged
|
||||
// to use these.
|
||||
|
||||
// This header and the implementations for each platform (located in
|
||||
// atomicops_internals_*) must be kept in sync with the upstream code (V8).
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_H_
|
||||
#define GOOGLE_PROTOBUF_ATOMICOPS_H_
|
||||
|
||||
// Don't include this file for people not concerned about thread safety.
|
||||
#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
|
||||
|
||||
#include <google/protobuf/stubs/platform_macros.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
typedef int32 Atomic32;
|
||||
#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
|
||||
// We need to be able to go between Atomic64 and AtomicWord implicitly. This
|
||||
// means Atomic64 and AtomicWord should be the same type on 64-bit.
|
||||
#if defined(__ILP32__) || defined(GOOGLE_PROTOBUF_OS_NACL) || defined(GOOGLE_PROTOBUF_ARCH_SPARC)
|
||||
// NaCl's intptr_t is not actually 64-bits on 64-bit!
|
||||
// http://code.google.com/p/nativeclient/issues/detail?id=1162
|
||||
// sparcv9's pointer type is 32bits
|
||||
typedef int64 Atomic64;
|
||||
#else
|
||||
typedef intptr_t Atomic64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or
|
||||
// Atomic64 routines below, depending on your architecture.
|
||||
typedef intptr_t AtomicWord;
|
||||
|
||||
// Atomically execute:
|
||||
// result = *ptr;
|
||||
// if (*ptr == old_value)
|
||||
// *ptr = new_value;
|
||||
// return result;
|
||||
//
|
||||
// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
|
||||
// Always return the old value of "*ptr"
|
||||
//
|
||||
// This routine implies no memory barriers.
|
||||
Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value);
|
||||
|
||||
// Atomically store new_value into *ptr, returning the previous value held in
|
||||
// *ptr. This routine implies no memory barriers.
|
||||
Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
|
||||
|
||||
// Atomically increment *ptr by "increment". Returns the new value of
|
||||
// *ptr with the increment applied. This routine implies no memory barriers.
|
||||
Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
|
||||
|
||||
Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment);
|
||||
|
||||
// These following lower-level operations are typically useful only to people
|
||||
// implementing higher-level synchronization operations like spinlocks,
|
||||
// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or
|
||||
// a store with appropriate memory-ordering instructions. "Acquire" operations
|
||||
// ensure that no later memory access can be reordered ahead of the operation.
|
||||
// "Release" operations ensure that no previous memory access can be reordered
|
||||
// after the operation. "Barrier" operations have both "Acquire" and "Release"
|
||||
// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory
|
||||
// access.
|
||||
Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value);
|
||||
Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value);
|
||||
|
||||
#if defined(__MINGW32__) && defined(MemoryBarrier)
|
||||
#undef MemoryBarrier
|
||||
#endif
|
||||
void MemoryBarrier();
|
||||
void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
|
||||
void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
|
||||
void Release_Store(volatile Atomic32* ptr, Atomic32 value);
|
||||
|
||||
Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
|
||||
Atomic32 Acquire_Load(volatile const Atomic32* ptr);
|
||||
Atomic32 Release_Load(volatile const Atomic32* ptr);
|
||||
|
||||
// 64-bit atomic operations (only available on 64-bit processors).
|
||||
#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
|
||||
Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value);
|
||||
Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
|
||||
Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
|
||||
Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
|
||||
|
||||
Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value);
|
||||
Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value);
|
||||
void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
|
||||
void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
|
||||
void Release_Store(volatile Atomic64* ptr, Atomic64 value);
|
||||
Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
|
||||
Atomic64 Acquire_Load(volatile const Atomic64* ptr);
|
||||
Atomic64 Release_Load(volatile const Atomic64* ptr);
|
||||
#endif // GOOGLE_PROTOBUF_ARCH_64_BIT
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// Include our platform specific implementation.
|
||||
#define GOOGLE_PROTOBUF_ATOMICOPS_ERROR \
|
||||
#error "Atomic operations are not supported on your platform"
|
||||
|
||||
// ThreadSanitizer, http://clang.llvm.org/docs/ThreadSanitizer.html.
|
||||
#if defined(THREAD_SANITIZER)
|
||||
#include <google/protobuf/stubs/atomicops_internals_tsan.h>
|
||||
// MSVC.
|
||||
#elif defined(_MSC_VER)
|
||||
#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64)
|
||||
#include <google/protobuf/stubs/atomicops_internals_x86_msvc.h>
|
||||
#else
|
||||
GOOGLE_PROTOBUF_ATOMICOPS_ERROR
|
||||
#endif
|
||||
|
||||
// Solaris
|
||||
#elif defined(GOOGLE_PROTOBUF_OS_SOLARIS)
|
||||
#include <google/protobuf/stubs/atomicops_internals_solaris.h>
|
||||
|
||||
// Apple.
|
||||
#elif defined(GOOGLE_PROTOBUF_OS_APPLE)
|
||||
#include <google/protobuf/stubs/atomicops_internals_macosx.h>
|
||||
|
||||
// GCC.
|
||||
#elif defined(__GNUC__)
|
||||
#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64)
|
||||
#include <google/protobuf/stubs/atomicops_internals_x86_gcc.h>
|
||||
#elif defined(GOOGLE_PROTOBUF_ARCH_ARM) && defined(__linux__)
|
||||
#include <google/protobuf/stubs/atomicops_internals_arm_gcc.h>
|
||||
#elif defined(GOOGLE_PROTOBUF_ARCH_AARCH64)
|
||||
#include <google/protobuf/stubs/atomicops_internals_arm64_gcc.h>
|
||||
#elif defined(GOOGLE_PROTOBUF_ARCH_ARM_QNX)
|
||||
#include <google/protobuf/stubs/atomicops_internals_arm_qnx.h>
|
||||
#elif defined(GOOGLE_PROTOBUF_ARCH_MIPS) || defined(GOOGLE_PROTOBUF_ARCH_MIPS64)
|
||||
#include <google/protobuf/stubs/atomicops_internals_mips_gcc.h>
|
||||
#elif defined(__native_client__)
|
||||
#include <google/protobuf/stubs/atomicops_internals_pnacl.h>
|
||||
#elif (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))
|
||||
#include <google/protobuf/stubs/atomicops_internals_generic_gcc.h>
|
||||
#elif defined(__clang__)
|
||||
#if __has_extension(c_atomic)
|
||||
#include <google/protobuf/stubs/atomicops_internals_generic_gcc.h>
|
||||
#else
|
||||
GOOGLE_PROTOBUF_ATOMICOPS_ERROR
|
||||
#endif
|
||||
#else
|
||||
GOOGLE_PROTOBUF_ATOMICOPS_ERROR
|
||||
#endif
|
||||
|
||||
// Unknown.
|
||||
#else
|
||||
GOOGLE_PROTOBUF_ATOMICOPS_ERROR
|
||||
#endif
|
||||
|
||||
// On some platforms we need additional declarations to make AtomicWord
|
||||
// compatible with our other Atomic* types.
|
||||
#if defined(GOOGLE_PROTOBUF_OS_APPLE)
|
||||
#include <google/protobuf/stubs/atomicops_internals_atomicword_compat.h>
|
||||
#endif
|
||||
|
||||
#undef GOOGLE_PROTOBUF_ATOMICOPS_ERROR
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ATOMICOPS_H_
|
|
@ -0,0 +1,150 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
|
||||
// This file is an internal atomic implementation, use atomicops.h instead.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
|
||||
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
return Barrier_AtomicIncrement(ptr, increment);
|
||||
}
|
||||
|
||||
#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
#error "We require at least vs2005 for MemoryBarrier"
|
||||
#endif
|
||||
|
||||
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
NoBarrier_AtomicExchange(ptr, value);
|
||||
// acts as a barrier in this implementation
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value; // works w/o barrier for current Intel chips as of June 2005
|
||||
// See comments in Atomic64 version of Release_Store() below.
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
|
||||
Atomic32 value = *ptr;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#if defined(_WIN64)
|
||||
|
||||
// 64-bit low-level operations on 64-bit platform.
|
||||
|
||||
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
return Barrier_AtomicIncrement(ptr, increment);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
NoBarrier_AtomicExchange(ptr, value);
|
||||
// acts as a barrier in this implementation
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value; // works w/o barrier for current Intel chips as of June 2005
|
||||
|
||||
// When new chips come out, check:
|
||||
// IA-32 Intel Architecture Software Developer's Manual, Volume 3:
|
||||
// System Programming Guide, Chatper 7: Multiple-processor management,
|
||||
// Section 7.2, Memory Ordering.
|
||||
// Last seen at:
|
||||
// http://developer.intel.com/design/pentium4/manuals/index_new.htm
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
|
||||
Atomic64 value = *ptr;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
#endif // defined(_WIN64)
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,166 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// emulates google3/base/once.h
|
||||
//
|
||||
// This header is intended to be included only by internal .cc files and
|
||||
// generated .pb.cc files. Users should not use this directly.
|
||||
//
|
||||
// This is basically a portable version of pthread_once().
|
||||
//
|
||||
// This header declares:
|
||||
// * A type called ProtobufOnceType.
|
||||
// * A macro GOOGLE_PROTOBUF_DECLARE_ONCE() which declares a variable of type
|
||||
// ProtobufOnceType. This is the only legal way to declare such a variable.
|
||||
// The macro may only be used at the global scope (you cannot create local or
|
||||
// class member variables of this type).
|
||||
// * A function GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()).
|
||||
// This function, when invoked multiple times given the same ProtobufOnceType
|
||||
// object, will invoke init_func on the first call only, and will make sure
|
||||
// none of the calls return before that first call to init_func has finished.
|
||||
// * The user can provide a parameter which GoogleOnceInit() forwards to the
|
||||
// user-provided function when it is called. Usage example:
|
||||
// int a = 10;
|
||||
// GoogleOnceInit(&my_once, &MyFunctionExpectingIntArgument, &a);
|
||||
// * This implementation guarantees that ProtobufOnceType is a POD (i.e. no
|
||||
// static initializer generated).
|
||||
//
|
||||
// This implements a way to perform lazy initialization. It's more efficient
|
||||
// than using mutexes as no lock is needed if initialization has already
|
||||
// happened.
|
||||
//
|
||||
// Example usage:
|
||||
// void Init();
|
||||
// GOOGLE_PROTOBUF_DECLARE_ONCE(once_init);
|
||||
//
|
||||
// // Calls Init() exactly once.
|
||||
// void InitOnce() {
|
||||
// GoogleOnceInit(&once_init, &Init);
|
||||
// }
|
||||
//
|
||||
// Note that if GoogleOnceInit() is called before main() has begun, it must
|
||||
// only be called by the thread that will eventually call main() -- that is,
|
||||
// the thread that performs dynamic initialization. In general this is a safe
|
||||
// assumption since people don't usually construct threads before main() starts,
|
||||
// but it is technically not guaranteed. Unfortunately, Win32 provides no way
|
||||
// whatsoever to statically-initialize its synchronization primitives, so our
|
||||
// only choice is to assume that dynamic initialization is single-threaded.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
||||
|
||||
#include <google/protobuf/stubs/atomicops.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
|
||||
|
||||
typedef bool ProtobufOnceType;
|
||||
|
||||
#define GOOGLE_PROTOBUF_ONCE_INIT false
|
||||
|
||||
inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) {
|
||||
if (!*once) {
|
||||
*once = true;
|
||||
init_func();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg),
|
||||
Arg arg) {
|
||||
if (!*once) {
|
||||
*once = true;
|
||||
init_func(arg);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
enum {
|
||||
ONCE_STATE_UNINITIALIZED = 0,
|
||||
ONCE_STATE_EXECUTING_CLOSURE = 1,
|
||||
ONCE_STATE_DONE = 2
|
||||
};
|
||||
|
||||
typedef internal::AtomicWord ProtobufOnceType;
|
||||
|
||||
#define GOOGLE_PROTOBUF_ONCE_INIT ::google::protobuf::ONCE_STATE_UNINITIALIZED
|
||||
|
||||
LIBPROTOBUF_EXPORT
|
||||
void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure);
|
||||
|
||||
inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) {
|
||||
if (internal::Acquire_Load(once) != ONCE_STATE_DONE) {
|
||||
internal::FunctionClosure0 func(init_func, false);
|
||||
GoogleOnceInitImpl(once, &func);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg*),
|
||||
Arg* arg) {
|
||||
if (internal::Acquire_Load(once) != ONCE_STATE_DONE) {
|
||||
internal::FunctionClosure1<Arg*> func(init_func, false, arg);
|
||||
GoogleOnceInitImpl(once, &func);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY
|
||||
|
||||
class GoogleOnceDynamic {
|
||||
public:
|
||||
GoogleOnceDynamic() : state_(GOOGLE_PROTOBUF_ONCE_INIT) { }
|
||||
|
||||
// If this->Init() has not been called before by any thread,
|
||||
// execute (*func_with_arg)(arg) then return.
|
||||
// Otherwise, wait until that prior invocation has finished
|
||||
// executing its function, then return.
|
||||
template<typename T>
|
||||
void Init(void (*func_with_arg)(T*), T* arg) {
|
||||
GoogleOnceInit<T>(&this->state_,
|
||||
func_with_arg,
|
||||
arg);
|
||||
}
|
||||
private:
|
||||
ProtobufOnceType state_;
|
||||
};
|
||||
|
||||
#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \
|
||||
::google::protobuf::ProtobufOnceType NAME = GOOGLE_PROTOBUF_ONCE_INIT
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
|
@ -0,0 +1,103 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
|
||||
#define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#define GOOGLE_PROTOBUF_PLATFORM_ERROR \
|
||||
#error "Host platform was not detected as supported by protobuf"
|
||||
|
||||
// Processor architecture detection. For more info on what's defined, see:
|
||||
// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
|
||||
// http://www.agner.org/optimize/calling_conventions.pdf
|
||||
// or with gcc, run: "echo | gcc -E -dM -"
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_X64 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(_M_IX86) || defined(__i386__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_IA32 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__QNX__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__ARMEL__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_ARM 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__aarch64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_AARCH64 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(__MIPSEL__)
|
||||
#if defined(__LP64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_MIPS64 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#else
|
||||
#define GOOGLE_PROTOBUF_ARCH_MIPS 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#endif
|
||||
#elif defined(__pnacl__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(sparc)
|
||||
#define GOOGLE_PROTOBUF_ARCH_SPARC 1
|
||||
#ifdef SOLARIS_64BIT_ENABLED
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#else
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
# if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))
|
||||
// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h
|
||||
# elif defined(__clang__)
|
||||
# if !__has_extension(c_atomic)
|
||||
GOOGLE_PROTOBUF_PLATFORM_ERROR
|
||||
# endif
|
||||
// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h
|
||||
# endif
|
||||
# if __LP64__
|
||||
# define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
# else
|
||||
# define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
# endif
|
||||
#else
|
||||
GOOGLE_PROTOBUF_PLATFORM_ERROR
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#define GOOGLE_PROTOBUF_OS_APPLE
|
||||
#elif defined(__native_client__)
|
||||
#define GOOGLE_PROTOBUF_OS_NACL
|
||||
#elif defined(sun)
|
||||
#define GOOGLE_PROTOBUF_OS_SOLARIS
|
||||
#endif
|
||||
|
||||
#undef GOOGLE_PROTOBUF_PLATFORM_ERROR
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
|
|
@ -0,0 +1,138 @@
|
|||
// Copyright 2005 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// 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: lar@google.com (Laramie Leavitt)
|
||||
//
|
||||
// Template metaprogramming utility functions.
|
||||
//
|
||||
// This code is compiled directly on many platforms, including client
|
||||
// platforms like Windows, Mac, and embedded systems. Before making
|
||||
// any changes here, make sure that you're not breaking any platforms.
|
||||
//
|
||||
//
|
||||
// The names choosen here reflect those used in tr1 and the boost::mpl
|
||||
// library, there are similar operations used in the Loki library as
|
||||
// well. I prefer the boost names for 2 reasons:
|
||||
// 1. I think that portions of the Boost libraries are more likely to
|
||||
// be included in the c++ standard.
|
||||
// 2. It is not impossible that some of the boost libraries will be
|
||||
// included in our own build in the future.
|
||||
// Both of these outcomes means that we may be able to directly replace
|
||||
// some of these with boost equivalents.
|
||||
//
|
||||
#ifndef GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
|
||||
#define GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Types small_ and big_ are guaranteed such that sizeof(small_) <
|
||||
// sizeof(big_)
|
||||
typedef char small_;
|
||||
|
||||
struct big_ {
|
||||
char dummy[2];
|
||||
};
|
||||
|
||||
// Identity metafunction.
|
||||
template <class T>
|
||||
struct identity_ {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
// integral_constant, defined in tr1, is a wrapper for an integer
|
||||
// value. We don't really need this generality; we could get away
|
||||
// with hardcoding the integer type to bool. We use the fully
|
||||
// general integer_constant for compatibility with tr1.
|
||||
|
||||
template<class T, T v>
|
||||
struct integral_constant {
|
||||
static const T value = v;
|
||||
typedef T value_type;
|
||||
typedef integral_constant<T, v> type;
|
||||
};
|
||||
|
||||
template <class T, T v> const T integral_constant<T, v>::value;
|
||||
|
||||
|
||||
// Abbreviations: true_type and false_type are structs that represent boolean
|
||||
// true and false values. Also define the boost::mpl versions of those names,
|
||||
// true_ and false_.
|
||||
typedef integral_constant<bool, true> true_type;
|
||||
typedef integral_constant<bool, false> false_type;
|
||||
typedef true_type true_;
|
||||
typedef false_type false_;
|
||||
|
||||
// if_ is a templatized conditional statement.
|
||||
// if_<cond, A, B> is a compile time evaluation of cond.
|
||||
// if_<>::type contains A if cond is true, B otherwise.
|
||||
template<bool cond, typename A, typename B>
|
||||
struct if_{
|
||||
typedef A type;
|
||||
};
|
||||
|
||||
template<typename A, typename B>
|
||||
struct if_<false, A, B> {
|
||||
typedef B type;
|
||||
};
|
||||
|
||||
|
||||
// type_equals_ is a template type comparator, similar to Loki IsSameType.
|
||||
// type_equals_<A, B>::value is true iff "A" is the same type as "B".
|
||||
//
|
||||
// New code should prefer base::is_same, defined in base/type_traits.h.
|
||||
// It is functionally identical, but is_same is the standard spelling.
|
||||
template<typename A, typename B>
|
||||
struct type_equals_ : public false_ {
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
struct type_equals_<A, A> : public true_ {
|
||||
};
|
||||
|
||||
// and_ is a template && operator.
|
||||
// and_<A, B>::value evaluates "A::value && B::value".
|
||||
template<typename A, typename B>
|
||||
struct and_ : public integral_constant<bool, (A::value && B::value)> {
|
||||
};
|
||||
|
||||
// or_ is a template || operator.
|
||||
// or_<A, B>::value evaluates "A::value || B::value".
|
||||
template<typename A, typename B>
|
||||
struct or_ : public integral_constant<bool, (A::value || B::value)> {
|
||||
};
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
|
|
@ -0,0 +1,336 @@
|
|||
// Copyright (c) 2006, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// 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: Matt Austern
|
||||
//
|
||||
// This code is compiled directly on many platforms, including client
|
||||
// platforms like Windows, Mac, and embedded systems. Before making
|
||||
// any changes here, make sure that you're not breaking any platforms.
|
||||
//
|
||||
// Define a small subset of tr1 type traits. The traits we define are:
|
||||
// is_integral
|
||||
// is_floating_point
|
||||
// is_pointer
|
||||
// is_enum
|
||||
// is_reference
|
||||
// is_pod
|
||||
// has_trivial_constructor
|
||||
// has_trivial_copy
|
||||
// has_trivial_assign
|
||||
// has_trivial_destructor
|
||||
// remove_const
|
||||
// remove_volatile
|
||||
// remove_cv
|
||||
// remove_reference
|
||||
// add_reference
|
||||
// remove_pointer
|
||||
// is_same
|
||||
// is_convertible
|
||||
// We can add more type traits as required.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_
|
||||
#define GOOGLE_PROTOBUF_TYPE_TRAITS_H_
|
||||
|
||||
#include <utility> // For pair
|
||||
|
||||
#include <google/protobuf/stubs/template_util.h> // For true_type and false_type
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
template <class T> struct is_integral;
|
||||
template <class T> struct is_floating_point;
|
||||
template <class T> struct is_pointer;
|
||||
// MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least)
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
|
||||
// is_enum uses is_convertible, which is not available on MSVC.
|
||||
template <class T> struct is_enum;
|
||||
#endif
|
||||
template <class T> struct is_reference;
|
||||
template <class T> struct is_pod;
|
||||
template <class T> struct has_trivial_constructor;
|
||||
template <class T> struct has_trivial_copy;
|
||||
template <class T> struct has_trivial_assign;
|
||||
template <class T> struct has_trivial_destructor;
|
||||
template <class T> struct remove_const;
|
||||
template <class T> struct remove_volatile;
|
||||
template <class T> struct remove_cv;
|
||||
template <class T> struct remove_reference;
|
||||
template <class T> struct add_reference;
|
||||
template <class T> struct remove_pointer;
|
||||
template <class T, class U> struct is_same;
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
|
||||
template <class From, class To> struct is_convertible;
|
||||
#endif
|
||||
|
||||
// is_integral is false except for the built-in integer types. A
|
||||
// cv-qualified type is integral if and only if the underlying type is.
|
||||
template <class T> struct is_integral : false_type { };
|
||||
template<> struct is_integral<bool> : true_type { };
|
||||
template<> struct is_integral<char> : true_type { };
|
||||
template<> struct is_integral<unsigned char> : true_type { };
|
||||
template<> struct is_integral<signed char> : true_type { };
|
||||
#if defined(_MSC_VER)
|
||||
// wchar_t is not by default a distinct type from unsigned short in
|
||||
// Microsoft C.
|
||||
// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
|
||||
template<> struct is_integral<__wchar_t> : true_type { };
|
||||
#else
|
||||
template<> struct is_integral<wchar_t> : true_type { };
|
||||
#endif
|
||||
template<> struct is_integral<short> : true_type { };
|
||||
template<> struct is_integral<unsigned short> : true_type { };
|
||||
template<> struct is_integral<int> : true_type { };
|
||||
template<> struct is_integral<unsigned int> : true_type { };
|
||||
template<> struct is_integral<long> : true_type { };
|
||||
template<> struct is_integral<unsigned long> : true_type { };
|
||||
#ifdef HAVE_LONG_LONG
|
||||
template<> struct is_integral<long long> : true_type { };
|
||||
template<> struct is_integral<unsigned long long> : true_type { };
|
||||
#endif
|
||||
template <class T> struct is_integral<const T> : is_integral<T> { };
|
||||
template <class T> struct is_integral<volatile T> : is_integral<T> { };
|
||||
template <class T> struct is_integral<const volatile T> : is_integral<T> { };
|
||||
|
||||
// is_floating_point is false except for the built-in floating-point types.
|
||||
// A cv-qualified type is integral if and only if the underlying type is.
|
||||
template <class T> struct is_floating_point : false_type { };
|
||||
template<> struct is_floating_point<float> : true_type { };
|
||||
template<> struct is_floating_point<double> : true_type { };
|
||||
template<> struct is_floating_point<long double> : true_type { };
|
||||
template <class T> struct is_floating_point<const T>
|
||||
: is_floating_point<T> { };
|
||||
template <class T> struct is_floating_point<volatile T>
|
||||
: is_floating_point<T> { };
|
||||
template <class T> struct is_floating_point<const volatile T>
|
||||
: is_floating_point<T> { };
|
||||
|
||||
// is_pointer is false except for pointer types. A cv-qualified type (e.g.
|
||||
// "int* const", as opposed to "int const*") is cv-qualified if and only if
|
||||
// the underlying type is.
|
||||
template <class T> struct is_pointer : false_type { };
|
||||
template <class T> struct is_pointer<T*> : true_type { };
|
||||
template <class T> struct is_pointer<const T> : is_pointer<T> { };
|
||||
template <class T> struct is_pointer<volatile T> : is_pointer<T> { };
|
||||
template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
|
||||
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class T> struct is_class_or_union {
|
||||
template <class U> static small_ tester(void (U::*)());
|
||||
template <class U> static big_ tester(...);
|
||||
static const bool value = sizeof(tester<T>(0)) == sizeof(small_);
|
||||
};
|
||||
|
||||
// is_convertible chokes if the first argument is an array. That's why
|
||||
// we use add_reference here.
|
||||
template <bool NotUnum, class T> struct is_enum_impl
|
||||
: is_convertible<typename add_reference<T>::type, int> { };
|
||||
|
||||
template <class T> struct is_enum_impl<true, T> : false_type { };
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Specified by TR1 [4.5.1] primary type categories.
|
||||
|
||||
// Implementation note:
|
||||
//
|
||||
// Each type is either void, integral, floating point, array, pointer,
|
||||
// reference, member object pointer, member function pointer, enum,
|
||||
// union or class. Out of these, only integral, floating point, reference,
|
||||
// class and enum types are potentially convertible to int. Therefore,
|
||||
// if a type is not a reference, integral, floating point or class and
|
||||
// is convertible to int, it's a enum. Adding cv-qualification to a type
|
||||
// does not change whether it's an enum.
|
||||
//
|
||||
// Is-convertible-to-int check is done only if all other checks pass,
|
||||
// because it can't be used with some types (e.g. void or classes with
|
||||
// inaccessible conversion operators).
|
||||
template <class T> struct is_enum
|
||||
: internal::is_enum_impl<
|
||||
is_same<T, void>::value ||
|
||||
is_integral<T>::value ||
|
||||
is_floating_point<T>::value ||
|
||||
is_reference<T>::value ||
|
||||
internal::is_class_or_union<T>::value,
|
||||
T> { };
|
||||
|
||||
template <class T> struct is_enum<const T> : is_enum<T> { };
|
||||
template <class T> struct is_enum<volatile T> : is_enum<T> { };
|
||||
template <class T> struct is_enum<const volatile T> : is_enum<T> { };
|
||||
|
||||
#endif
|
||||
|
||||
// is_reference is false except for reference types.
|
||||
template<typename T> struct is_reference : false_type {};
|
||||
template<typename T> struct is_reference<T&> : true_type {};
|
||||
|
||||
|
||||
// We can't get is_pod right without compiler help, so fail conservatively.
|
||||
// We will assume it's false except for arithmetic types, enumerations,
|
||||
// pointers and cv-qualified versions thereof. Note that std::pair<T,U>
|
||||
// is not a POD even if T and U are PODs.
|
||||
template <class T> struct is_pod
|
||||
: integral_constant<bool, (is_integral<T>::value ||
|
||||
is_floating_point<T>::value ||
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
|
||||
// is_enum is not available on MSVC.
|
||||
is_enum<T>::value ||
|
||||
#endif
|
||||
is_pointer<T>::value)> { };
|
||||
template <class T> struct is_pod<const T> : is_pod<T> { };
|
||||
template <class T> struct is_pod<volatile T> : is_pod<T> { };
|
||||
template <class T> struct is_pod<const volatile T> : is_pod<T> { };
|
||||
|
||||
|
||||
// We can't get has_trivial_constructor right without compiler help, so
|
||||
// fail conservatively. We will assume it's false except for: (1) types
|
||||
// for which is_pod is true. (2) std::pair of types with trivial
|
||||
// constructors. (3) array of a type with a trivial constructor.
|
||||
// (4) const versions thereof.
|
||||
template <class T> struct has_trivial_constructor : is_pod<T> { };
|
||||
template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
|
||||
: integral_constant<bool,
|
||||
(has_trivial_constructor<T>::value &&
|
||||
has_trivial_constructor<U>::value)> { };
|
||||
template <class A, int N> struct has_trivial_constructor<A[N]>
|
||||
: has_trivial_constructor<A> { };
|
||||
template <class T> struct has_trivial_constructor<const T>
|
||||
: has_trivial_constructor<T> { };
|
||||
|
||||
// We can't get has_trivial_copy right without compiler help, so fail
|
||||
// conservatively. We will assume it's false except for: (1) types
|
||||
// for which is_pod is true. (2) std::pair of types with trivial copy
|
||||
// constructors. (3) array of a type with a trivial copy constructor.
|
||||
// (4) const versions thereof.
|
||||
template <class T> struct has_trivial_copy : is_pod<T> { };
|
||||
template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
|
||||
: integral_constant<bool,
|
||||
(has_trivial_copy<T>::value &&
|
||||
has_trivial_copy<U>::value)> { };
|
||||
template <class A, int N> struct has_trivial_copy<A[N]>
|
||||
: has_trivial_copy<A> { };
|
||||
template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
|
||||
|
||||
// We can't get has_trivial_assign right without compiler help, so fail
|
||||
// conservatively. We will assume it's false except for: (1) types
|
||||
// for which is_pod is true. (2) std::pair of types with trivial copy
|
||||
// constructors. (3) array of a type with a trivial assign constructor.
|
||||
template <class T> struct has_trivial_assign : is_pod<T> { };
|
||||
template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
|
||||
: integral_constant<bool,
|
||||
(has_trivial_assign<T>::value &&
|
||||
has_trivial_assign<U>::value)> { };
|
||||
template <class A, int N> struct has_trivial_assign<A[N]>
|
||||
: has_trivial_assign<A> { };
|
||||
|
||||
// We can't get has_trivial_destructor right without compiler help, so
|
||||
// fail conservatively. We will assume it's false except for: (1) types
|
||||
// for which is_pod is true. (2) std::pair of types with trivial
|
||||
// destructors. (3) array of a type with a trivial destructor.
|
||||
// (4) const versions thereof.
|
||||
template <class T> struct has_trivial_destructor : is_pod<T> { };
|
||||
template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
|
||||
: integral_constant<bool,
|
||||
(has_trivial_destructor<T>::value &&
|
||||
has_trivial_destructor<U>::value)> { };
|
||||
template <class A, int N> struct has_trivial_destructor<A[N]>
|
||||
: has_trivial_destructor<A> { };
|
||||
template <class T> struct has_trivial_destructor<const T>
|
||||
: has_trivial_destructor<T> { };
|
||||
|
||||
// Specified by TR1 [4.7.1]
|
||||
template<typename T> struct remove_const { typedef T type; };
|
||||
template<typename T> struct remove_const<T const> { typedef T type; };
|
||||
template<typename T> struct remove_volatile { typedef T type; };
|
||||
template<typename T> struct remove_volatile<T volatile> { typedef T type; };
|
||||
template<typename T> struct remove_cv {
|
||||
typedef typename remove_const<typename remove_volatile<T>::type>::type type;
|
||||
};
|
||||
|
||||
|
||||
// Specified by TR1 [4.7.2] Reference modifications.
|
||||
template<typename T> struct remove_reference { typedef T type; };
|
||||
template<typename T> struct remove_reference<T&> { typedef T type; };
|
||||
|
||||
template <typename T> struct add_reference { typedef T& type; };
|
||||
template <typename T> struct add_reference<T&> { typedef T& type; };
|
||||
|
||||
// Specified by TR1 [4.7.4] Pointer modifications.
|
||||
template<typename T> struct remove_pointer { typedef T type; };
|
||||
template<typename T> struct remove_pointer<T*> { typedef T type; };
|
||||
template<typename T> struct remove_pointer<T* const> { typedef T type; };
|
||||
template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
|
||||
template<typename T> struct remove_pointer<T* const volatile> {
|
||||
typedef T type; };
|
||||
|
||||
// Specified by TR1 [4.6] Relationships between types
|
||||
template<typename T, typename U> struct is_same : public false_type { };
|
||||
template<typename T> struct is_same<T, T> : public true_type { };
|
||||
|
||||
// Specified by TR1 [4.6] Relationships between types
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
|
||||
namespace internal {
|
||||
|
||||
// This class is an implementation detail for is_convertible, and you
|
||||
// don't need to know how it works to use is_convertible. For those
|
||||
// who care: we declare two different functions, one whose argument is
|
||||
// of type To and one with a variadic argument list. We give them
|
||||
// return types of different size, so we can use sizeof to trick the
|
||||
// compiler into telling us which function it would have chosen if we
|
||||
// had called it with an argument of type From. See Alexandrescu's
|
||||
// _Modern C++ Design_ for more details on this sort of trick.
|
||||
|
||||
template <typename From, typename To>
|
||||
struct ConvertHelper {
|
||||
static small_ Test(To);
|
||||
static big_ Test(...);
|
||||
static From Create();
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
// Inherits from true_type if From is convertible to To, false_type otherwise.
|
||||
template <typename From, typename To>
|
||||
struct is_convertible
|
||||
: integral_constant<bool,
|
||||
sizeof(internal::ConvertHelper<From, To>::Test(
|
||||
internal::ConvertHelper<From, To>::Create()))
|
||||
== sizeof(small_)> {
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_TYPE_TRAITS_H_
|
|
@ -0,0 +1,473 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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: jschorr@google.com (Joseph Schorr)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Utilities for printing and parsing protocol messages in a human-readable,
|
||||
// text-based format.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_TEXT_FORMAT_H__
|
||||
#define GOOGLE_PROTOBUF_TEXT_FORMAT_H__
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/message.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace io {
|
||||
class ErrorCollector; // tokenizer.h
|
||||
}
|
||||
|
||||
// This class implements protocol buffer text format. Printing and parsing
|
||||
// protocol messages in text format is useful for debugging and human editing
|
||||
// of messages.
|
||||
//
|
||||
// This class is really a namespace that contains only static methods.
|
||||
class LIBPROTOBUF_EXPORT TextFormat {
|
||||
public:
|
||||
// Outputs a textual representation of the given message to the given
|
||||
// output stream.
|
||||
static bool Print(const Message& message, io::ZeroCopyOutputStream* output);
|
||||
|
||||
// Print the fields in an UnknownFieldSet. They are printed by tag number
|
||||
// only. Embedded messages are heuristically identified by attempting to
|
||||
// parse them.
|
||||
static bool PrintUnknownFields(const UnknownFieldSet& unknown_fields,
|
||||
io::ZeroCopyOutputStream* output);
|
||||
|
||||
// Like Print(), but outputs directly to a string.
|
||||
static bool PrintToString(const Message& message, string* output);
|
||||
|
||||
// Like PrintUnknownFields(), but outputs directly to a string.
|
||||
static bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields,
|
||||
string* output);
|
||||
|
||||
// Outputs a textual representation of the value of the field supplied on
|
||||
// the message supplied. For non-repeated fields, an index of -1 must
|
||||
// be supplied. Note that this method will print the default value for a
|
||||
// field if it is not set.
|
||||
static void PrintFieldValueToString(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index,
|
||||
string* output);
|
||||
|
||||
// The default printer that converts scalar values from fields into
|
||||
// their string representation.
|
||||
// You can derive from this FieldValuePrinter if you want to have
|
||||
// fields to be printed in a different way and register it at the
|
||||
// Printer.
|
||||
class LIBPROTOBUF_EXPORT FieldValuePrinter {
|
||||
public:
|
||||
FieldValuePrinter();
|
||||
virtual ~FieldValuePrinter();
|
||||
virtual string PrintBool(bool val) const;
|
||||
virtual string PrintInt32(int32 val) const;
|
||||
virtual string PrintUInt32(uint32 val) const;
|
||||
virtual string PrintInt64(int64 val) const;
|
||||
virtual string PrintUInt64(uint64 val) const;
|
||||
virtual string PrintFloat(float val) const;
|
||||
virtual string PrintDouble(double val) const;
|
||||
virtual string PrintString(const string& val) const;
|
||||
virtual string PrintBytes(const string& val) const;
|
||||
virtual string PrintEnum(int32 val, const string& name) const;
|
||||
virtual string PrintFieldName(const Message& message,
|
||||
const Reflection* reflection,
|
||||
const FieldDescriptor* field) const;
|
||||
virtual string PrintMessageStart(const Message& message,
|
||||
int field_index,
|
||||
int field_count,
|
||||
bool single_line_mode) const;
|
||||
virtual string PrintMessageEnd(const Message& message,
|
||||
int field_index,
|
||||
int field_count,
|
||||
bool single_line_mode) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldValuePrinter);
|
||||
};
|
||||
|
||||
// Class for those users which require more fine-grained control over how
|
||||
// a protobuffer message is printed out.
|
||||
class LIBPROTOBUF_EXPORT Printer {
|
||||
public:
|
||||
Printer();
|
||||
~Printer();
|
||||
|
||||
// Like TextFormat::Print
|
||||
bool Print(const Message& message, io::ZeroCopyOutputStream* output) const;
|
||||
// Like TextFormat::PrintUnknownFields
|
||||
bool PrintUnknownFields(const UnknownFieldSet& unknown_fields,
|
||||
io::ZeroCopyOutputStream* output) const;
|
||||
// Like TextFormat::PrintToString
|
||||
bool PrintToString(const Message& message, string* output) const;
|
||||
// Like TextFormat::PrintUnknownFieldsToString
|
||||
bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields,
|
||||
string* output) const;
|
||||
// Like TextFormat::PrintFieldValueToString
|
||||
void PrintFieldValueToString(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index,
|
||||
string* output) const;
|
||||
|
||||
// Adjust the initial indent level of all output. Each indent level is
|
||||
// equal to two spaces.
|
||||
void SetInitialIndentLevel(int indent_level) {
|
||||
initial_indent_level_ = indent_level;
|
||||
}
|
||||
|
||||
// If printing in single line mode, then the entire message will be output
|
||||
// on a single line with no line breaks.
|
||||
void SetSingleLineMode(bool single_line_mode) {
|
||||
single_line_mode_ = single_line_mode;
|
||||
}
|
||||
|
||||
bool IsInSingleLineMode() {
|
||||
return single_line_mode_;
|
||||
}
|
||||
|
||||
// If use_field_number is true, uses field number instead of field name.
|
||||
void SetUseFieldNumber(bool use_field_number) {
|
||||
use_field_number_ = use_field_number;
|
||||
}
|
||||
|
||||
// Set true to print repeated primitives in a format like:
|
||||
// field_name: [1, 2, 3, 4]
|
||||
// instead of printing each value on its own line. Short format applies
|
||||
// only to primitive values -- i.e. everything except strings and
|
||||
// sub-messages/groups.
|
||||
void SetUseShortRepeatedPrimitives(bool use_short_repeated_primitives) {
|
||||
use_short_repeated_primitives_ = use_short_repeated_primitives;
|
||||
}
|
||||
|
||||
// Set true to output UTF-8 instead of ASCII. The only difference
|
||||
// is that bytes >= 0x80 in string fields will not be escaped,
|
||||
// because they are assumed to be part of UTF-8 multi-byte
|
||||
// sequences. This will change the default FieldValuePrinter.
|
||||
void SetUseUtf8StringEscaping(bool as_utf8);
|
||||
|
||||
// Set the default FieldValuePrinter that is used for all fields that
|
||||
// don't have a field-specific printer registered.
|
||||
// Takes ownership of the printer.
|
||||
void SetDefaultFieldValuePrinter(const FieldValuePrinter* printer);
|
||||
|
||||
// Sets whether we want to hide unknown fields or not.
|
||||
// Usually unknown fields are printed in a generic way that includes the
|
||||
// tag number of the field instead of field name. However, sometimes it
|
||||
// is useful to be able to print the message without unknown fields (e.g.
|
||||
// for the python protobuf version to maintain consistency between its pure
|
||||
// python and c++ implementations).
|
||||
void SetHideUnknownFields(bool hide) {
|
||||
hide_unknown_fields_ = hide;
|
||||
}
|
||||
|
||||
// If print_message_fields_in_index_order is true, print fields of a proto
|
||||
// message using the order defined in source code instead of the field
|
||||
// number. By default, use the field number order.
|
||||
void SetPrintMessageFieldsInIndexOrder(
|
||||
bool print_message_fields_in_index_order) {
|
||||
print_message_fields_in_index_order_ =
|
||||
print_message_fields_in_index_order;
|
||||
}
|
||||
|
||||
// Register a custom field-specific FieldValuePrinter for fields
|
||||
// with a particular FieldDescriptor.
|
||||
// Returns "true" if the registration succeeded, or "false", if there is
|
||||
// already a printer for that FieldDescriptor.
|
||||
// Takes ownership of the printer on successful registration.
|
||||
bool RegisterFieldValuePrinter(const FieldDescriptor* field,
|
||||
const FieldValuePrinter* printer);
|
||||
|
||||
private:
|
||||
// Forward declaration of an internal class used to print the text
|
||||
// output to the OutputStream (see text_format.cc for implementation).
|
||||
class TextGenerator;
|
||||
|
||||
// Internal Print method, used for writing to the OutputStream via
|
||||
// the TextGenerator class.
|
||||
void Print(const Message& message,
|
||||
TextGenerator& generator) const;
|
||||
|
||||
// Print a single field.
|
||||
void PrintField(const Message& message,
|
||||
const Reflection* reflection,
|
||||
const FieldDescriptor* field,
|
||||
TextGenerator& generator) const;
|
||||
|
||||
// Print a repeated primitive field in short form.
|
||||
void PrintShortRepeatedField(const Message& message,
|
||||
const Reflection* reflection,
|
||||
const FieldDescriptor* field,
|
||||
TextGenerator& generator) const;
|
||||
|
||||
// Print the name of a field -- i.e. everything that comes before the
|
||||
// ':' for a single name/value pair.
|
||||
void PrintFieldName(const Message& message,
|
||||
const Reflection* reflection,
|
||||
const FieldDescriptor* field,
|
||||
TextGenerator& generator) const;
|
||||
|
||||
// Outputs a textual representation of the value of the field supplied on
|
||||
// the message supplied or the default value if not set.
|
||||
void PrintFieldValue(const Message& message,
|
||||
const Reflection* reflection,
|
||||
const FieldDescriptor* field,
|
||||
int index,
|
||||
TextGenerator& generator) const;
|
||||
|
||||
// Print the fields in an UnknownFieldSet. They are printed by tag number
|
||||
// only. Embedded messages are heuristically identified by attempting to
|
||||
// parse them.
|
||||
void PrintUnknownFields(const UnknownFieldSet& unknown_fields,
|
||||
TextGenerator& generator) const;
|
||||
|
||||
int initial_indent_level_;
|
||||
|
||||
bool single_line_mode_;
|
||||
|
||||
bool use_field_number_;
|
||||
|
||||
bool use_short_repeated_primitives_;
|
||||
|
||||
bool hide_unknown_fields_;
|
||||
|
||||
bool print_message_fields_in_index_order_;
|
||||
|
||||
scoped_ptr<const FieldValuePrinter> default_field_value_printer_;
|
||||
typedef map<const FieldDescriptor*,
|
||||
const FieldValuePrinter*> CustomPrinterMap;
|
||||
CustomPrinterMap custom_printers_;
|
||||
};
|
||||
|
||||
// Parses a text-format protocol message from the given input stream to
|
||||
// the given message object. This function parses the format written
|
||||
// by Print().
|
||||
static bool Parse(io::ZeroCopyInputStream* input, Message* output);
|
||||
// Like Parse(), but reads directly from a string.
|
||||
static bool ParseFromString(const string& input, Message* output);
|
||||
|
||||
// Like Parse(), but the data is merged into the given message, as if
|
||||
// using Message::MergeFrom().
|
||||
static bool Merge(io::ZeroCopyInputStream* input, Message* output);
|
||||
// Like Merge(), but reads directly from a string.
|
||||
static bool MergeFromString(const string& input, Message* output);
|
||||
|
||||
// Parse the given text as a single field value and store it into the
|
||||
// given field of the given message. If the field is a repeated field,
|
||||
// the new value will be added to the end
|
||||
static bool ParseFieldValueFromString(const string& input,
|
||||
const FieldDescriptor* field,
|
||||
Message* message);
|
||||
|
||||
// Interface that TextFormat::Parser can use to find extensions.
|
||||
// This class may be extended in the future to find more information
|
||||
// like fields, etc.
|
||||
class LIBPROTOBUF_EXPORT Finder {
|
||||
public:
|
||||
virtual ~Finder();
|
||||
|
||||
// Try to find an extension of *message by fully-qualified field
|
||||
// name. Returns NULL if no extension is known for this name or number.
|
||||
virtual const FieldDescriptor* FindExtension(
|
||||
Message* message,
|
||||
const string& name) const = 0;
|
||||
};
|
||||
|
||||
// A location in the parsed text.
|
||||
struct ParseLocation {
|
||||
int line;
|
||||
int column;
|
||||
|
||||
ParseLocation() : line(-1), column(-1) {}
|
||||
ParseLocation(int line_param, int column_param)
|
||||
: line(line_param), column(column_param) {}
|
||||
};
|
||||
|
||||
// Data structure which is populated with the locations of each field
|
||||
// value parsed from the text.
|
||||
class LIBPROTOBUF_EXPORT ParseInfoTree {
|
||||
public:
|
||||
ParseInfoTree();
|
||||
~ParseInfoTree();
|
||||
|
||||
// Returns the parse location for index-th value of the field in the parsed
|
||||
// text. If none exists, returns a location with line = -1. Index should be
|
||||
// -1 for not-repeated fields.
|
||||
ParseLocation GetLocation(const FieldDescriptor* field, int index) const;
|
||||
|
||||
// Returns the parse info tree for the given field, which must be a message
|
||||
// type. The nested information tree is owned by the root tree and will be
|
||||
// deleted when it is deleted.
|
||||
ParseInfoTree* GetTreeForNested(const FieldDescriptor* field,
|
||||
int index) const;
|
||||
|
||||
private:
|
||||
// Allow the text format parser to record information into the tree.
|
||||
friend class TextFormat;
|
||||
|
||||
// Records the starting location of a single value for a field.
|
||||
void RecordLocation(const FieldDescriptor* field, ParseLocation location);
|
||||
|
||||
// Create and records a nested tree for a nested message field.
|
||||
ParseInfoTree* CreateNested(const FieldDescriptor* field);
|
||||
|
||||
// Defines the map from the index-th field descriptor to its parse location.
|
||||
typedef map<const FieldDescriptor*, vector<ParseLocation> > LocationMap;
|
||||
|
||||
// Defines the map from the index-th field descriptor to the nested parse
|
||||
// info tree.
|
||||
typedef map<const FieldDescriptor*, vector<ParseInfoTree*> > NestedMap;
|
||||
|
||||
LocationMap locations_;
|
||||
NestedMap nested_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParseInfoTree);
|
||||
};
|
||||
|
||||
// For more control over parsing, use this class.
|
||||
class LIBPROTOBUF_EXPORT Parser {
|
||||
public:
|
||||
Parser();
|
||||
~Parser();
|
||||
|
||||
// Like TextFormat::Parse().
|
||||
bool Parse(io::ZeroCopyInputStream* input, Message* output);
|
||||
// Like TextFormat::ParseFromString().
|
||||
bool ParseFromString(const string& input, Message* output);
|
||||
// Like TextFormat::Merge().
|
||||
bool Merge(io::ZeroCopyInputStream* input, Message* output);
|
||||
// Like TextFormat::MergeFromString().
|
||||
bool MergeFromString(const string& input, Message* output);
|
||||
|
||||
// Set where to report parse errors. If NULL (the default), errors will
|
||||
// be printed to stderr.
|
||||
void RecordErrorsTo(io::ErrorCollector* error_collector) {
|
||||
error_collector_ = error_collector;
|
||||
}
|
||||
|
||||
// Set how parser finds extensions. If NULL (the default), the
|
||||
// parser will use the standard Reflection object associated with
|
||||
// the message being parsed.
|
||||
void SetFinder(Finder* finder) {
|
||||
finder_ = finder;
|
||||
}
|
||||
|
||||
// Sets where location information about the parse will be written. If NULL
|
||||
// (the default), then no location will be written.
|
||||
void WriteLocationsTo(ParseInfoTree* tree) {
|
||||
parse_info_tree_ = tree;
|
||||
}
|
||||
|
||||
// Normally parsing fails if, after parsing, output->IsInitialized()
|
||||
// returns false. Call AllowPartialMessage(true) to skip this check.
|
||||
void AllowPartialMessage(bool allow) {
|
||||
allow_partial_ = allow;
|
||||
}
|
||||
|
||||
// Allow field names to be matched case-insensitively.
|
||||
// This is not advisable if there are fields that only differ in case, or
|
||||
// if you want to enforce writing in the canonical form.
|
||||
// This is 'false' by default.
|
||||
void AllowCaseInsensitiveField(bool allow) {
|
||||
allow_case_insensitive_field_ = allow;
|
||||
}
|
||||
|
||||
// Like TextFormat::ParseFieldValueFromString
|
||||
bool ParseFieldValueFromString(const string& input,
|
||||
const FieldDescriptor* field,
|
||||
Message* output);
|
||||
|
||||
|
||||
void AllowFieldNumber(bool allow) {
|
||||
allow_field_number_ = allow;
|
||||
}
|
||||
|
||||
private:
|
||||
// Forward declaration of an internal class used to parse text
|
||||
// representations (see text_format.cc for implementation).
|
||||
class ParserImpl;
|
||||
|
||||
// Like TextFormat::Merge(). The provided implementation is used
|
||||
// to do the parsing.
|
||||
bool MergeUsingImpl(io::ZeroCopyInputStream* input,
|
||||
Message* output,
|
||||
ParserImpl* parser_impl);
|
||||
|
||||
io::ErrorCollector* error_collector_;
|
||||
Finder* finder_;
|
||||
ParseInfoTree* parse_info_tree_;
|
||||
bool allow_partial_;
|
||||
bool allow_case_insensitive_field_;
|
||||
bool allow_unknown_field_;
|
||||
bool allow_unknown_enum_;
|
||||
bool allow_field_number_;
|
||||
bool allow_relaxed_whitespace_;
|
||||
bool allow_singular_overwrites_;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
// Hack: ParseInfoTree declares TextFormat as a friend which should extend
|
||||
// the friendship to TextFormat::Parser::ParserImpl, but unfortunately some
|
||||
// old compilers (e.g. GCC 3.4.6) don't implement this correctly. We provide
|
||||
// helpers for ParserImpl to call methods of ParseInfoTree.
|
||||
static inline void RecordLocation(ParseInfoTree* info_tree,
|
||||
const FieldDescriptor* field,
|
||||
ParseLocation location);
|
||||
static inline ParseInfoTree* CreateNested(ParseInfoTree* info_tree,
|
||||
const FieldDescriptor* field);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormat);
|
||||
};
|
||||
|
||||
inline void TextFormat::RecordLocation(ParseInfoTree* info_tree,
|
||||
const FieldDescriptor* field,
|
||||
ParseLocation location) {
|
||||
info_tree->RecordLocation(field, location);
|
||||
}
|
||||
|
||||
|
||||
inline TextFormat::ParseInfoTree* TextFormat::CreateNested(
|
||||
ParseInfoTree* info_tree, const FieldDescriptor* field) {
|
||||
return info_tree->CreateNested(field);
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_TEXT_FORMAT_H__
|
|
@ -0,0 +1,318 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Contains classes used to keep track of unrecognized fields seen while
|
||||
// parsing a protocol message.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
|
||||
#define GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
|
||||
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
class CodedInputStream; // coded_stream.h
|
||||
class CodedOutputStream; // coded_stream.h
|
||||
class ZeroCopyInputStream; // zero_copy_stream.h
|
||||
}
|
||||
namespace internal {
|
||||
class WireFormat; // wire_format.h
|
||||
class MessageSetFieldSkipperUsingCord;
|
||||
// extension_set_heavy.cc
|
||||
}
|
||||
|
||||
class Message; // message.h
|
||||
class UnknownField; // below
|
||||
|
||||
// An UnknownFieldSet contains fields that were encountered while parsing a
|
||||
// message but were not defined by its type. Keeping track of these can be
|
||||
// useful, especially in that they may be written if the message is serialized
|
||||
// again without being cleared in between. This means that software which
|
||||
// simply receives messages and forwards them to other servers does not need
|
||||
// to be updated every time a new field is added to the message definition.
|
||||
//
|
||||
// To get the UnknownFieldSet attached to any message, call
|
||||
// Reflection::GetUnknownFields().
|
||||
//
|
||||
// This class is necessarily tied to the protocol buffer wire format, unlike
|
||||
// the Reflection interface which is independent of any serialization scheme.
|
||||
class LIBPROTOBUF_EXPORT UnknownFieldSet {
|
||||
public:
|
||||
UnknownFieldSet();
|
||||
~UnknownFieldSet();
|
||||
|
||||
// Remove all fields.
|
||||
inline void Clear();
|
||||
|
||||
// Remove all fields and deallocate internal data objects
|
||||
void ClearAndFreeMemory();
|
||||
|
||||
// Is this set empty?
|
||||
inline bool empty() const;
|
||||
|
||||
// Merge the contents of some other UnknownFieldSet with this one.
|
||||
void MergeFrom(const UnknownFieldSet& other);
|
||||
|
||||
// Swaps the contents of some other UnknownFieldSet with this one.
|
||||
inline void Swap(UnknownFieldSet* x);
|
||||
|
||||
// Computes (an estimate of) the total number of bytes currently used for
|
||||
// storing the unknown fields in memory. Does NOT include
|
||||
// sizeof(*this) in the calculation.
|
||||
int SpaceUsedExcludingSelf() const;
|
||||
|
||||
// Version of SpaceUsed() including sizeof(*this).
|
||||
int SpaceUsed() const;
|
||||
|
||||
// Returns the number of fields present in the UnknownFieldSet.
|
||||
inline int field_count() const;
|
||||
// Get a field in the set, where 0 <= index < field_count(). The fields
|
||||
// appear in the order in which they were added.
|
||||
inline const UnknownField& field(int index) const;
|
||||
// Get a mutable pointer to a field in the set, where
|
||||
// 0 <= index < field_count(). The fields appear in the order in which
|
||||
// they were added.
|
||||
inline UnknownField* mutable_field(int index);
|
||||
|
||||
// Adding fields ---------------------------------------------------
|
||||
|
||||
void AddVarint(int number, uint64 value);
|
||||
void AddFixed32(int number, uint32 value);
|
||||
void AddFixed64(int number, uint64 value);
|
||||
void AddLengthDelimited(int number, const string& value);
|
||||
string* AddLengthDelimited(int number);
|
||||
UnknownFieldSet* AddGroup(int number);
|
||||
|
||||
// Adds an unknown field from another set.
|
||||
void AddField(const UnknownField& field);
|
||||
|
||||
// Delete fields with indices in the range [start .. start+num-1].
|
||||
// Caution: implementation moves all fields with indices [start+num .. ].
|
||||
void DeleteSubrange(int start, int num);
|
||||
|
||||
// Delete all fields with a specific field number. The order of left fields
|
||||
// is preserved.
|
||||
// Caution: implementation moves all fields after the first deleted field.
|
||||
void DeleteByNumber(int number);
|
||||
|
||||
// Parsing helpers -------------------------------------------------
|
||||
// These work exactly like the similarly-named methods of Message.
|
||||
|
||||
bool MergeFromCodedStream(io::CodedInputStream* input);
|
||||
bool ParseFromCodedStream(io::CodedInputStream* input);
|
||||
bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
|
||||
bool ParseFromArray(const void* data, int size);
|
||||
inline bool ParseFromString(const string& data) {
|
||||
return ParseFromArray(data.data(), static_cast<int>(data.size()));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void ClearFallback();
|
||||
|
||||
vector<UnknownField>* fields_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
|
||||
};
|
||||
|
||||
// Represents one field in an UnknownFieldSet.
|
||||
class LIBPROTOBUF_EXPORT UnknownField {
|
||||
public:
|
||||
enum Type {
|
||||
TYPE_VARINT,
|
||||
TYPE_FIXED32,
|
||||
TYPE_FIXED64,
|
||||
TYPE_LENGTH_DELIMITED,
|
||||
TYPE_GROUP
|
||||
};
|
||||
|
||||
// The field's tag number, as seen on the wire.
|
||||
inline int number() const;
|
||||
|
||||
// The field type.
|
||||
inline Type type() const;
|
||||
|
||||
// Accessors -------------------------------------------------------
|
||||
// Each method works only for UnknownFields of the corresponding type.
|
||||
|
||||
inline uint64 varint() const;
|
||||
inline uint32 fixed32() const;
|
||||
inline uint64 fixed64() const;
|
||||
inline const string& length_delimited() const;
|
||||
inline const UnknownFieldSet& group() const;
|
||||
|
||||
inline void set_varint(uint64 value);
|
||||
inline void set_fixed32(uint32 value);
|
||||
inline void set_fixed64(uint64 value);
|
||||
inline void set_length_delimited(const string& value);
|
||||
inline string* mutable_length_delimited();
|
||||
inline UnknownFieldSet* mutable_group();
|
||||
|
||||
// Serialization API.
|
||||
// These methods can take advantage of the underlying implementation and may
|
||||
// archieve a better performance than using getters to retrieve the data and
|
||||
// do the serialization yourself.
|
||||
void SerializeLengthDelimitedNoTag(io::CodedOutputStream* output) const;
|
||||
uint8* SerializeLengthDelimitedNoTagToArray(uint8* target) const;
|
||||
|
||||
inline int GetLengthDelimitedSize() const;
|
||||
|
||||
private:
|
||||
friend class UnknownFieldSet;
|
||||
|
||||
// If this UnknownField contains a pointer, delete it.
|
||||
void Delete();
|
||||
|
||||
// Make a deep copy of any pointers in this UnknownField.
|
||||
void DeepCopy();
|
||||
|
||||
// Set the wire type of this UnknownField. Should only be used when this
|
||||
// UnknownField is being created.
|
||||
inline void SetType(Type type);
|
||||
|
||||
uint32 number_;
|
||||
uint32 type_;
|
||||
union {
|
||||
uint64 varint_;
|
||||
uint32 fixed32_;
|
||||
uint64 fixed64_;
|
||||
mutable union {
|
||||
string* string_value_;
|
||||
} length_delimited_;
|
||||
UnknownFieldSet* group_;
|
||||
};
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
// inline implementations
|
||||
|
||||
inline void UnknownFieldSet::Clear() {
|
||||
if (fields_ != NULL) {
|
||||
ClearFallback();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool UnknownFieldSet::empty() const {
|
||||
return fields_ == NULL || fields_->empty();
|
||||
}
|
||||
|
||||
inline void UnknownFieldSet::Swap(UnknownFieldSet* x) {
|
||||
std::swap(fields_, x->fields_);
|
||||
}
|
||||
|
||||
inline int UnknownFieldSet::field_count() const {
|
||||
return (fields_ == NULL) ? 0 : static_cast<int>(fields_->size());
|
||||
}
|
||||
inline const UnknownField& UnknownFieldSet::field(int index) const {
|
||||
return (*fields_)[index];
|
||||
}
|
||||
inline UnknownField* UnknownFieldSet::mutable_field(int index) {
|
||||
return &(*fields_)[index];
|
||||
}
|
||||
|
||||
inline void UnknownFieldSet::AddLengthDelimited(
|
||||
int number, const string& value) {
|
||||
AddLengthDelimited(number)->assign(value);
|
||||
}
|
||||
|
||||
|
||||
inline int UnknownField::number() const { return number_; }
|
||||
inline UnknownField::Type UnknownField::type() const {
|
||||
return static_cast<Type>(type_);
|
||||
}
|
||||
|
||||
inline uint64 UnknownField::varint() const {
|
||||
assert(type() == TYPE_VARINT);
|
||||
return varint_;
|
||||
}
|
||||
inline uint32 UnknownField::fixed32() const {
|
||||
assert(type() == TYPE_FIXED32);
|
||||
return fixed32_;
|
||||
}
|
||||
inline uint64 UnknownField::fixed64() const {
|
||||
assert(type() == TYPE_FIXED64);
|
||||
return fixed64_;
|
||||
}
|
||||
inline const string& UnknownField::length_delimited() const {
|
||||
assert(type() == TYPE_LENGTH_DELIMITED);
|
||||
return *length_delimited_.string_value_;
|
||||
}
|
||||
inline const UnknownFieldSet& UnknownField::group() const {
|
||||
assert(type() == TYPE_GROUP);
|
||||
return *group_;
|
||||
}
|
||||
|
||||
inline void UnknownField::set_varint(uint64 value) {
|
||||
assert(type() == TYPE_VARINT);
|
||||
varint_ = value;
|
||||
}
|
||||
inline void UnknownField::set_fixed32(uint32 value) {
|
||||
assert(type() == TYPE_FIXED32);
|
||||
fixed32_ = value;
|
||||
}
|
||||
inline void UnknownField::set_fixed64(uint64 value) {
|
||||
assert(type() == TYPE_FIXED64);
|
||||
fixed64_ = value;
|
||||
}
|
||||
inline void UnknownField::set_length_delimited(const string& value) {
|
||||
assert(type() == TYPE_LENGTH_DELIMITED);
|
||||
length_delimited_.string_value_->assign(value);
|
||||
}
|
||||
inline string* UnknownField::mutable_length_delimited() {
|
||||
assert(type() == TYPE_LENGTH_DELIMITED);
|
||||
return length_delimited_.string_value_;
|
||||
}
|
||||
inline UnknownFieldSet* UnknownField::mutable_group() {
|
||||
assert(type() == TYPE_GROUP);
|
||||
return group_;
|
||||
}
|
||||
|
||||
inline int UnknownField::GetLengthDelimitedSize() const {
|
||||
GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
|
||||
return static_cast<int>(length_delimited_.string_value_->size());
|
||||
}
|
||||
|
||||
inline void UnknownField::SetType(Type type) {
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
|
|
@ -0,0 +1,336 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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)
|
||||
// atenasio@google.com (Chris Atenasio) (ZigZag transform)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This header is logically internal, but is made public because it is used
|
||||
// from protocol-compiler-generated code, which may reside in other components.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_H__
|
||||
#define GOOGLE_PROTOBUF_WIRE_FORMAT_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
|
||||
// Do UTF-8 validation on string type in Debug build only
|
||||
#ifndef NDEBUG
|
||||
#define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
class CodedInputStream; // coded_stream.h
|
||||
class CodedOutputStream; // coded_stream.h
|
||||
}
|
||||
class UnknownFieldSet; // unknown_field_set.h
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// This class is for internal use by the protocol buffer library and by
|
||||
// protocol-complier-generated message classes. It must not be called
|
||||
// directly by clients.
|
||||
//
|
||||
// This class contains code for implementing the binary protocol buffer
|
||||
// wire format via reflection. The WireFormatLite class implements the
|
||||
// non-reflection based routines.
|
||||
//
|
||||
// This class is really a namespace that contains only static methods
|
||||
class LIBPROTOBUF_EXPORT WireFormat {
|
||||
public:
|
||||
|
||||
// Given a field return its WireType
|
||||
static inline WireFormatLite::WireType WireTypeForField(
|
||||
const FieldDescriptor* field);
|
||||
|
||||
// Given a FieldDescriptor::Type return its WireType
|
||||
static inline WireFormatLite::WireType WireTypeForFieldType(
|
||||
FieldDescriptor::Type type);
|
||||
|
||||
// Compute the byte size of a tag. For groups, this includes both the start
|
||||
// and end tags.
|
||||
static inline int TagSize(int field_number, FieldDescriptor::Type type);
|
||||
|
||||
// These procedures can be used to implement the methods of Message which
|
||||
// handle parsing and serialization of the protocol buffer wire format
|
||||
// using only the Reflection interface. When you ask the protocol
|
||||
// compiler to optimize for code size rather than speed, it will implement
|
||||
// those methods in terms of these procedures. Of course, these are much
|
||||
// slower than the specialized implementations which the protocol compiler
|
||||
// generates when told to optimize for speed.
|
||||
|
||||
// Read a message in protocol buffer wire format.
|
||||
//
|
||||
// This procedure reads either to the end of the input stream or through
|
||||
// a WIRETYPE_END_GROUP tag ending the message, whichever comes first.
|
||||
// It returns false if the input is invalid.
|
||||
//
|
||||
// Required fields are NOT checked by this method. You must call
|
||||
// IsInitialized() on the resulting message yourself.
|
||||
static bool ParseAndMergePartial(io::CodedInputStream* input,
|
||||
Message* message);
|
||||
|
||||
// Serialize a message in protocol buffer wire format.
|
||||
//
|
||||
// Any embedded messages within the message must have their correct sizes
|
||||
// cached. However, the top-level message need not; its size is passed as
|
||||
// a parameter to this procedure.
|
||||
//
|
||||
// These return false iff the underlying stream returns a write error.
|
||||
static void SerializeWithCachedSizes(
|
||||
const Message& message,
|
||||
int size, io::CodedOutputStream* output);
|
||||
|
||||
// Implements Message::ByteSize() via reflection. WARNING: The result
|
||||
// of this method is *not* cached anywhere. However, all embedded messages
|
||||
// will have their ByteSize() methods called, so their sizes will be cached.
|
||||
// Therefore, calling this method is sufficient to allow you to call
|
||||
// WireFormat::SerializeWithCachedSizes() on the same object.
|
||||
static int ByteSize(const Message& message);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Helpers for dealing with unknown fields
|
||||
|
||||
// Skips a field value of the given WireType. The input should start
|
||||
// positioned immediately after the tag. If unknown_fields is non-NULL,
|
||||
// the contents of the field will be added to it.
|
||||
static bool SkipField(io::CodedInputStream* input, uint32 tag,
|
||||
UnknownFieldSet* unknown_fields);
|
||||
|
||||
// Reads and ignores a message from the input. If unknown_fields is non-NULL,
|
||||
// the contents will be added to it.
|
||||
static bool SkipMessage(io::CodedInputStream* input,
|
||||
UnknownFieldSet* unknown_fields);
|
||||
|
||||
// Write the contents of an UnknownFieldSet to the output.
|
||||
static void SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
|
||||
io::CodedOutputStream* output);
|
||||
// Same as above, except writing directly to the provided buffer.
|
||||
// Requires that the buffer have sufficient capacity for
|
||||
// ComputeUnknownFieldsSize(unknown_fields).
|
||||
//
|
||||
// Returns a pointer past the last written byte.
|
||||
static uint8* SerializeUnknownFieldsToArray(
|
||||
const UnknownFieldSet& unknown_fields,
|
||||
uint8* target);
|
||||
|
||||
// Same thing except for messages that have the message_set_wire_format
|
||||
// option.
|
||||
static void SerializeUnknownMessageSetItems(
|
||||
const UnknownFieldSet& unknown_fields,
|
||||
io::CodedOutputStream* output);
|
||||
// Same as above, except writing directly to the provided buffer.
|
||||
// Requires that the buffer have sufficient capacity for
|
||||
// ComputeUnknownMessageSetItemsSize(unknown_fields).
|
||||
//
|
||||
// Returns a pointer past the last written byte.
|
||||
static uint8* SerializeUnknownMessageSetItemsToArray(
|
||||
const UnknownFieldSet& unknown_fields,
|
||||
uint8* target);
|
||||
|
||||
// Compute the size of the UnknownFieldSet on the wire.
|
||||
static int ComputeUnknownFieldsSize(const UnknownFieldSet& unknown_fields);
|
||||
|
||||
// Same thing except for messages that have the message_set_wire_format
|
||||
// option.
|
||||
static int ComputeUnknownMessageSetItemsSize(
|
||||
const UnknownFieldSet& unknown_fields);
|
||||
|
||||
|
||||
// Helper functions for encoding and decoding tags. (Inlined below and in
|
||||
// _inl.h)
|
||||
//
|
||||
// This is different from MakeTag(field->number(), field->type()) in the case
|
||||
// of packed repeated fields.
|
||||
static uint32 MakeTag(const FieldDescriptor* field);
|
||||
|
||||
// Parse a single field. The input should start out positioned immediately
|
||||
// after the tag.
|
||||
static bool ParseAndMergeField(
|
||||
uint32 tag,
|
||||
const FieldDescriptor* field, // May be NULL for unknown
|
||||
Message* message,
|
||||
io::CodedInputStream* input);
|
||||
|
||||
// Serialize a single field.
|
||||
static void SerializeFieldWithCachedSizes(
|
||||
const FieldDescriptor* field, // Cannot be NULL
|
||||
const Message& message,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
// Compute size of a single field. If the field is a message type, this
|
||||
// will call ByteSize() for the embedded message, insuring that it caches
|
||||
// its size.
|
||||
static int FieldByteSize(
|
||||
const FieldDescriptor* field, // Cannot be NULL
|
||||
const Message& message);
|
||||
|
||||
// Parse/serialize a MessageSet::Item group. Used with messages that use
|
||||
// opion message_set_wire_format = true.
|
||||
static bool ParseAndMergeMessageSetItem(
|
||||
io::CodedInputStream* input,
|
||||
Message* message);
|
||||
static void SerializeMessageSetItemWithCachedSizes(
|
||||
const FieldDescriptor* field,
|
||||
const Message& message,
|
||||
io::CodedOutputStream* output);
|
||||
static int MessageSetItemByteSize(
|
||||
const FieldDescriptor* field,
|
||||
const Message& message);
|
||||
|
||||
// Computes the byte size of a field, excluding tags. For packed fields, it
|
||||
// only includes the size of the raw data, and not the size of the total
|
||||
// length, but for other length-delimited types, the size of the length is
|
||||
// included.
|
||||
static int FieldDataOnlyByteSize(
|
||||
const FieldDescriptor* field, // Cannot be NULL
|
||||
const Message& message);
|
||||
|
||||
enum Operation {
|
||||
PARSE,
|
||||
SERIALIZE,
|
||||
};
|
||||
|
||||
// Verifies that a string field is valid UTF8, logging an error if not.
|
||||
// This function will not be called by newly generated protobuf code
|
||||
// but remains present to support existing code.
|
||||
static void VerifyUTF8String(const char* data, int size, Operation op);
|
||||
// The NamedField variant takes a field name in order to produce an
|
||||
// informative error message if verification fails.
|
||||
static void VerifyUTF8StringNamedField(const char* data,
|
||||
int size,
|
||||
Operation op,
|
||||
const char* field_name);
|
||||
|
||||
private:
|
||||
// Verifies that a string field is valid UTF8, logging an error if not.
|
||||
static void VerifyUTF8StringFallback(
|
||||
const char* data,
|
||||
int size,
|
||||
Operation op,
|
||||
const char* field_name);
|
||||
|
||||
// Skip a MessageSet field.
|
||||
static bool SkipMessageSetField(io::CodedInputStream* input,
|
||||
uint32 field_number,
|
||||
UnknownFieldSet* unknown_fields);
|
||||
|
||||
// Parse a MessageSet field.
|
||||
static bool ParseAndMergeMessageSetField(uint32 field_number,
|
||||
const FieldDescriptor* field,
|
||||
Message* message,
|
||||
io::CodedInputStream* input);
|
||||
|
||||
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormat);
|
||||
};
|
||||
|
||||
// Subclass of FieldSkipper which saves skipped fields to an UnknownFieldSet.
|
||||
class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper {
|
||||
public:
|
||||
UnknownFieldSetFieldSkipper(UnknownFieldSet* unknown_fields)
|
||||
: unknown_fields_(unknown_fields) {}
|
||||
virtual ~UnknownFieldSetFieldSkipper() {}
|
||||
|
||||
// implements FieldSkipper -----------------------------------------
|
||||
virtual bool SkipField(io::CodedInputStream* input, uint32 tag);
|
||||
virtual bool SkipMessage(io::CodedInputStream* input);
|
||||
virtual void SkipUnknownEnum(int field_number, int value);
|
||||
|
||||
protected:
|
||||
UnknownFieldSet* unknown_fields_;
|
||||
};
|
||||
|
||||
// inline methods ====================================================
|
||||
|
||||
inline WireFormatLite::WireType WireFormat::WireTypeForField(
|
||||
const FieldDescriptor* field) {
|
||||
if (field->options().packed()) {
|
||||
return WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
|
||||
} else {
|
||||
return WireTypeForFieldType(field->type());
|
||||
}
|
||||
}
|
||||
|
||||
inline WireFormatLite::WireType WireFormat::WireTypeForFieldType(
|
||||
FieldDescriptor::Type type) {
|
||||
// Some compilers don't like enum -> enum casts, so we implicit_cast to
|
||||
// int first.
|
||||
return WireFormatLite::WireTypeForFieldType(
|
||||
static_cast<WireFormatLite::FieldType>(
|
||||
implicit_cast<int>(type)));
|
||||
}
|
||||
|
||||
inline uint32 WireFormat::MakeTag(const FieldDescriptor* field) {
|
||||
return WireFormatLite::MakeTag(field->number(), WireTypeForField(field));
|
||||
}
|
||||
|
||||
inline int WireFormat::TagSize(int field_number, FieldDescriptor::Type type) {
|
||||
// Some compilers don't like enum -> enum casts, so we implicit_cast to
|
||||
// int first.
|
||||
return WireFormatLite::TagSize(field_number,
|
||||
static_cast<WireFormatLite::FieldType>(
|
||||
implicit_cast<int>(type)));
|
||||
}
|
||||
|
||||
inline void WireFormat::VerifyUTF8String(const char* data, int size,
|
||||
WireFormat::Operation op) {
|
||||
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
WireFormat::VerifyUTF8StringFallback(data, size, op, NULL);
|
||||
#else
|
||||
// Avoid the compiler warning about unsued variables.
|
||||
(void)data; (void)size; (void)op;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void WireFormat::VerifyUTF8StringNamedField(
|
||||
const char* data, int size, WireFormat::Operation op,
|
||||
const char* field_name) {
|
||||
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
|
||||
WireFormat::VerifyUTF8StringFallback(data, size, op, field_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_H__
|
|
@ -0,0 +1,661 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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)
|
||||
// atenasio@google.com (Chris Atenasio) (ZigZag transform)
|
||||
// wink@google.com (Wink Saville) (refactored from wire_format.h)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This header is logically internal, but is made public because it is used
|
||||
// from protocol-compiler-generated code, which may reside in other components.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/io/coded_stream.h> // for CodedOutputStream::Varint32Size
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
template <typename T> class RepeatedField; // repeated_field.h
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
class StringPieceField;
|
||||
|
||||
// This class is for internal use by the protocol buffer library and by
|
||||
// protocol-complier-generated message classes. It must not be called
|
||||
// directly by clients.
|
||||
//
|
||||
// This class contains helpers for implementing the binary protocol buffer
|
||||
// wire format without the need for reflection. Use WireFormat when using
|
||||
// reflection.
|
||||
//
|
||||
// This class is really a namespace that contains only static methods.
|
||||
class LIBPROTOBUF_EXPORT WireFormatLite {
|
||||
public:
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Helper constants and functions related to the format. These are
|
||||
// mostly meant for internal and generated code to use.
|
||||
|
||||
// The wire format is composed of a sequence of tag/value pairs, each
|
||||
// of which contains the value of one field (or one element of a repeated
|
||||
// field). Each tag is encoded as a varint. The lower bits of the tag
|
||||
// identify its wire type, which specifies the format of the data to follow.
|
||||
// The rest of the bits contain the field number. Each type of field (as
|
||||
// declared by FieldDescriptor::Type, in descriptor.h) maps to one of
|
||||
// these wire types. Immediately following each tag is the field's value,
|
||||
// encoded in the format specified by the wire type. Because the tag
|
||||
// identifies the encoding of this data, it is possible to skip
|
||||
// unrecognized fields for forwards compatibility.
|
||||
|
||||
enum WireType {
|
||||
WIRETYPE_VARINT = 0,
|
||||
WIRETYPE_FIXED64 = 1,
|
||||
WIRETYPE_LENGTH_DELIMITED = 2,
|
||||
WIRETYPE_START_GROUP = 3,
|
||||
WIRETYPE_END_GROUP = 4,
|
||||
WIRETYPE_FIXED32 = 5,
|
||||
};
|
||||
|
||||
// Lite alternative to FieldDescriptor::Type. Must be kept in sync.
|
||||
enum FieldType {
|
||||
TYPE_DOUBLE = 1,
|
||||
TYPE_FLOAT = 2,
|
||||
TYPE_INT64 = 3,
|
||||
TYPE_UINT64 = 4,
|
||||
TYPE_INT32 = 5,
|
||||
TYPE_FIXED64 = 6,
|
||||
TYPE_FIXED32 = 7,
|
||||
TYPE_BOOL = 8,
|
||||
TYPE_STRING = 9,
|
||||
TYPE_GROUP = 10,
|
||||
TYPE_MESSAGE = 11,
|
||||
TYPE_BYTES = 12,
|
||||
TYPE_UINT32 = 13,
|
||||
TYPE_ENUM = 14,
|
||||
TYPE_SFIXED32 = 15,
|
||||
TYPE_SFIXED64 = 16,
|
||||
TYPE_SINT32 = 17,
|
||||
TYPE_SINT64 = 18,
|
||||
MAX_FIELD_TYPE = 18,
|
||||
};
|
||||
|
||||
// Lite alternative to FieldDescriptor::CppType. Must be kept in sync.
|
||||
enum CppType {
|
||||
CPPTYPE_INT32 = 1,
|
||||
CPPTYPE_INT64 = 2,
|
||||
CPPTYPE_UINT32 = 3,
|
||||
CPPTYPE_UINT64 = 4,
|
||||
CPPTYPE_DOUBLE = 5,
|
||||
CPPTYPE_FLOAT = 6,
|
||||
CPPTYPE_BOOL = 7,
|
||||
CPPTYPE_ENUM = 8,
|
||||
CPPTYPE_STRING = 9,
|
||||
CPPTYPE_MESSAGE = 10,
|
||||
MAX_CPPTYPE = 10,
|
||||
};
|
||||
|
||||
// Helper method to get the CppType for a particular Type.
|
||||
static CppType FieldTypeToCppType(FieldType type);
|
||||
|
||||
// Given a FieldSescriptor::Type return its WireType
|
||||
static inline WireFormatLite::WireType WireTypeForFieldType(
|
||||
WireFormatLite::FieldType type) {
|
||||
return kWireTypeForFieldType[type];
|
||||
}
|
||||
|
||||
// Number of bits in a tag which identify the wire type.
|
||||
static const int kTagTypeBits = 3;
|
||||
// Mask for those bits.
|
||||
static const uint32 kTagTypeMask = (1 << kTagTypeBits) - 1;
|
||||
|
||||
// Helper functions for encoding and decoding tags. (Inlined below and in
|
||||
// _inl.h)
|
||||
//
|
||||
// This is different from MakeTag(field->number(), field->type()) in the case
|
||||
// of packed repeated fields.
|
||||
static uint32 MakeTag(int field_number, WireType type);
|
||||
static WireType GetTagWireType(uint32 tag);
|
||||
static int GetTagFieldNumber(uint32 tag);
|
||||
|
||||
// Compute the byte size of a tag. For groups, this includes both the start
|
||||
// and end tags.
|
||||
static inline int TagSize(int field_number, WireFormatLite::FieldType type);
|
||||
|
||||
// Skips a field value with the given tag. The input should start
|
||||
// positioned immediately after the tag. Skipped values are simply discarded,
|
||||
// not recorded anywhere. See WireFormat::SkipField() for a version that
|
||||
// records to an UnknownFieldSet.
|
||||
static bool SkipField(io::CodedInputStream* input, uint32 tag);
|
||||
|
||||
// Skips a field value with the given tag. The input should start
|
||||
// positioned immediately after the tag. Skipped values are recorded to a
|
||||
// CodedOutputStream.
|
||||
static bool SkipField(io::CodedInputStream* input, uint32 tag,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
// Reads and ignores a message from the input. Skipped values are simply
|
||||
// discarded, not recorded anywhere. See WireFormat::SkipMessage() for a
|
||||
// version that records to an UnknownFieldSet.
|
||||
static bool SkipMessage(io::CodedInputStream* input);
|
||||
|
||||
// Reads and ignores a message from the input. Skipped values are recorded
|
||||
// to a CodedOutputStream.
|
||||
static bool SkipMessage(io::CodedInputStream* input,
|
||||
io::CodedOutputStream* output);
|
||||
|
||||
// This macro does the same thing as WireFormatLite::MakeTag(), but the
|
||||
// result is usable as a compile-time constant, which makes it usable
|
||||
// as a switch case or a template input. WireFormatLite::MakeTag() is more
|
||||
// type-safe, though, so prefer it if possible.
|
||||
#define GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(FIELD_NUMBER, TYPE) \
|
||||
static_cast<uint32>( \
|
||||
((FIELD_NUMBER) << ::google::protobuf::internal::WireFormatLite::kTagTypeBits) \
|
||||
| (TYPE))
|
||||
|
||||
// These are the tags for the old MessageSet format, which was defined as:
|
||||
// message MessageSet {
|
||||
// repeated group Item = 1 {
|
||||
// required int32 type_id = 2;
|
||||
// required string message = 3;
|
||||
// }
|
||||
// }
|
||||
static const int kMessageSetItemNumber = 1;
|
||||
static const int kMessageSetTypeIdNumber = 2;
|
||||
static const int kMessageSetMessageNumber = 3;
|
||||
static const int kMessageSetItemStartTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber,
|
||||
WireFormatLite::WIRETYPE_START_GROUP);
|
||||
static const int kMessageSetItemEndTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber,
|
||||
WireFormatLite::WIRETYPE_END_GROUP);
|
||||
static const int kMessageSetTypeIdTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetTypeIdNumber,
|
||||
WireFormatLite::WIRETYPE_VARINT);
|
||||
static const int kMessageSetMessageTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetMessageNumber,
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
|
||||
|
||||
// Byte size of all tags of a MessageSet::Item combined.
|
||||
static const int kMessageSetItemTagsSize;
|
||||
|
||||
// Helper functions for converting between floats/doubles and IEEE-754
|
||||
// uint32s/uint64s so that they can be written. (Assumes your platform
|
||||
// uses IEEE-754 floats.)
|
||||
static uint32 EncodeFloat(float value);
|
||||
static float DecodeFloat(uint32 value);
|
||||
static uint64 EncodeDouble(double value);
|
||||
static double DecodeDouble(uint64 value);
|
||||
|
||||
// Helper functions for mapping signed integers to unsigned integers in
|
||||
// such a way that numbers with small magnitudes will encode to smaller
|
||||
// varints. If you simply static_cast a negative number to an unsigned
|
||||
// number and varint-encode it, it will always take 10 bytes, defeating
|
||||
// the purpose of varint. So, for the "sint32" and "sint64" field types,
|
||||
// we ZigZag-encode the values.
|
||||
static uint32 ZigZagEncode32(int32 n);
|
||||
static int32 ZigZagDecode32(uint32 n);
|
||||
static uint64 ZigZagEncode64(int64 n);
|
||||
static int64 ZigZagDecode64(uint64 n);
|
||||
|
||||
// =================================================================
|
||||
// Methods for reading/writing individual field. The implementations
|
||||
// of these methods are defined in wire_format_lite_inl.h; you must #include
|
||||
// that file to use these.
|
||||
|
||||
// Avoid ugly line wrapping
|
||||
#define input io::CodedInputStream* input_arg
|
||||
#define output io::CodedOutputStream* output_arg
|
||||
#define field_number int field_number_arg
|
||||
#define INL GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
|
||||
// Read fields, not including tags. The assumption is that you already
|
||||
// read the tag to determine what field to read.
|
||||
|
||||
// For primitive fields, we just use a templatized routine parameterized by
|
||||
// the represented type and the FieldType. These are specialized with the
|
||||
// appropriate definition for each declared type.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static inline bool ReadPrimitive(input, CType* value) INL;
|
||||
|
||||
// Reads repeated primitive values, with optimizations for repeats.
|
||||
// tag_size and tag should both be compile-time constants provided by the
|
||||
// protocol compiler.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static inline bool ReadRepeatedPrimitive(int tag_size,
|
||||
uint32 tag,
|
||||
input,
|
||||
RepeatedField<CType>* value) INL;
|
||||
|
||||
// Identical to ReadRepeatedPrimitive, except will not inline the
|
||||
// implementation.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static bool ReadRepeatedPrimitiveNoInline(int tag_size,
|
||||
uint32 tag,
|
||||
input,
|
||||
RepeatedField<CType>* value);
|
||||
|
||||
// Reads a primitive value directly from the provided buffer. It returns a
|
||||
// pointer past the segment of data that was read.
|
||||
//
|
||||
// This is only implemented for the types with fixed wire size, e.g.
|
||||
// float, double, and the (s)fixed* types.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static inline const uint8* ReadPrimitiveFromArray(const uint8* buffer,
|
||||
CType* value) INL;
|
||||
|
||||
// Reads a primitive packed field.
|
||||
//
|
||||
// This is only implemented for packable types.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static inline bool ReadPackedPrimitive(input,
|
||||
RepeatedField<CType>* value) INL;
|
||||
|
||||
// Identical to ReadPackedPrimitive, except will not inline the
|
||||
// implementation.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static bool ReadPackedPrimitiveNoInline(input, RepeatedField<CType>* value);
|
||||
|
||||
// Read a packed enum field. Values for which is_valid() returns false are
|
||||
// dropped.
|
||||
static bool ReadPackedEnumNoInline(input,
|
||||
bool (*is_valid)(int),
|
||||
RepeatedField<int>* value);
|
||||
|
||||
static bool ReadString(input, string* value);
|
||||
static bool ReadBytes (input, string* value);
|
||||
|
||||
static inline bool ReadGroup (field_number, input, MessageLite* value);
|
||||
static inline bool ReadMessage(input, MessageLite* value);
|
||||
|
||||
// Like above, but de-virtualize the call to MergePartialFromCodedStream().
|
||||
// The pointer must point at an instance of MessageType, *not* a subclass (or
|
||||
// the subclass must not override MergePartialFromCodedStream()).
|
||||
template<typename MessageType>
|
||||
static inline bool ReadGroupNoVirtual(field_number, input,
|
||||
MessageType* value);
|
||||
template<typename MessageType>
|
||||
static inline bool ReadMessageNoVirtual(input, MessageType* value);
|
||||
|
||||
// Write a tag. The Write*() functions typically include the tag, so
|
||||
// normally there's no need to call this unless using the Write*NoTag()
|
||||
// variants.
|
||||
static inline void WriteTag(field_number, WireType type, output) INL;
|
||||
|
||||
// Write fields, without tags.
|
||||
static inline void WriteInt32NoTag (int32 value, output) INL;
|
||||
static inline void WriteInt64NoTag (int64 value, output) INL;
|
||||
static inline void WriteUInt32NoTag (uint32 value, output) INL;
|
||||
static inline void WriteUInt64NoTag (uint64 value, output) INL;
|
||||
static inline void WriteSInt32NoTag (int32 value, output) INL;
|
||||
static inline void WriteSInt64NoTag (int64 value, output) INL;
|
||||
static inline void WriteFixed32NoTag (uint32 value, output) INL;
|
||||
static inline void WriteFixed64NoTag (uint64 value, output) INL;
|
||||
static inline void WriteSFixed32NoTag(int32 value, output) INL;
|
||||
static inline void WriteSFixed64NoTag(int64 value, output) INL;
|
||||
static inline void WriteFloatNoTag (float value, output) INL;
|
||||
static inline void WriteDoubleNoTag (double value, output) INL;
|
||||
static inline void WriteBoolNoTag (bool value, output) INL;
|
||||
static inline void WriteEnumNoTag (int value, output) INL;
|
||||
|
||||
// Write fields, including tags.
|
||||
static void WriteInt32 (field_number, int32 value, output);
|
||||
static void WriteInt64 (field_number, int64 value, output);
|
||||
static void WriteUInt32 (field_number, uint32 value, output);
|
||||
static void WriteUInt64 (field_number, uint64 value, output);
|
||||
static void WriteSInt32 (field_number, int32 value, output);
|
||||
static void WriteSInt64 (field_number, int64 value, output);
|
||||
static void WriteFixed32 (field_number, uint32 value, output);
|
||||
static void WriteFixed64 (field_number, uint64 value, output);
|
||||
static void WriteSFixed32(field_number, int32 value, output);
|
||||
static void WriteSFixed64(field_number, int64 value, output);
|
||||
static void WriteFloat (field_number, float value, output);
|
||||
static void WriteDouble (field_number, double value, output);
|
||||
static void WriteBool (field_number, bool value, output);
|
||||
static void WriteEnum (field_number, int value, output);
|
||||
|
||||
static void WriteString(field_number, const string& value, output);
|
||||
static void WriteBytes (field_number, const string& value, output);
|
||||
static void WriteStringMaybeAliased(
|
||||
field_number, const string& value, output);
|
||||
static void WriteBytesMaybeAliased(
|
||||
field_number, const string& value, output);
|
||||
|
||||
static void WriteGroup(
|
||||
field_number, const MessageLite& value, output);
|
||||
static void WriteMessage(
|
||||
field_number, const MessageLite& value, output);
|
||||
// Like above, but these will check if the output stream has enough
|
||||
// space to write directly to a flat array.
|
||||
static void WriteGroupMaybeToArray(
|
||||
field_number, const MessageLite& value, output);
|
||||
static void WriteMessageMaybeToArray(
|
||||
field_number, const MessageLite& value, output);
|
||||
|
||||
// Like above, but de-virtualize the call to SerializeWithCachedSizes(). The
|
||||
// pointer must point at an instance of MessageType, *not* a subclass (or
|
||||
// the subclass must not override SerializeWithCachedSizes()).
|
||||
template<typename MessageType>
|
||||
static inline void WriteGroupNoVirtual(
|
||||
field_number, const MessageType& value, output);
|
||||
template<typename MessageType>
|
||||
static inline void WriteMessageNoVirtual(
|
||||
field_number, const MessageType& value, output);
|
||||
|
||||
#undef output
|
||||
#define output uint8* target
|
||||
|
||||
// Like above, but use only *ToArray methods of CodedOutputStream.
|
||||
static inline uint8* WriteTagToArray(field_number, WireType type, output) INL;
|
||||
|
||||
// Write fields, without tags.
|
||||
static inline uint8* WriteInt32NoTagToArray (int32 value, output) INL;
|
||||
static inline uint8* WriteInt64NoTagToArray (int64 value, output) INL;
|
||||
static inline uint8* WriteUInt32NoTagToArray (uint32 value, output) INL;
|
||||
static inline uint8* WriteUInt64NoTagToArray (uint64 value, output) INL;
|
||||
static inline uint8* WriteSInt32NoTagToArray (int32 value, output) INL;
|
||||
static inline uint8* WriteSInt64NoTagToArray (int64 value, output) INL;
|
||||
static inline uint8* WriteFixed32NoTagToArray (uint32 value, output) INL;
|
||||
static inline uint8* WriteFixed64NoTagToArray (uint64 value, output) INL;
|
||||
static inline uint8* WriteSFixed32NoTagToArray(int32 value, output) INL;
|
||||
static inline uint8* WriteSFixed64NoTagToArray(int64 value, output) INL;
|
||||
static inline uint8* WriteFloatNoTagToArray (float value, output) INL;
|
||||
static inline uint8* WriteDoubleNoTagToArray (double value, output) INL;
|
||||
static inline uint8* WriteBoolNoTagToArray (bool value, output) INL;
|
||||
static inline uint8* WriteEnumNoTagToArray (int value, output) INL;
|
||||
|
||||
// Write fields, including tags.
|
||||
static inline uint8* WriteInt32ToArray(
|
||||
field_number, int32 value, output) INL;
|
||||
static inline uint8* WriteInt64ToArray(
|
||||
field_number, int64 value, output) INL;
|
||||
static inline uint8* WriteUInt32ToArray(
|
||||
field_number, uint32 value, output) INL;
|
||||
static inline uint8* WriteUInt64ToArray(
|
||||
field_number, uint64 value, output) INL;
|
||||
static inline uint8* WriteSInt32ToArray(
|
||||
field_number, int32 value, output) INL;
|
||||
static inline uint8* WriteSInt64ToArray(
|
||||
field_number, int64 value, output) INL;
|
||||
static inline uint8* WriteFixed32ToArray(
|
||||
field_number, uint32 value, output) INL;
|
||||
static inline uint8* WriteFixed64ToArray(
|
||||
field_number, uint64 value, output) INL;
|
||||
static inline uint8* WriteSFixed32ToArray(
|
||||
field_number, int32 value, output) INL;
|
||||
static inline uint8* WriteSFixed64ToArray(
|
||||
field_number, int64 value, output) INL;
|
||||
static inline uint8* WriteFloatToArray(
|
||||
field_number, float value, output) INL;
|
||||
static inline uint8* WriteDoubleToArray(
|
||||
field_number, double value, output) INL;
|
||||
static inline uint8* WriteBoolToArray(
|
||||
field_number, bool value, output) INL;
|
||||
static inline uint8* WriteEnumToArray(
|
||||
field_number, int value, output) INL;
|
||||
|
||||
static inline uint8* WriteStringToArray(
|
||||
field_number, const string& value, output) INL;
|
||||
static inline uint8* WriteBytesToArray(
|
||||
field_number, const string& value, output) INL;
|
||||
|
||||
static inline uint8* WriteGroupToArray(
|
||||
field_number, const MessageLite& value, output) INL;
|
||||
static inline uint8* WriteMessageToArray(
|
||||
field_number, const MessageLite& value, output) INL;
|
||||
|
||||
// Like above, but de-virtualize the call to SerializeWithCachedSizes(). The
|
||||
// pointer must point at an instance of MessageType, *not* a subclass (or
|
||||
// the subclass must not override SerializeWithCachedSizes()).
|
||||
template<typename MessageType>
|
||||
static inline uint8* WriteGroupNoVirtualToArray(
|
||||
field_number, const MessageType& value, output) INL;
|
||||
template<typename MessageType>
|
||||
static inline uint8* WriteMessageNoVirtualToArray(
|
||||
field_number, const MessageType& value, output) INL;
|
||||
|
||||
#undef output
|
||||
#undef input
|
||||
#undef INL
|
||||
|
||||
#undef field_number
|
||||
|
||||
// Compute the byte size of a field. The XxSize() functions do NOT include
|
||||
// the tag, so you must also call TagSize(). (This is because, for repeated
|
||||
// fields, you should only call TagSize() once and multiply it by the element
|
||||
// count, but you may have to call XxSize() for each individual element.)
|
||||
static inline int Int32Size ( int32 value);
|
||||
static inline int Int64Size ( int64 value);
|
||||
static inline int UInt32Size (uint32 value);
|
||||
static inline int UInt64Size (uint64 value);
|
||||
static inline int SInt32Size ( int32 value);
|
||||
static inline int SInt64Size ( int64 value);
|
||||
static inline int EnumSize ( int value);
|
||||
|
||||
// These types always have the same size.
|
||||
static const int kFixed32Size = 4;
|
||||
static const int kFixed64Size = 8;
|
||||
static const int kSFixed32Size = 4;
|
||||
static const int kSFixed64Size = 8;
|
||||
static const int kFloatSize = 4;
|
||||
static const int kDoubleSize = 8;
|
||||
static const int kBoolSize = 1;
|
||||
|
||||
static inline int StringSize(const string& value);
|
||||
static inline int BytesSize (const string& value);
|
||||
|
||||
static inline int GroupSize (const MessageLite& value);
|
||||
static inline int MessageSize(const MessageLite& value);
|
||||
|
||||
// Like above, but de-virtualize the call to ByteSize(). The
|
||||
// pointer must point at an instance of MessageType, *not* a subclass (or
|
||||
// the subclass must not override ByteSize()).
|
||||
template<typename MessageType>
|
||||
static inline int GroupSizeNoVirtual (const MessageType& value);
|
||||
template<typename MessageType>
|
||||
static inline int MessageSizeNoVirtual(const MessageType& value);
|
||||
|
||||
// Given the length of data, calculate the byte size of the data on the
|
||||
// wire if we encode the data as a length delimited field.
|
||||
static inline int LengthDelimitedSize(int length);
|
||||
|
||||
private:
|
||||
// A helper method for the repeated primitive reader. This method has
|
||||
// optimizations for primitive types that have fixed size on the wire, and
|
||||
// can be read using potentially faster paths.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static inline bool ReadRepeatedFixedSizePrimitive(
|
||||
int tag_size,
|
||||
uint32 tag,
|
||||
google::protobuf::io::CodedInputStream* input,
|
||||
RepeatedField<CType>* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
|
||||
|
||||
// Like ReadRepeatedFixedSizePrimitive but for packed primitive fields.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static inline bool ReadPackedFixedSizePrimitive(
|
||||
google::protobuf::io::CodedInputStream* input,
|
||||
RepeatedField<CType>* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
|
||||
|
||||
static const CppType kFieldTypeToCppTypeMap[];
|
||||
static const WireFormatLite::WireType kWireTypeForFieldType[];
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormatLite);
|
||||
};
|
||||
|
||||
// A class which deals with unknown values. The default implementation just
|
||||
// discards them. WireFormat defines a subclass which writes to an
|
||||
// UnknownFieldSet. This class is used by ExtensionSet::ParseField(), since
|
||||
// ExtensionSet is part of the lite library but UnknownFieldSet is not.
|
||||
class LIBPROTOBUF_EXPORT FieldSkipper {
|
||||
public:
|
||||
FieldSkipper() {}
|
||||
virtual ~FieldSkipper() {}
|
||||
|
||||
// Skip a field whose tag has already been consumed.
|
||||
virtual bool SkipField(io::CodedInputStream* input, uint32 tag);
|
||||
|
||||
// Skip an entire message or group, up to an end-group tag (which is consumed)
|
||||
// or end-of-stream.
|
||||
virtual bool SkipMessage(io::CodedInputStream* input);
|
||||
|
||||
// Deal with an already-parsed unrecognized enum value. The default
|
||||
// implementation does nothing, but the UnknownFieldSet-based implementation
|
||||
// saves it as an unknown varint.
|
||||
virtual void SkipUnknownEnum(int field_number, int value);
|
||||
};
|
||||
|
||||
// Subclass of FieldSkipper which saves skipped fields to a CodedOutputStream.
|
||||
|
||||
class LIBPROTOBUF_EXPORT CodedOutputStreamFieldSkipper : public FieldSkipper {
|
||||
public:
|
||||
explicit CodedOutputStreamFieldSkipper(io::CodedOutputStream* unknown_fields)
|
||||
: unknown_fields_(unknown_fields) {}
|
||||
virtual ~CodedOutputStreamFieldSkipper() {}
|
||||
|
||||
// implements FieldSkipper -----------------------------------------
|
||||
virtual bool SkipField(io::CodedInputStream* input, uint32 tag);
|
||||
virtual bool SkipMessage(io::CodedInputStream* input);
|
||||
virtual void SkipUnknownEnum(int field_number, int value);
|
||||
|
||||
protected:
|
||||
io::CodedOutputStream* unknown_fields_;
|
||||
};
|
||||
|
||||
|
||||
// inline methods ====================================================
|
||||
|
||||
inline WireFormatLite::CppType
|
||||
WireFormatLite::FieldTypeToCppType(FieldType type) {
|
||||
return kFieldTypeToCppTypeMap[type];
|
||||
}
|
||||
|
||||
inline uint32 WireFormatLite::MakeTag(int field_number, WireType type) {
|
||||
return GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(field_number, type);
|
||||
}
|
||||
|
||||
inline WireFormatLite::WireType WireFormatLite::GetTagWireType(uint32 tag) {
|
||||
return static_cast<WireType>(tag & kTagTypeMask);
|
||||
}
|
||||
|
||||
inline int WireFormatLite::GetTagFieldNumber(uint32 tag) {
|
||||
return static_cast<int>(tag >> kTagTypeBits);
|
||||
}
|
||||
|
||||
inline int WireFormatLite::TagSize(int field_number,
|
||||
WireFormatLite::FieldType type) {
|
||||
int result = io::CodedOutputStream::VarintSize32(
|
||||
field_number << kTagTypeBits);
|
||||
if (type == TYPE_GROUP) {
|
||||
// Groups have both a start and an end tag.
|
||||
return result * 2;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
inline uint32 WireFormatLite::EncodeFloat(float value) {
|
||||
union {float f; uint32 i;};
|
||||
f = value;
|
||||
return i;
|
||||
}
|
||||
|
||||
inline float WireFormatLite::DecodeFloat(uint32 value) {
|
||||
union {float f; uint32 i;};
|
||||
i = value;
|
||||
return f;
|
||||
}
|
||||
|
||||
inline uint64 WireFormatLite::EncodeDouble(double value) {
|
||||
union {double f; uint64 i;};
|
||||
f = value;
|
||||
return i;
|
||||
}
|
||||
|
||||
inline double WireFormatLite::DecodeDouble(uint64 value) {
|
||||
union {double f; uint64 i;};
|
||||
i = value;
|
||||
return f;
|
||||
}
|
||||
|
||||
// ZigZag Transform: Encodes signed integers so that they can be
|
||||
// effectively used with varint encoding.
|
||||
//
|
||||
// varint operates on unsigned integers, encoding smaller numbers into
|
||||
// fewer bytes. If you try to use it on a signed integer, it will treat
|
||||
// this number as a very large unsigned integer, which means that even
|
||||
// small signed numbers like -1 will take the maximum number of bytes
|
||||
// (10) to encode. ZigZagEncode() maps signed integers to unsigned
|
||||
// in such a way that those with a small absolute value will have smaller
|
||||
// encoded values, making them appropriate for encoding using varint.
|
||||
//
|
||||
// int32 -> uint32
|
||||
// -------------------------
|
||||
// 0 -> 0
|
||||
// -1 -> 1
|
||||
// 1 -> 2
|
||||
// -2 -> 3
|
||||
// ... -> ...
|
||||
// 2147483647 -> 4294967294
|
||||
// -2147483648 -> 4294967295
|
||||
//
|
||||
// >> encode >>
|
||||
// << decode <<
|
||||
|
||||
inline uint32 WireFormatLite::ZigZagEncode32(int32 n) {
|
||||
// Note: the right-shift must be arithmetic
|
||||
return (n << 1) ^ (n >> 31);
|
||||
}
|
||||
|
||||
inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
|
||||
return (n >> 1) ^ -static_cast<int32>(n & 1);
|
||||
}
|
||||
|
||||
inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
|
||||
// Note: the right-shift must be arithmetic
|
||||
return (n << 1) ^ (n >> 63);
|
||||
}
|
||||
|
||||
inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
|
||||
return (n >> 1) ^ -static_cast<int64>(n & 1);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
|
|
@ -0,0 +1,860 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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)
|
||||
// wink@google.com (Wink Saville) (refactored from wire_format.h)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__
|
||||
#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// This is required for min/max on VS2013 only.
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format_lite.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Implementation details of ReadPrimitive.
|
||||
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(
|
||||
io::CodedInputStream* input,
|
||||
int32* value) {
|
||||
uint32 temp;
|
||||
if (!input->ReadVarint32(&temp)) return false;
|
||||
*value = static_cast<int32>(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_INT64>(
|
||||
io::CodedInputStream* input,
|
||||
int64* value) {
|
||||
uint64 temp;
|
||||
if (!input->ReadVarint64(&temp)) return false;
|
||||
*value = static_cast<int64>(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>(
|
||||
io::CodedInputStream* input,
|
||||
uint32* value) {
|
||||
return input->ReadVarint32(value);
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_UINT64>(
|
||||
io::CodedInputStream* input,
|
||||
uint64* value) {
|
||||
return input->ReadVarint64(value);
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(
|
||||
io::CodedInputStream* input,
|
||||
int32* value) {
|
||||
uint32 temp;
|
||||
if (!input->ReadVarint32(&temp)) return false;
|
||||
*value = ZigZagDecode32(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SINT64>(
|
||||
io::CodedInputStream* input,
|
||||
int64* value) {
|
||||
uint64 temp;
|
||||
if (!input->ReadVarint64(&temp)) return false;
|
||||
*value = ZigZagDecode64(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_FIXED32>(
|
||||
io::CodedInputStream* input,
|
||||
uint32* value) {
|
||||
return input->ReadLittleEndian32(value);
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_FIXED64>(
|
||||
io::CodedInputStream* input,
|
||||
uint64* value) {
|
||||
return input->ReadLittleEndian64(value);
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SFIXED32>(
|
||||
io::CodedInputStream* input,
|
||||
int32* value) {
|
||||
uint32 temp;
|
||||
if (!input->ReadLittleEndian32(&temp)) return false;
|
||||
*value = static_cast<int32>(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SFIXED64>(
|
||||
io::CodedInputStream* input,
|
||||
int64* value) {
|
||||
uint64 temp;
|
||||
if (!input->ReadLittleEndian64(&temp)) return false;
|
||||
*value = static_cast<int64>(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<float, WireFormatLite::TYPE_FLOAT>(
|
||||
io::CodedInputStream* input,
|
||||
float* value) {
|
||||
uint32 temp;
|
||||
if (!input->ReadLittleEndian32(&temp)) return false;
|
||||
*value = DecodeFloat(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<double, WireFormatLite::TYPE_DOUBLE>(
|
||||
io::CodedInputStream* input,
|
||||
double* value) {
|
||||
uint64 temp;
|
||||
if (!input->ReadLittleEndian64(&temp)) return false;
|
||||
*value = DecodeDouble(temp);
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<bool, WireFormatLite::TYPE_BOOL>(
|
||||
io::CodedInputStream* input,
|
||||
bool* value) {
|
||||
uint64 temp;
|
||||
if (!input->ReadVarint64(&temp)) return false;
|
||||
*value = temp != 0;
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
inline bool WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
|
||||
io::CodedInputStream* input,
|
||||
int* value) {
|
||||
uint32 temp;
|
||||
if (!input->ReadVarint32(&temp)) return false;
|
||||
*value = static_cast<int>(temp);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
|
||||
uint32, WireFormatLite::TYPE_FIXED32>(
|
||||
const uint8* buffer,
|
||||
uint32* value) {
|
||||
return io::CodedInputStream::ReadLittleEndian32FromArray(buffer, value);
|
||||
}
|
||||
template <>
|
||||
inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
|
||||
uint64, WireFormatLite::TYPE_FIXED64>(
|
||||
const uint8* buffer,
|
||||
uint64* value) {
|
||||
return io::CodedInputStream::ReadLittleEndian64FromArray(buffer, value);
|
||||
}
|
||||
template <>
|
||||
inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
|
||||
int32, WireFormatLite::TYPE_SFIXED32>(
|
||||
const uint8* buffer,
|
||||
int32* value) {
|
||||
uint32 temp;
|
||||
buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp);
|
||||
*value = static_cast<int32>(temp);
|
||||
return buffer;
|
||||
}
|
||||
template <>
|
||||
inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
|
||||
int64, WireFormatLite::TYPE_SFIXED64>(
|
||||
const uint8* buffer,
|
||||
int64* value) {
|
||||
uint64 temp;
|
||||
buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp);
|
||||
*value = static_cast<int64>(temp);
|
||||
return buffer;
|
||||
}
|
||||
template <>
|
||||
inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
|
||||
float, WireFormatLite::TYPE_FLOAT>(
|
||||
const uint8* buffer,
|
||||
float* value) {
|
||||
uint32 temp;
|
||||
buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp);
|
||||
*value = DecodeFloat(temp);
|
||||
return buffer;
|
||||
}
|
||||
template <>
|
||||
inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
|
||||
double, WireFormatLite::TYPE_DOUBLE>(
|
||||
const uint8* buffer,
|
||||
double* value) {
|
||||
uint64 temp;
|
||||
buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp);
|
||||
*value = DecodeDouble(temp);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
|
||||
inline bool WireFormatLite::ReadRepeatedPrimitive(
|
||||
int, // tag_size, unused.
|
||||
uint32 tag,
|
||||
io::CodedInputStream* input,
|
||||
RepeatedField<CType>* values) {
|
||||
CType value;
|
||||
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
|
||||
values->Add(value);
|
||||
int elements_already_reserved = values->Capacity() - values->size();
|
||||
while (elements_already_reserved > 0 && input->ExpectTag(tag)) {
|
||||
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
|
||||
values->AddAlreadyReserved(value);
|
||||
elements_already_reserved--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
|
||||
inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive(
|
||||
int tag_size,
|
||||
uint32 tag,
|
||||
io::CodedInputStream* input,
|
||||
RepeatedField<CType>* values) {
|
||||
GOOGLE_DCHECK_EQ(UInt32Size(tag), tag_size);
|
||||
CType value;
|
||||
if (!ReadPrimitive<CType, DeclaredType>(input, &value))
|
||||
return false;
|
||||
values->Add(value);
|
||||
|
||||
// For fixed size values, repeated values can be read more quickly by
|
||||
// reading directly from a raw array.
|
||||
//
|
||||
// We can get a tight loop by only reading as many elements as can be
|
||||
// added to the RepeatedField without having to do any resizing. Additionally,
|
||||
// we only try to read as many elements as are available from the current
|
||||
// buffer space. Doing so avoids having to perform boundary checks when
|
||||
// reading the value: the maximum number of elements that can be read is
|
||||
// known outside of the loop.
|
||||
const void* void_pointer;
|
||||
int size;
|
||||
input->GetDirectBufferPointerInline(&void_pointer, &size);
|
||||
if (size > 0) {
|
||||
const uint8* buffer = reinterpret_cast<const uint8*>(void_pointer);
|
||||
// The number of bytes each type occupies on the wire.
|
||||
const int per_value_size = tag_size + sizeof(value);
|
||||
|
||||
int elements_available = min(values->Capacity() - values->size(),
|
||||
size / per_value_size);
|
||||
int num_read = 0;
|
||||
while (num_read < elements_available &&
|
||||
(buffer = io::CodedInputStream::ExpectTagFromArray(
|
||||
buffer, tag)) != NULL) {
|
||||
buffer = ReadPrimitiveFromArray<CType, DeclaredType>(buffer, &value);
|
||||
values->AddAlreadyReserved(value);
|
||||
++num_read;
|
||||
}
|
||||
const int read_bytes = num_read * per_value_size;
|
||||
if (read_bytes > 0) {
|
||||
input->Skip(read_bytes);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Specializations of ReadRepeatedPrimitive for the fixed size types, which use
|
||||
// the optimized code path.
|
||||
#define READ_REPEATED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \
|
||||
template <> \
|
||||
inline bool WireFormatLite::ReadRepeatedPrimitive< \
|
||||
CPPTYPE, WireFormatLite::DECLARED_TYPE>( \
|
||||
int tag_size, \
|
||||
uint32 tag, \
|
||||
io::CodedInputStream* input, \
|
||||
RepeatedField<CPPTYPE>* values) { \
|
||||
return ReadRepeatedFixedSizePrimitive< \
|
||||
CPPTYPE, WireFormatLite::DECLARED_TYPE>( \
|
||||
tag_size, tag, input, values); \
|
||||
}
|
||||
|
||||
READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32)
|
||||
READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64)
|
||||
READ_REPEATED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32)
|
||||
READ_REPEATED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64)
|
||||
READ_REPEATED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT)
|
||||
READ_REPEATED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE)
|
||||
|
||||
#undef READ_REPEATED_FIXED_SIZE_PRIMITIVE
|
||||
|
||||
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
|
||||
bool WireFormatLite::ReadRepeatedPrimitiveNoInline(
|
||||
int tag_size,
|
||||
uint32 tag,
|
||||
io::CodedInputStream* input,
|
||||
RepeatedField<CType>* value) {
|
||||
return ReadRepeatedPrimitive<CType, DeclaredType>(
|
||||
tag_size, tag, input, value);
|
||||
}
|
||||
|
||||
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
|
||||
inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input,
|
||||
RepeatedField<CType>* values) {
|
||||
uint32 length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
io::CodedInputStream::Limit limit = input->PushLimit(length);
|
||||
while (input->BytesUntilLimit() > 0) {
|
||||
CType value;
|
||||
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
|
||||
values->Add(value);
|
||||
}
|
||||
input->PopLimit(limit);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
|
||||
inline bool WireFormatLite::ReadPackedFixedSizePrimitive(
|
||||
io::CodedInputStream* input, RepeatedField<CType>* values) {
|
||||
uint32 length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
const uint32 old_entries = values->size();
|
||||
const uint32 new_entries = length / sizeof(CType);
|
||||
const uint32 new_bytes = new_entries * sizeof(CType);
|
||||
if (new_bytes != length) return false;
|
||||
// We would *like* to pre-allocate the buffer to write into (for
|
||||
// speed), but *must* avoid performing a very large allocation due
|
||||
// to a malicious user-supplied "length" above. So we have a fast
|
||||
// path that pre-allocates when the "length" is less than a bound.
|
||||
// We determine the bound by calling BytesUntilTotalBytesLimit() and
|
||||
// BytesUntilLimit(). These return -1 to mean "no limit set".
|
||||
// There are four cases:
|
||||
// TotalBytesLimit Limit
|
||||
// -1 -1 Use slow path.
|
||||
// -1 >= 0 Use fast path if length <= Limit.
|
||||
// >= 0 -1 Use slow path.
|
||||
// >= 0 >= 0 Use fast path if length <= min(both limits).
|
||||
int64 bytes_limit = input->BytesUntilTotalBytesLimit();
|
||||
if (bytes_limit == -1) {
|
||||
bytes_limit = input->BytesUntilLimit();
|
||||
} else {
|
||||
bytes_limit =
|
||||
min(bytes_limit, static_cast<int64>(input->BytesUntilLimit()));
|
||||
}
|
||||
if (bytes_limit >= new_bytes) {
|
||||
// Fast-path that pre-allocates *values to the final size.
|
||||
#if defined(PROTOBUF_LITTLE_ENDIAN)
|
||||
values->Resize(old_entries + new_entries, 0);
|
||||
// values->mutable_data() may change after Resize(), so do this after:
|
||||
void* dest = reinterpret_cast<void*>(values->mutable_data() + old_entries);
|
||||
if (!input->ReadRaw(dest, new_bytes)) {
|
||||
values->Truncate(old_entries);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
values->Reserve(old_entries + new_entries);
|
||||
CType value;
|
||||
for (int i = 0; i < new_entries; ++i) {
|
||||
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
|
||||
values->AddAlreadyReserved(value);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// This is the slow-path case where "length" may be too large to
|
||||
// safely allocate. We read as much as we can into *values
|
||||
// without pre-allocating "length" bytes.
|
||||
CType value;
|
||||
for (uint32 i = 0; i < new_entries; ++i) {
|
||||
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
|
||||
values->Add(value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Specializations of ReadPackedPrimitive for the fixed size types, which use
|
||||
// an optimized code path.
|
||||
#define READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \
|
||||
template <> \
|
||||
inline bool WireFormatLite::ReadPackedPrimitive< \
|
||||
CPPTYPE, WireFormatLite::DECLARED_TYPE>( \
|
||||
io::CodedInputStream* input, \
|
||||
RepeatedField<CPPTYPE>* values) { \
|
||||
return ReadPackedFixedSizePrimitive< \
|
||||
CPPTYPE, WireFormatLite::DECLARED_TYPE>(input, values); \
|
||||
}
|
||||
|
||||
READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32);
|
||||
READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64);
|
||||
READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32);
|
||||
READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64);
|
||||
READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT);
|
||||
READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE);
|
||||
|
||||
#undef READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE
|
||||
|
||||
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
|
||||
bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input,
|
||||
RepeatedField<CType>* values) {
|
||||
return ReadPackedPrimitive<CType, DeclaredType>(input, values);
|
||||
}
|
||||
|
||||
|
||||
inline bool WireFormatLite::ReadGroup(int field_number,
|
||||
io::CodedInputStream* input,
|
||||
MessageLite* value) {
|
||||
if (!input->IncrementRecursionDepth()) return false;
|
||||
if (!value->MergePartialFromCodedStream(input)) return false;
|
||||
input->DecrementRecursionDepth();
|
||||
// Make sure the last thing read was an end tag for this group.
|
||||
if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
inline bool WireFormatLite::ReadMessage(io::CodedInputStream* input,
|
||||
MessageLite* value) {
|
||||
uint32 length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
if (!input->IncrementRecursionDepth()) return false;
|
||||
io::CodedInputStream::Limit limit = input->PushLimit(length);
|
||||
if (!value->MergePartialFromCodedStream(input)) return false;
|
||||
// Make sure that parsing stopped when the limit was hit, not at an endgroup
|
||||
// tag.
|
||||
if (!input->ConsumedEntireMessage()) return false;
|
||||
input->PopLimit(limit);
|
||||
input->DecrementRecursionDepth();
|
||||
return true;
|
||||
}
|
||||
|
||||
// We name the template parameter something long and extremely unlikely to occur
|
||||
// elsewhere because a *qualified* member access expression designed to avoid
|
||||
// virtual dispatch, C++03 [basic.lookup.classref] 3.4.5/4 requires that the
|
||||
// name of the qualifying class to be looked up both in the context of the full
|
||||
// expression (finding the template parameter) and in the context of the object
|
||||
// whose member we are accessing. This could potentially find a nested type
|
||||
// within that object. The standard goes on to require these names to refer to
|
||||
// the same entity, which this collision would violate. The lack of a safe way
|
||||
// to avoid this collision appears to be a defect in the standard, but until it
|
||||
// is corrected, we choose the name to avoid accidental collisions.
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline bool WireFormatLite::ReadGroupNoVirtual(
|
||||
int field_number, io::CodedInputStream* input,
|
||||
MessageType_WorkAroundCppLookupDefect* value) {
|
||||
if (!input->IncrementRecursionDepth()) return false;
|
||||
if (!value->
|
||||
MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
|
||||
return false;
|
||||
input->DecrementRecursionDepth();
|
||||
// Make sure the last thing read was an end tag for this group.
|
||||
if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline bool WireFormatLite::ReadMessageNoVirtual(
|
||||
io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) {
|
||||
uint32 length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
if (!input->IncrementRecursionDepth()) return false;
|
||||
io::CodedInputStream::Limit limit = input->PushLimit(length);
|
||||
if (!value->
|
||||
MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
|
||||
return false;
|
||||
// Make sure that parsing stopped when the limit was hit, not at an endgroup
|
||||
// tag.
|
||||
if (!input->ConsumedEntireMessage()) return false;
|
||||
input->PopLimit(limit);
|
||||
input->DecrementRecursionDepth();
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
inline void WireFormatLite::WriteTag(int field_number, WireType type,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteTag(MakeTag(field_number, type));
|
||||
}
|
||||
|
||||
inline void WireFormatLite::WriteInt32NoTag(int32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint32SignExtended(value);
|
||||
}
|
||||
inline void WireFormatLite::WriteInt64NoTag(int64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint64(static_cast<uint64>(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteUInt32NoTag(uint32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint32(value);
|
||||
}
|
||||
inline void WireFormatLite::WriteUInt64NoTag(uint64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint64(value);
|
||||
}
|
||||
inline void WireFormatLite::WriteSInt32NoTag(int32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint32(ZigZagEncode32(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteSInt64NoTag(int64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint64(ZigZagEncode64(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteFixed32NoTag(uint32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteLittleEndian32(value);
|
||||
}
|
||||
inline void WireFormatLite::WriteFixed64NoTag(uint64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteLittleEndian64(value);
|
||||
}
|
||||
inline void WireFormatLite::WriteSFixed32NoTag(int32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteLittleEndian32(static_cast<uint32>(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteSFixed64NoTag(int64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteLittleEndian64(static_cast<uint64>(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteFloatNoTag(float value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteLittleEndian32(EncodeFloat(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteDoubleNoTag(double value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteLittleEndian64(EncodeDouble(value));
|
||||
}
|
||||
inline void WireFormatLite::WriteBoolNoTag(bool value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint32(value ? 1 : 0);
|
||||
}
|
||||
inline void WireFormatLite::WriteEnumNoTag(int value,
|
||||
io::CodedOutputStream* output) {
|
||||
output->WriteVarint32SignExtended(value);
|
||||
}
|
||||
|
||||
// See comment on ReadGroupNoVirtual to understand the need for this template
|
||||
// parameter name.
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline void WireFormatLite::WriteGroupNoVirtual(
|
||||
int field_number, const MessageType_WorkAroundCppLookupDefect& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_START_GROUP, output);
|
||||
value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output);
|
||||
WriteTag(field_number, WIRETYPE_END_GROUP, output);
|
||||
}
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline void WireFormatLite::WriteMessageNoVirtual(
|
||||
int field_number, const MessageType_WorkAroundCppLookupDefect& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
|
||||
output->WriteVarint32(
|
||||
value.MessageType_WorkAroundCppLookupDefect::GetCachedSize());
|
||||
value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output);
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
inline uint8* WireFormatLite::WriteTagToArray(int field_number,
|
||||
WireType type,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteTagToArray(MakeTag(field_number, type),
|
||||
target);
|
||||
}
|
||||
|
||||
inline uint8* WireFormatLite::WriteInt32NoTagToArray(int32 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteInt64NoTagToArray(int64 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint64ToArray(
|
||||
static_cast<uint64>(value), target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteUInt32NoTagToArray(uint32 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint32ToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteUInt64NoTagToArray(uint64 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint64ToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSInt32NoTagToArray(int32 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint32ToArray(ZigZagEncode32(value),
|
||||
target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSInt64NoTagToArray(int64 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint64ToArray(ZigZagEncode64(value),
|
||||
target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFixed32NoTagToArray(uint32 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteLittleEndian32ToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFixed64NoTagToArray(uint64 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteLittleEndian64ToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSFixed32NoTagToArray(int32 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteLittleEndian32ToArray(
|
||||
static_cast<uint32>(value), target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSFixed64NoTagToArray(int64 value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteLittleEndian64ToArray(
|
||||
static_cast<uint64>(value), target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFloatNoTagToArray(float value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteLittleEndian32ToArray(EncodeFloat(value),
|
||||
target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteDoubleNoTagToArray(double value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteLittleEndian64ToArray(EncodeDouble(value),
|
||||
target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteBoolNoTagToArray(bool value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint32ToArray(value ? 1 : 0, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteEnumNoTagToArray(int value,
|
||||
uint8* target) {
|
||||
return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target);
|
||||
}
|
||||
|
||||
inline uint8* WireFormatLite::WriteInt32ToArray(int field_number,
|
||||
int32 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteInt32NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteInt64ToArray(int field_number,
|
||||
int64 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteInt64NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteUInt32ToArray(int field_number,
|
||||
uint32 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteUInt32NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteUInt64ToArray(int field_number,
|
||||
uint64 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteUInt64NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSInt32ToArray(int field_number,
|
||||
int32 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteSInt32NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSInt64ToArray(int field_number,
|
||||
int64 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteSInt64NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFixed32ToArray(int field_number,
|
||||
uint32 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
|
||||
return WriteFixed32NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFixed64ToArray(int field_number,
|
||||
uint64 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
|
||||
return WriteFixed64NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSFixed32ToArray(int field_number,
|
||||
int32 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
|
||||
return WriteSFixed32NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteSFixed64ToArray(int field_number,
|
||||
int64 value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
|
||||
return WriteSFixed64NoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteFloatToArray(int field_number,
|
||||
float value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
|
||||
return WriteFloatNoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteDoubleToArray(int field_number,
|
||||
double value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
|
||||
return WriteDoubleNoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteBoolToArray(int field_number,
|
||||
bool value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteBoolNoTagToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteEnumToArray(int field_number,
|
||||
int value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
|
||||
return WriteEnumNoTagToArray(value, target);
|
||||
}
|
||||
|
||||
inline uint8* WireFormatLite::WriteStringToArray(int field_number,
|
||||
const string& value,
|
||||
uint8* target) {
|
||||
// String is for UTF-8 text only
|
||||
// WARNING: In wire_format.cc, both strings and bytes are handled by
|
||||
// WriteString() to avoid code duplication. If the implementations become
|
||||
// different, you will need to update that usage.
|
||||
target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
|
||||
return io::CodedOutputStream::WriteStringWithSizeToArray(value, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteBytesToArray(int field_number,
|
||||
const string& value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
|
||||
return io::CodedOutputStream::WriteStringWithSizeToArray(value, target);
|
||||
}
|
||||
|
||||
|
||||
inline uint8* WireFormatLite::WriteGroupToArray(int field_number,
|
||||
const MessageLite& value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
|
||||
target = value.SerializeWithCachedSizesToArray(target);
|
||||
return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
|
||||
}
|
||||
inline uint8* WireFormatLite::WriteMessageToArray(int field_number,
|
||||
const MessageLite& value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
|
||||
target = io::CodedOutputStream::WriteVarint32ToArray(
|
||||
value.GetCachedSize(), target);
|
||||
return value.SerializeWithCachedSizesToArray(target);
|
||||
}
|
||||
|
||||
// See comment on ReadGroupNoVirtual to understand the need for this template
|
||||
// parameter name.
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline uint8* WireFormatLite::WriteGroupNoVirtualToArray(
|
||||
int field_number, const MessageType_WorkAroundCppLookupDefect& value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
|
||||
target = value.MessageType_WorkAroundCppLookupDefect
|
||||
::SerializeWithCachedSizesToArray(target);
|
||||
return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
|
||||
}
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline uint8* WireFormatLite::WriteMessageNoVirtualToArray(
|
||||
int field_number, const MessageType_WorkAroundCppLookupDefect& value,
|
||||
uint8* target) {
|
||||
target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
|
||||
target = io::CodedOutputStream::WriteVarint32ToArray(
|
||||
value.MessageType_WorkAroundCppLookupDefect::GetCachedSize(), target);
|
||||
return value.MessageType_WorkAroundCppLookupDefect
|
||||
::SerializeWithCachedSizesToArray(target);
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
inline int WireFormatLite::Int32Size(int32 value) {
|
||||
return io::CodedOutputStream::VarintSize32SignExtended(value);
|
||||
}
|
||||
inline int WireFormatLite::Int64Size(int64 value) {
|
||||
return io::CodedOutputStream::VarintSize64(static_cast<uint64>(value));
|
||||
}
|
||||
inline int WireFormatLite::UInt32Size(uint32 value) {
|
||||
return io::CodedOutputStream::VarintSize32(value);
|
||||
}
|
||||
inline int WireFormatLite::UInt64Size(uint64 value) {
|
||||
return io::CodedOutputStream::VarintSize64(value);
|
||||
}
|
||||
inline int WireFormatLite::SInt32Size(int32 value) {
|
||||
return io::CodedOutputStream::VarintSize32(ZigZagEncode32(value));
|
||||
}
|
||||
inline int WireFormatLite::SInt64Size(int64 value) {
|
||||
return io::CodedOutputStream::VarintSize64(ZigZagEncode64(value));
|
||||
}
|
||||
inline int WireFormatLite::EnumSize(int value) {
|
||||
return io::CodedOutputStream::VarintSize32SignExtended(value);
|
||||
}
|
||||
|
||||
inline int WireFormatLite::StringSize(const string& value) {
|
||||
return io::CodedOutputStream::VarintSize32(value.size()) +
|
||||
value.size();
|
||||
}
|
||||
inline int WireFormatLite::BytesSize(const string& value) {
|
||||
return io::CodedOutputStream::VarintSize32(value.size()) +
|
||||
value.size();
|
||||
}
|
||||
|
||||
|
||||
inline int WireFormatLite::GroupSize(const MessageLite& value) {
|
||||
return value.ByteSize();
|
||||
}
|
||||
inline int WireFormatLite::MessageSize(const MessageLite& value) {
|
||||
return LengthDelimitedSize(value.ByteSize());
|
||||
}
|
||||
|
||||
// See comment on ReadGroupNoVirtual to understand the need for this template
|
||||
// parameter name.
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline int WireFormatLite::GroupSizeNoVirtual(
|
||||
const MessageType_WorkAroundCppLookupDefect& value) {
|
||||
return value.MessageType_WorkAroundCppLookupDefect::ByteSize();
|
||||
}
|
||||
template<typename MessageType_WorkAroundCppLookupDefect>
|
||||
inline int WireFormatLite::MessageSizeNoVirtual(
|
||||
const MessageType_WorkAroundCppLookupDefect& value) {
|
||||
return LengthDelimitedSize(
|
||||
value.MessageType_WorkAroundCppLookupDefect::ByteSize());
|
||||
}
|
||||
|
||||
inline int WireFormatLite::LengthDelimitedSize(int length) {
|
||||
return io::CodedOutputStream::VarintSize32(length) + length;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -3,6 +3,8 @@
|
|||
# CarlaServer.cpp
|
||||
# TCPServer.h
|
||||
# TCPServer.cpp
|
||||
# Protocol.h
|
||||
# Protocol.cpp
|
||||
# )
|
||||
file(GLOB carla_server_SRC
|
||||
"*.h"
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
#include "Carla.h"
|
||||
#include "CarlaCommunication.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace carla {
|
||||
namespace server {
|
||||
// -- Static methods ---------------------------------------------------------
|
||||
|
||||
template <typename ERROR_CODE>
|
||||
static void logTCPError(const std::string &text, const ERROR_CODE &errorCode) {
|
||||
std::cerr << "CarlaConnection - TCP Server: " << text << ": " << errorCode.message() << std::endl;
|
||||
}
|
||||
|
||||
// This is the thread that sends a string over the TCP socket.
|
||||
static void serverWorkerThread(TCPServer &server, std::string &message) {
|
||||
|
||||
TCPServer::error_code error;
|
||||
//message = message.size.c_ + message;
|
||||
|
||||
server.writeString(message, error);
|
||||
if (error)
|
||||
logTCPError("Failed to send", error);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//TODO:
|
||||
// Sortida amb google protocol
|
||||
// This is the thread that listens for string over the TCP socket.
|
||||
static std::string clientWorkerThread(TCPServer &server) {
|
||||
std::string message;
|
||||
TCPServer::error_code error;
|
||||
server.readString(message, error);
|
||||
if (error && (error != boost::asio::error::eof)) { // eof is expected.
|
||||
logTCPError("Failed to read", error);
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
//2threads para el mundo ? uno para leer y uno para enviar
|
||||
// This is the thread that listens & sends a string over the TCP world socket.
|
||||
static std::string worldReceiveThread(TCPServer &server) {
|
||||
|
||||
std::string message;
|
||||
TCPServer::error_code error;
|
||||
server.readString(message, error);
|
||||
if (error && (error != boost::asio::error::eof)) { // eof is expected.
|
||||
logTCPError("Failed to read", error);
|
||||
return std::string();
|
||||
}
|
||||
return message;
|
||||
|
||||
}
|
||||
|
||||
static void worldSendThread(TCPServer &server, std::string &message) {
|
||||
|
||||
TCPServer::error_code error;
|
||||
//message = message.size + message;
|
||||
server.writeString(message, error);
|
||||
if (error)
|
||||
logTCPError("Failed to send", error);
|
||||
|
||||
}
|
||||
|
||||
CarlaCommunication::CarlaCommunication(int writePort, int readPort, int worldPort) :
|
||||
_server(writePort),
|
||||
_client(readPort),
|
||||
_world(worldPort),
|
||||
_serverThread([this](std::string &str) { serverWorkerThread(this->_server, str); }),
|
||||
_clientThread([this]() { return clientWorkerThread(this->_client); }),
|
||||
_worldThread([this]() {return worldReceiveThread(this->_world); },
|
||||
[this](std::string &msg) { worldSendThread(this->_world, msg); })
|
||||
//_worldThread([this](const std::string &str) { serverWorkerThread(this->_server, str); })
|
||||
{}
|
||||
|
||||
void CarlaCommunication::sendReward(const Reward &reward) {
|
||||
std::string message;
|
||||
bool error = !reward.SerializeToString(&message);
|
||||
_serverThread.push(message);
|
||||
}
|
||||
|
||||
bool CarlaCommunication::tryReadControl(std::string &control) {
|
||||
return _clientThread.tryPop(control);
|
||||
}
|
||||
|
||||
void CarlaCommunication::sendWorld(const World &world) {
|
||||
std::string message;
|
||||
bool error = !world.SerializeToString(&message);
|
||||
_worldThread.push(message);
|
||||
}
|
||||
|
||||
void CarlaCommunication::sendScene(const Scene &scene) {
|
||||
std::string message;
|
||||
bool error = !scene.SerializeToString(&message);
|
||||
_worldThread.push(message);
|
||||
}
|
||||
|
||||
void CarlaCommunication::sendReset(const EpisodeReady &ready) {
|
||||
std::string message;
|
||||
bool error = !ready.SerializeToString(&message);
|
||||
_worldThread.push(message);
|
||||
}
|
||||
|
||||
bool CarlaCommunication::tryReadWorldInfo(std::string &info) {
|
||||
return _worldThread.tryPop(info);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include "carla/server/Protocol.h"
|
||||
#include "carla/server/TCPServer.h"
|
||||
|
||||
#include "carla/thread/AsyncReaderJobQueue.h"
|
||||
#include "carla/thread/AsyncWriterJobQueue.h"
|
||||
#include "carla/thread/AsyncreadWriteJobQueue.h"
|
||||
|
||||
namespace carla {
|
||||
namespace server {
|
||||
class CarlaCommunication : private NonCopyable {
|
||||
public:
|
||||
|
||||
explicit CarlaCommunication(int writePort, int readPort, int worldPort);
|
||||
|
||||
void sendReward(const Reward &reward);
|
||||
|
||||
bool tryReadControl(std::string &control);
|
||||
|
||||
void sendScene(const Scene &scene);
|
||||
|
||||
void sendReset(const EpisodeReady &ready);
|
||||
|
||||
void sendWorld(const World &world);
|
||||
|
||||
bool tryReadWorldInfo(std::string &info);
|
||||
|
||||
private:
|
||||
|
||||
TCPServer _server;
|
||||
|
||||
TCPServer _client;
|
||||
|
||||
TCPServer _world;
|
||||
|
||||
thread::AsyncReaderJobQueue<std::string> _serverThread;
|
||||
|
||||
thread::AsyncWriterJobQueue<std::string> _clientThread;
|
||||
|
||||
thread::AsyncReadWriteJobQueue<std::string, std::string> _worldThread;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
|
@ -3,86 +3,106 @@
|
|||
#include "Carla.h"
|
||||
#include "CarlaServer.h"
|
||||
|
||||
#include <carla/server/TCPServer.h>
|
||||
#include <carla/thread/AsyncReaderJobQueue.h>
|
||||
#include <carla/thread/AsyncWriterJobQueue.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
namespace carla {
|
||||
|
||||
namespace server {
|
||||
|
||||
template <typename ERROR_CODE>
|
||||
static void logTCPError(const std::string &text, const ERROR_CODE &errorCode) {
|
||||
std::cerr << "CarlaServer - TCP Server: " << text << ": " << errorCode.message() << std::endl;
|
||||
}
|
||||
|
||||
// -- Static methods ---------------------------------------------------------
|
||||
|
||||
// This is the thread that sends a string over the TCP socket.
|
||||
static void serverWorkerThread(TCPServer &server, const std::string &message) {
|
||||
TCPServer::error_code error;
|
||||
server.writeString(message, error);
|
||||
if (error)
|
||||
logTCPError("Failed to send", error);
|
||||
}
|
||||
|
||||
// This is the thread that listens for string over the TCP socket.
|
||||
static std::string clientWorkerThread(TCPServer &server) {
|
||||
std::string message;
|
||||
TCPServer::error_code error;
|
||||
server.readString(message, error);
|
||||
if (error && (error != boost::asio::error::eof)) { // eof is expected.
|
||||
logTCPError("Failed to read", error);
|
||||
return std::string();
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
// -- CarlaServer::Pimpl -----------------------------------------------------
|
||||
|
||||
class CarlaServer::Pimpl : private NonCopyable {
|
||||
public:
|
||||
|
||||
explicit Pimpl(int writePort, int readPort) :
|
||||
_server(writePort),
|
||||
_client(readPort),
|
||||
_serverThread([this](const std::string &str){ serverWorkerThread(this->_server, str); }),
|
||||
_clientThread([this](){ return clientWorkerThread(this->_client); }) {}
|
||||
|
||||
void writeString(const std::string &message) {
|
||||
_serverThread.push(message);
|
||||
}
|
||||
|
||||
bool tryReadString(std::string &message) {
|
||||
return _clientThread.tryPop(message);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
TCPServer _server;
|
||||
|
||||
TCPServer _client;
|
||||
|
||||
thread::AsyncReaderJobQueue<std::string> _serverThread;
|
||||
|
||||
thread::AsyncWriterJobQueue<std::string> _clientThread;
|
||||
};
|
||||
|
||||
// -- CarlaServer ------------------------------------------------------------
|
||||
|
||||
CarlaServer::CarlaServer(int writePort, int readPort) :
|
||||
_pimpl(std::make_unique<Pimpl>(writePort, readPort)) {}
|
||||
CarlaServer::CarlaServer(int writePort, int readPort, int worldPort, int modesCount, int scenesCount) :
|
||||
_communication(std::make_unique<CarlaCommunication>(writePort, readPort, worldPort)), _proto(std::make_unique<Protocol>(this)),
|
||||
_modes(modesCount),
|
||||
_scenes(scenesCount){}
|
||||
|
||||
CarlaServer::~CarlaServer() {}
|
||||
|
||||
void CarlaServer::writeString(const std::string &message) {
|
||||
_pimpl->writeString(message);
|
||||
void CarlaServer::sendReward(const Reward_Values &values) {
|
||||
Reward reward = _proto->LoadReward(values);
|
||||
_communication->sendReward(reward);
|
||||
}
|
||||
|
||||
bool CarlaServer::tryReadString(std::string &message) {
|
||||
return _pimpl->tryReadString(message);
|
||||
void CarlaServer::sendSceneValues(const Scene_Values &values) {
|
||||
Scene scene = _proto->LoadScene(values);
|
||||
_communication->sendScene(scene);
|
||||
}
|
||||
|
||||
void CarlaServer::sendEndReset() {
|
||||
EpisodeReady eReady;
|
||||
eReady.set_ready(true);
|
||||
_communication->sendReset(eReady);
|
||||
}
|
||||
|
||||
void CarlaServer::sendWord() {
|
||||
World world = _proto->LoadWorld();
|
||||
_communication->sendWorld(world);
|
||||
}
|
||||
|
||||
bool CarlaServer::tryReadControl(float &steer, float &gas) {
|
||||
std::string controlMessage;
|
||||
bool error = !_communication->tryReadControl(controlMessage);
|
||||
Control control;
|
||||
error &= !control.ParseFromString(controlMessage);
|
||||
steer = control.steer();
|
||||
gas = control.gas();
|
||||
|
||||
return !error;
|
||||
}
|
||||
|
||||
bool CarlaServer::tryReadSceneInit(int &mode, int &scene) {
|
||||
std::string initMessage;
|
||||
bool error = !_communication->tryReadWorldInfo(initMessage);
|
||||
SceneInit sceneInit;
|
||||
error &= !sceneInit.ParseFromString(initMessage);
|
||||
mode = sceneInit.mode();
|
||||
scene = sceneInit.scene();
|
||||
|
||||
return !error;
|
||||
}
|
||||
|
||||
bool CarlaServer::tryReadEpisodeStart(float &start_index, float &end_index) {
|
||||
std::string startData;
|
||||
bool error = !_communication->tryReadWorldInfo(startData);
|
||||
EpisodeStart episodeStart;
|
||||
error &= !episodeStart.ParseFromString(startData);
|
||||
start_index = episodeStart.start_index();
|
||||
end_index = episodeStart.end_index();
|
||||
|
||||
return !error;
|
||||
}
|
||||
|
||||
void CarlaServer::setMode(Mode mode) {
|
||||
_mode = mode;
|
||||
}
|
||||
|
||||
Mode CarlaServer::GetMode() const {
|
||||
return _mode;
|
||||
}
|
||||
|
||||
void CarlaServer::SetScene(int scene) {
|
||||
_scene = scene;
|
||||
}
|
||||
|
||||
int CarlaServer::GetScene() const {
|
||||
return _scene;
|
||||
}
|
||||
|
||||
int CarlaServer::GetModesCount() const {
|
||||
return _modes;
|
||||
}
|
||||
|
||||
int CarlaServer::GetScenesCount() const {
|
||||
return _scenes;
|
||||
}
|
||||
|
||||
void CarlaServer::SetReset(bool reset) {
|
||||
_reset = reset;
|
||||
}
|
||||
|
||||
bool CarlaServer::Reset() const {
|
||||
return _reset;
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
|
|
|
@ -2,12 +2,52 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "CarlaCommunication.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
|
||||
namespace carla {
|
||||
namespace server {
|
||||
|
||||
|
||||
struct Color {
|
||||
std::uint8_t red;
|
||||
std::uint8_t green;
|
||||
std::uint8_t blue;
|
||||
std::uint8_t alpha;
|
||||
};
|
||||
|
||||
struct Position {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
struct Reward_Values {
|
||||
float player_x, player_y;
|
||||
float speed;
|
||||
float collision_gen, collision_ped, collision_car;
|
||||
float intersect;
|
||||
float inertia_x, inertia_y, inertia_z;
|
||||
std::int32_t timestamp;
|
||||
float ori_x = 0, ori_y, ori_z;
|
||||
std::vector<Color> img;
|
||||
std::vector<Color> img_2;
|
||||
std::vector<Color> depth_1;
|
||||
std::vector<Color> depth_2;
|
||||
};
|
||||
|
||||
struct Scene_Values {
|
||||
std::vector<Position> _possible_Positions;
|
||||
std::vector<const float*> _projection_Matrix;
|
||||
};
|
||||
|
||||
enum Mode {
|
||||
MONO = 0,
|
||||
STEREO = 1
|
||||
};
|
||||
/// Asynchronous TCP server. Uses two ports, one for sending messages (write)
|
||||
/// and one for receiving messages (read).
|
||||
///
|
||||
|
@ -20,21 +60,62 @@ namespace server {
|
|||
public:
|
||||
|
||||
/// Starts two threads for writing and reading.
|
||||
explicit CarlaServer(int writePort, int readPort);
|
||||
explicit CarlaServer(int writePort, int readPort, int worldPort, int modesCount, int scenesCount);
|
||||
|
||||
~CarlaServer();
|
||||
|
||||
/// Push a string to the sending queue.
|
||||
void writeString(const std::string &message);
|
||||
///// Send values of the current player status
|
||||
void sendReward( const Reward_Values &values);
|
||||
|
||||
//// Send the values of the generated scene
|
||||
void sendSceneValues( const Scene_Values &values);
|
||||
|
||||
//// Send a signal to the client to notify that the car is ready
|
||||
void sendEndReset();
|
||||
|
||||
void sendWord();
|
||||
|
||||
///// Try to read the response of the client. Return false if the queue
|
||||
///// is empty.
|
||||
bool tryReadControl(float &steer, float &gas);
|
||||
|
||||
////Try to read if the client has selected an scene and mode. Return false if the queue is empty
|
||||
bool tryReadSceneInit(int &mode, int &scene);
|
||||
|
||||
////Try to read if the client has selected an end & start point. Return false if the queue is empty
|
||||
bool tryReadEpisodeStart(float &start_index, float &end_index);
|
||||
|
||||
|
||||
|
||||
int GetModesCount() const;
|
||||
int GetScenesCount() const;
|
||||
|
||||
void setMode(Mode mode);
|
||||
Mode GetMode() const;
|
||||
|
||||
void SetScene(int scene);
|
||||
int GetScene() const;
|
||||
|
||||
void SetReset(bool reset);
|
||||
bool Reset() const;
|
||||
|
||||
/// Try to read a string from the receiving queue. Return false if the queue
|
||||
/// is empty.
|
||||
bool tryReadString(std::string &message);
|
||||
|
||||
private:
|
||||
|
||||
class Pimpl;
|
||||
const std::unique_ptr<Pimpl> _pimpl;
|
||||
|
||||
std::mutex _mutex;
|
||||
|
||||
std::atomic<Mode> _mode = MONO;
|
||||
std::atomic_int _scene;
|
||||
std::atomic_bool _reset;
|
||||
|
||||
const int _modes;
|
||||
const int _scenes;
|
||||
|
||||
const std::unique_ptr<CarlaCommunication> _communication;
|
||||
|
||||
const std::unique_ptr<Protocol> _proto;
|
||||
|
||||
};
|
||||
|
||||
} // namespace server
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
#include "Carla.h"
|
||||
#include "Protocol.h"
|
||||
|
||||
#include "CarlaServer.h"
|
||||
|
||||
namespace carla {
|
||||
namespace server {
|
||||
Protocol::Protocol(carla::server::CarlaServer *server) {
|
||||
_server = server;
|
||||
}
|
||||
|
||||
Protocol::~Protocol() {
|
||||
|
||||
}
|
||||
|
||||
Reward Protocol::LoadReward(const Reward_Values &values) {
|
||||
Reward reward;
|
||||
reward.set_collision_car(values.collision_car);
|
||||
reward.set_collision_gen(values.collision_gen);
|
||||
reward.set_collision_ped(values.collision_ped);
|
||||
|
||||
//IMAGE 1
|
||||
std::string* image = reward.add_image();
|
||||
std::vector<Color> img = values.img;
|
||||
|
||||
for (int i = 0; i < img.size(); ++i) {
|
||||
image->append((const char*)img[i].red);
|
||||
image->append((const char*)img[i].green);
|
||||
image->append((const char*)img[i].blue);
|
||||
image->append((const char*)img[i].alpha);
|
||||
}
|
||||
|
||||
|
||||
if (_server->GetMode() == STEREO) {
|
||||
|
||||
//IMAGE 2
|
||||
image = reward.add_image();
|
||||
img = values.img_2;
|
||||
|
||||
for (int i = 0; i < img.size(); ++i) {
|
||||
image->append((const char*)img[i].red);
|
||||
image->append((const char*)img[i].green);
|
||||
image->append((const char*)img[i].blue);
|
||||
image->append((const char*)img[i].alpha);
|
||||
}
|
||||
|
||||
//DEPTH 1
|
||||
image = reward.add_image();
|
||||
img = values.depth_1;
|
||||
|
||||
for (int i = 0; i < img.size(); ++i) {
|
||||
image->append((const char*)img[i].red);
|
||||
image->append((const char*)img[i].green);
|
||||
image->append((const char*)img[i].blue);
|
||||
image->append((const char*)img[i].alpha);
|
||||
}
|
||||
|
||||
//DEPTH 2
|
||||
image = reward.add_image();
|
||||
img = values.depth_2;
|
||||
|
||||
for (int i = 0; i < img.size(); ++i) {
|
||||
image->append((const char*)img[i].red);
|
||||
image->append((const char*)img[i].green);
|
||||
image->append((const char*)img[i].blue);
|
||||
image->append((const char*)img[i].alpha);
|
||||
}
|
||||
}
|
||||
|
||||
reward.set_inertia_x(values.inertia_x);
|
||||
reward.set_inertia_y(values.inertia_y);
|
||||
reward.set_inertia_z(values.inertia_z);
|
||||
reward.set_intersect(values.intersect);
|
||||
reward.set_ori_x(values.ori_x);
|
||||
reward.set_ori_y(values.ori_y);
|
||||
reward.set_ori_z(values.ori_z);
|
||||
reward.set_player_y(values.player_y);
|
||||
reward.set_player_x(values.player_x);
|
||||
reward.set_speed(values.speed);
|
||||
reward.set_timestamp(values.timestamp);
|
||||
|
||||
return reward;
|
||||
}
|
||||
|
||||
Scene Protocol::LoadScene(const Scene_Values &values) {
|
||||
Scene scene;
|
||||
Scene::Position* point;
|
||||
std::vector<Position> positions = values._possible_Positions;
|
||||
for (int i = 0; i < positions.size(); ++i) {
|
||||
point = scene.add_position();
|
||||
point->set_pos_x(positions[i].x);
|
||||
point->set_pos_y(positions[i].y);
|
||||
}
|
||||
|
||||
|
||||
if (_server->GetMode() == STEREO) {
|
||||
Scene::Projection_Matrix* matrix;
|
||||
std::vector<const float*> projection_matrix = values._projection_Matrix;
|
||||
for (int i = 0; i < projection_matrix.size(); ++i) {
|
||||
matrix = scene.add_camera_matrix();
|
||||
for (int e = 0; e < 16; ++e) matrix->add_cam_param(projection_matrix[i][e]);
|
||||
}
|
||||
}
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
World Protocol::LoadWorld() {
|
||||
World world;
|
||||
world.add_modes(_server->GetModesCount());
|
||||
world.add_scenes(_server->GetModesCount());
|
||||
return world;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
#include "carla\Protocol\carlaProtocol\carla_protocol.pb.h"
|
||||
|
||||
//#include "carla\server\CarlaServer.h"
|
||||
#include <string>
|
||||
|
||||
namespace carla {
|
||||
namespace server {
|
||||
class CarlaServer;
|
||||
struct Reward_Values;
|
||||
struct Scene_Values;
|
||||
|
||||
class Protocol {
|
||||
|
||||
public:
|
||||
|
||||
Protocol(CarlaServer *server);
|
||||
~Protocol();
|
||||
|
||||
Reward LoadReward(const Reward_Values &values);
|
||||
|
||||
Scene LoadScene(const Scene_Values &values);
|
||||
|
||||
World LoadWorld();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
carla::server::CarlaServer *_server;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
// CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <carla/thread/ThreadSafeQueue.h>
|
||||
#include <carla/thread/ThreadUniquePointer.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
|
||||
namespace carla {
|
||||
namespace thread {
|
||||
|
||||
/// Executes the given job asynchronously. Every item that the job returns is
|
||||
/// added to the queue.
|
||||
template <typename W, typename R>
|
||||
class CARLA_API AsyncReadWriteJobQueue {
|
||||
public:
|
||||
|
||||
using WritingJob = std::function<W()>;
|
||||
using ReadingJob = std::function<void(R)>;
|
||||
|
||||
explicit AsyncReadWriteJobQueue(WritingJob &&writingJob, ReadingJob &&readingJob) :
|
||||
_done(false),
|
||||
_writeJob(std::move(writingJob)),
|
||||
_readJob(std::move(readingJob)),
|
||||
_writeQueue(),
|
||||
_thread(new std::thread(&AsyncReadWriteJobQueue::workerThread, this)) {}
|
||||
|
||||
~AsyncReadWriteJobQueue() {
|
||||
_done = true;
|
||||
}
|
||||
|
||||
bool tryPop(W &value) {
|
||||
return _writeQueue.try_pop(value);
|
||||
}
|
||||
|
||||
void push(R item) {
|
||||
_readQueue.push(item);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void workerThread() {
|
||||
while (!_done) {
|
||||
_writeQueue.push(_writeJob());
|
||||
R value;
|
||||
_readQueue.try_pop(value);
|
||||
_readJob(value);
|
||||
}
|
||||
}
|
||||
|
||||
std::atomic_bool _done;
|
||||
|
||||
WritingJob _writeJob;
|
||||
ReadingJob _readJob;
|
||||
|
||||
ThreadSafeQueue<W> _writeQueue;
|
||||
ThreadSafeQueue<R> _readQueue;
|
||||
|
||||
const ThreadUniquePointer _thread;
|
||||
};
|
||||
|
||||
} // namespace thread
|
||||
} // namespace carla
|
|
@ -23,7 +23,8 @@ namespace thread {
|
|||
_done(false),
|
||||
_job(std::move(job)),
|
||||
_queue(),
|
||||
_thread(new std::thread(&AsyncWriterJobQueue::workerThread, this)) {}
|
||||
_thread(new std::thread(&AsyncWriterJobQueue::workerThread, this))
|
||||
{}
|
||||
|
||||
~AsyncWriterJobQueue() {
|
||||
_done = true;
|
||||
|
@ -48,6 +49,7 @@ namespace thread {
|
|||
ThreadSafeQueue<T> _queue;
|
||||
|
||||
const ThreadUniquePointer _thread;
|
||||
|
||||
};
|
||||
|
||||
} // namespace thread
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
add_executable(test_async_server async_server.cpp)
|
||||
target_link_libraries(test_async_server carla_server ${Boost_SYSTEM_LIBRARY} ${Boost_DATE_TIME_LIBRARY} ${Boost_REGEX_LIBRARY})
|
||||
target_link_libraries(test_async_server carla_server ${Boost_DATE_TIME_LIBRARY} ${Boost_REGEX_LIBRARY} ${Boost_SYSTEM_LIBRARY})
|
||||
|
||||
add_executable(test_sync_server sync_server.cpp)
|
||||
target_link_libraries(test_sync_server carla_server ${Boost_SYSTEM_LIBRARY} ${Boost_DATE_TIME_LIBRARY} ${Boost_REGEX_LIBRARY})
|
||||
|
||||
add_executable(test_client client.cpp)
|
||||
target_link_libraries(test_client carla_server ${Boost_SYSTEM_LIBRARY} ${Boost_DATE_TIME_LIBRARY} ${Boost_REGEX_LIBRARY})
|
||||
target_link_libraries(test_client carla_server libprotobuf libprotobuf-lite libprotoc ${Boost_SYSTEM_LIBRARY} ${Boost_DATE_TIME_LIBRARY} ${Boost_REGEX_LIBRARY})
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
#include "Carla.h"
|
||||
|
||||
#include <carla/server/CarlaServer.h>
|
||||
#include "carla/server/CarlaServer.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
enum ErrorCodes {
|
||||
InvalidArguments,
|
||||
|
@ -35,24 +36,115 @@ int main(int argc, char* argv[]) {
|
|||
return InvalidArguments;
|
||||
}
|
||||
|
||||
using namespace carla::server;
|
||||
|
||||
// This already starts the two threads.
|
||||
carla::server::CarlaServer server(toInt(argv[1u]), toInt(argv[2u]));
|
||||
CarlaServer server(toInt(argv[1u]), toInt(argv[2u]), toInt(argv[3u]), toInt(argv[4u]), toInt(argv[5u]));
|
||||
|
||||
// Let's simulate the game loop.
|
||||
|
||||
|
||||
Color c1;
|
||||
c1.red = 1;
|
||||
c1.green = 2;
|
||||
c1.blue = 3;
|
||||
c1.alpha = 0;
|
||||
|
||||
Color c2;
|
||||
c2.red = 1;
|
||||
c2.green = 2;
|
||||
c2.blue = 3;
|
||||
c2.alpha = 0;
|
||||
|
||||
Color c3;
|
||||
c3.red = 1;
|
||||
c3.green = 2;
|
||||
c3.blue = 3;
|
||||
c3.alpha = 0;
|
||||
|
||||
Color c4;
|
||||
c4.red = 1;
|
||||
c4.green = 2;
|
||||
c4.blue = 3;
|
||||
c4.alpha = 0;
|
||||
|
||||
std::vector<Color> img;
|
||||
img.push_back(c1);
|
||||
std::vector<Color> img_2;
|
||||
img_2.push_back(c2);
|
||||
std::vector<Color> depth_1;
|
||||
depth_1.push_back(c3);
|
||||
std::vector<Color> depth_2;
|
||||
depth_2.push_back(c4);
|
||||
|
||||
Reward_Values testData;
|
||||
testData.player_x = 1.0f;
|
||||
testData.player_y = 1.0f;
|
||||
testData.speed = 100.0f;
|
||||
testData.collision_gen = 10.0f;
|
||||
testData.collision_ped = 10.0f;
|
||||
testData.collision_car = 10.0f;
|
||||
testData.intersect = 50.0f;
|
||||
testData.inertia_x = 0.5f;
|
||||
testData.inertia_y = 0.1f;
|
||||
testData.inertia_z = 0.02f;
|
||||
testData.timestamp = 1;
|
||||
testData.ori_x = 10.0f;
|
||||
testData.ori_y = 20.0f;
|
||||
testData.ori_z = 30.0f;
|
||||
testData.img = img;
|
||||
testData.img_2 = img_2;
|
||||
testData.depth_1 = depth_1;
|
||||
testData.depth_2 = depth_2;
|
||||
|
||||
|
||||
server.sendWord();
|
||||
|
||||
int mode, scene;
|
||||
while (!server.tryReadSceneInit(mode, scene));
|
||||
|
||||
std::cout << "Mode: " << mode << " Scene: " << scene << std::endl;
|
||||
|
||||
|
||||
std::vector<Position> positions;
|
||||
std::vector<const float*> pMatrix;
|
||||
|
||||
positions.push_back(Position{ 0.0f, 0.0f });
|
||||
positions.push_back(Position{ 1.0f, 2.0f });
|
||||
positions.push_back(Position{ 3.0f, 4.0f });
|
||||
|
||||
float list[16] = { 10.0, 10.0,10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0 };
|
||||
|
||||
pMatrix.push_back(list);
|
||||
|
||||
Scene_Values sceneVal = {
|
||||
positions,
|
||||
pMatrix,
|
||||
};
|
||||
|
||||
server.sendSceneValues(sceneVal);
|
||||
|
||||
float start, end;
|
||||
while (!server.tryReadEpisodeStart(start, end));
|
||||
|
||||
std::cout << "Start: " << start << " End: " << end << std::endl;
|
||||
|
||||
server.sendEndReset();
|
||||
|
||||
for (;;) {
|
||||
std::cout << "Sending..." << std::endl;
|
||||
auto time = daytimeString();
|
||||
server.writeString(time);
|
||||
|
||||
// server.reward = testData;
|
||||
server.sendReward(testData);
|
||||
using namespace std::chrono_literals;
|
||||
std::this_thread::sleep_for(1s);
|
||||
|
||||
std::cout << "Listening..." << std::endl;
|
||||
std::string message;
|
||||
if (server.tryReadString(message)) {
|
||||
std::cout << "Received: " << message << std::endl;
|
||||
if ((message == "q") || (message == "quit"))
|
||||
break;
|
||||
float steer, gas;
|
||||
if (server.tryReadControl(steer, gas)) {
|
||||
std::cout << "Received: steer: " << steer << " gas: " << gas << std::endl;
|
||||
/*if ((message == "q") || (message == "quit"))
|
||||
break;*/
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue