parent
9dabf51ac7
commit
dec6d3d379
@ -1,4 +1,5 @@
|
|||||||
Copyright 2008 Google Inc. All rights reserved.
|
Copyright 2008, Google Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are
|
modification, are permitted provided that the following conditions are
|
@ -1,9 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
|
||||||
|
|
||||||
message(WARNING "Calling of cmake with source directory set to \"cmake\" subdirectory of Protocol Buffers project is deprecated. Top-level directory of Protocol Buffers project should be used instead.")
|
|
||||||
|
|
||||||
project(protobuf C CXX)
|
|
||||||
|
|
||||||
set(protobuf_DEPRECATED_CMAKE_SUBDIRECTORY_USAGE TRUE)
|
|
||||||
|
|
||||||
include(../CMakeLists.txt)
|
|
@ -1,49 +0,0 @@
|
|||||||
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${protobuf_SOURCE_DIR}/conformance/conformance.pb.cc
|
|
||||||
DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/conformance/conformance.proto
|
|
||||||
COMMAND ${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/conformance/conformance.proto
|
|
||||||
--proto_path=${protobuf_SOURCE_DIR}/conformance
|
|
||||||
--cpp_out=${protobuf_SOURCE_DIR}/conformance
|
|
||||||
)
|
|
||||||
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.cc
|
|
||||||
DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.proto
|
|
||||||
${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.proto
|
|
||||||
COMMAND ${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.proto
|
|
||||||
--proto_path=${protobuf_SOURCE_DIR}/src
|
|
||||||
--cpp_out=${protobuf_SOURCE_DIR}/src
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(conformance_test_runner
|
|
||||||
${protobuf_SOURCE_DIR}/conformance/binary_json_conformance_suite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/conformance/binary_json_conformance_suite.h
|
|
||||||
${protobuf_SOURCE_DIR}/conformance/conformance.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/conformance/conformance_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/conformance/conformance_test_runner.cc
|
|
||||||
${protobuf_SOURCE_DIR}/conformance/third_party/jsoncpp/json.h
|
|
||||||
${protobuf_SOURCE_DIR}/conformance/third_party/jsoncpp/jsoncpp.cpp
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.cc
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(conformance_cpp
|
|
||||||
${protobuf_SOURCE_DIR}/conformance/conformance.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/conformance/conformance_cpp.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.cc
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(
|
|
||||||
conformance_test_runner
|
|
||||||
PUBLIC ${protobuf_SOURCE_DIR}/conformance)
|
|
||||||
|
|
||||||
target_include_directories(
|
|
||||||
conformance_cpp
|
|
||||||
PUBLIC ${protobuf_SOURCE_DIR}/conformance)
|
|
||||||
|
|
||||||
target_link_libraries(conformance_test_runner libprotobuf)
|
|
||||||
target_link_libraries(conformance_cpp libprotobuf)
|
|
@ -1,57 +0,0 @@
|
|||||||
if(protobuf_VERBOSE)
|
|
||||||
message(STATUS "Protocol Buffers Examples Configuring...")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
get_filename_component(examples_dir "${protobuf_SOURCE_DIR}/examples" ABSOLUTE)
|
|
||||||
|
|
||||||
if(protobuf_VERBOSE)
|
|
||||||
message(STATUS "Protocol Buffers Examples Configuring done")
|
|
||||||
endif()
|
|
||||||
include(ExternalProject)
|
|
||||||
|
|
||||||
# Internal utility function: Create a custom target representing a build of examples with custom options.
|
|
||||||
function(add_examples_build NAME)
|
|
||||||
|
|
||||||
ExternalProject_Add(${NAME}
|
|
||||||
PREFIX ${NAME}
|
|
||||||
SOURCE_DIR "${examples_dir}"
|
|
||||||
BINARY_DIR ${NAME}
|
|
||||||
STAMP_DIR ${NAME}/logs
|
|
||||||
INSTALL_COMMAND "" #Skip
|
|
||||||
LOG_CONFIGURE 1
|
|
||||||
CMAKE_CACHE_ARGS "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
|
|
||||||
"-Dprotobuf_VERBOSE:BOOL=${protobuf_VERBOSE}"
|
|
||||||
${ARGN}
|
|
||||||
)
|
|
||||||
set_property(TARGET ${NAME} PROPERTY FOLDER "Examples")
|
|
||||||
set_property(TARGET ${NAME} PROPERTY EXCLUDE_FROM_ALL TRUE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Add examples as an external project.
|
|
||||||
# sub_directory cannot be used because the find_package(protobuf) call would cause failures with redefined targets.
|
|
||||||
add_examples_build(examples "-Dprotobuf_DIR:PATH=${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}")
|
|
||||||
add_dependencies(examples libprotobuf protoc)
|
|
||||||
|
|
||||||
option(protobuf_BUILD_EXAMPLES_MULTITEST "Build Examples in multiple configurations. Useful for testing." OFF)
|
|
||||||
mark_as_advanced(protobuf_BUILD_EXAMPLES_MULTITEST)
|
|
||||||
if(protobuf_BUILD_EXAMPLES_MULTITEST)
|
|
||||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
|
||||||
|
|
||||||
#Build using the legacy compatibility module.
|
|
||||||
add_examples_build(examples-legacy
|
|
||||||
"-Dprotobuf_DIR:PATH=${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}"
|
|
||||||
"-Dprotobuf_MODULE_COMPATIBLE:BOOL=TRUE"
|
|
||||||
)
|
|
||||||
add_dependencies(examples-legacy libprotobuf protoc)
|
|
||||||
|
|
||||||
#Build using the installed library.
|
|
||||||
add_examples_build(examples-installed
|
|
||||||
"-Dprotobuf_DIR:PATH=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}"
|
|
||||||
)
|
|
||||||
|
|
||||||
#Build using the installed library in legacy compatibility mode.
|
|
||||||
add_examples_build(examples-installed-legacy
|
|
||||||
"-Dprotobuf_DIR:PATH=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}"
|
|
||||||
"-Dprotobuf_MODULE_COMPATIBLE:BOOL=TRUE"
|
|
||||||
)
|
|
||||||
endif()
|
|
@ -1,144 +0,0 @@
|
|||||||
mkdir include
|
|
||||||
mkdir include\google
|
|
||||||
mkdir include\google\protobuf
|
|
||||||
mkdir include\google\protobuf\compiler
|
|
||||||
mkdir include\google\protobuf\compiler\cpp
|
|
||||||
mkdir include\google\protobuf\compiler\csharp
|
|
||||||
mkdir include\google\protobuf\compiler\java
|
|
||||||
mkdir include\google\protobuf\compiler\objectivec
|
|
||||||
mkdir include\google\protobuf\compiler\php
|
|
||||||
mkdir include\google\protobuf\compiler\python
|
|
||||||
mkdir include\google\protobuf\compiler\ruby
|
|
||||||
mkdir include\google\protobuf\io
|
|
||||||
mkdir include\google\protobuf\stubs
|
|
||||||
mkdir include\google\protobuf\util
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.h" include\google\protobuf\any.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.pb.h" include\google\protobuf\any.pb.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\api.pb.h" include\google\protobuf\api.pb.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arena.h" include\google\protobuf\arena.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arena_impl.h" include\google\protobuf\arena_impl.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arenastring.h" include\google\protobuf\arenastring.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arenaz_sampler.h" include\google\protobuf\arenaz_sampler.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\code_generator.h" include\google\protobuf\compiler\code_generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\command_line_interface.h" include\google\protobuf\compiler\command_line_interface.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\file.h" include\google\protobuf\compiler\cpp\file.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_generator.h" include\google\protobuf\compiler\cpp\cpp_generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\generator.h" include\google\protobuf\compiler\cpp\generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\helpers.h" include\google\protobuf\compiler\cpp\helpers.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\names.h" include\google\protobuf\compiler\cpp\names.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_doc_comment.h" include\google\protobuf\compiler\csharp\csharp_doc_comment.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_generator.h" include\google\protobuf\compiler\csharp\csharp_generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_names.h" include\google\protobuf\compiler\csharp\csharp_names.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_options.h" include\google\protobuf\compiler\csharp\csharp_options.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\importer.h" include\google\protobuf\compiler\importer.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\generator.h" include\google\protobuf\compiler\java\generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_generator.h" include\google\protobuf\compiler\java\java_generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\kotlin_generator.h" include\google\protobuf\compiler\java\kotlin_generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\names.h" include\google\protobuf\compiler\java\names.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_generator.h" include\google\protobuf\compiler\objectivec\objectivec_generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_helpers.h" include\google\protobuf\compiler\objectivec\objectivec_helpers.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\parser.h" include\google\protobuf\compiler\parser.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\php\php_generator.h" include\google\protobuf\compiler\php\php_generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.h" include\google\protobuf\compiler\plugin.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.pb.h" include\google\protobuf\compiler\plugin.pb.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\generator.h" include\google\protobuf\compiler\python\generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\pyi_generator.h" include\google\protobuf\compiler\python\pyi_generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\python_generator.h" include\google\protobuf\compiler\python\python_generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\ruby\ruby_generator.h" include\google\protobuf\compiler\ruby\ruby_generator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.h" include\google\protobuf\descriptor.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.pb.h" include\google\protobuf\descriptor.pb.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor_database.h" include\google\protobuf\descriptor_database.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\duration.pb.h" include\google\protobuf\duration.pb.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\dynamic_message.h" include\google\protobuf\dynamic_message.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\empty.pb.h" include\google\protobuf\empty.pb.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\endian.h" include\google\protobuf\endian.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\explicitly_constructed.h" include\google\protobuf\explicitly_constructed.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\extension_set.h" include\google\protobuf\extension_set.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\extension_set_inl.h" include\google\protobuf\extension_set_inl.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_access_listener.h" include\google\protobuf\field_access_listener.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_mask.pb.h" include\google\protobuf\field_mask.pb.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_reflection.h" include\google\protobuf\generated_enum_reflection.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_util.h" include\google\protobuf\generated_enum_util.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_bases.h" include\google\protobuf\generated_message_bases.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_reflection.h" include\google\protobuf\generated_message_reflection.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_tctable_decl.h" include\google\protobuf\generated_message_tctable_decl.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_tctable_impl.h" include\google\protobuf\generated_message_tctable_impl.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_util.h" include\google\protobuf\generated_message_util.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\has_bits.h" include\google\protobuf\has_bits.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\implicit_weak_message.h" include\google\protobuf\implicit_weak_message.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\inlined_string_field.h" include\google\protobuf\inlined_string_field.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\coded_stream.h" include\google\protobuf\io\coded_stream.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\gzip_stream.h" include\google\protobuf\io\gzip_stream.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\io_win32.h" include\google\protobuf\io\io_win32.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\printer.h" include\google\protobuf\io\printer.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\strtod.h" include\google\protobuf\io\strtod.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\tokenizer.h" include\google\protobuf\io\tokenizer.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream.h" include\google\protobuf\io\zero_copy_stream.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream_impl.h" include\google\protobuf\io\zero_copy_stream_impl.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream_impl_lite.h" include\google\protobuf\io\zero_copy_stream_impl_lite.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map.h" include\google\protobuf\map.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_entry.h" include\google\protobuf\map_entry.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_entry_lite.h" include\google\protobuf\map_entry_lite.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field.h" include\google\protobuf\map_field.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field_inl.h" include\google\protobuf\map_field_inl.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field_lite.h" include\google\protobuf\map_field_lite.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_type_handler.h" include\google\protobuf\map_type_handler.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message.h" include\google\protobuf\message.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message_lite.h" include\google\protobuf\message_lite.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata.h" include\google\protobuf\metadata.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata_lite.h" include\google\protobuf\metadata_lite.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\parse_context.h" include\google\protobuf\parse_context.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\port.h" include\google\protobuf\port.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\port_def.inc" include\google\protobuf\port_def.inc
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\port_undef.inc" include\google\protobuf\port_undef.inc
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection.h" include\google\protobuf\reflection.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection_ops.h" include\google\protobuf\reflection_ops.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field.h" include\google\protobuf\repeated_field.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_ptr_field.h" include\google\protobuf\repeated_ptr_field.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\service.h" include\google\protobuf\service.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.pb.h" include\google\protobuf\source_context.pb.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.pb.h" include\google\protobuf\struct.pb.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\bytestream.h" include\google\protobuf\stubs\bytestream.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\callback.h" include\google\protobuf\stubs\callback.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\casts.h" include\google\protobuf\stubs\casts.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\common.h" include\google\protobuf\stubs\common.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\hash.h" include\google\protobuf\stubs\hash.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\logging.h" include\google\protobuf\stubs\logging.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\macros.h" include\google\protobuf\stubs\macros.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\map_util.h" include\google\protobuf\stubs\map_util.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\mutex.h" include\google\protobuf\stubs\mutex.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\once.h" include\google\protobuf\stubs\once.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\platform_macros.h" include\google\protobuf\stubs\platform_macros.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\port.h" include\google\protobuf\stubs\port.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\status.h" include\google\protobuf\stubs\status.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stl_util.h" include\google\protobuf\stubs\stl_util.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stringpiece.h" include\google\protobuf\stubs\stringpiece.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\strutil.h" include\google\protobuf\stubs\strutil.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\template_util.h" include\google\protobuf\stubs\template_util.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\text_format.h" include\google\protobuf\text_format.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.pb.h" include\google\protobuf\timestamp.pb.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.pb.h" include\google\protobuf\type.pb.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\unknown_field_set.h" include\google\protobuf\unknown_field_set.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\delimited_message_util.h" include\google\protobuf\util\delimited_message_util.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_comparator.h" include\google\protobuf\util\field_comparator.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_mask_util.h" include\google\protobuf\util\field_mask_util.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\json_util.h" include\google\protobuf\util\json_util.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\message_differencer.h" include\google\protobuf\util\message_differencer.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\time_util.h" include\google\protobuf\util\time_util.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver.h" include\google\protobuf\util\type_resolver.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver_util.h" include\google\protobuf\util\type_resolver_util.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format.h" include\google\protobuf\wire_format.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite.h" include\google\protobuf\wire_format_lite.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wrappers.pb.h" include\google\protobuf\wrappers.pb.h
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.proto" include\google\protobuf\any.proto
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\api.proto" include\google\protobuf\api.proto
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.proto" include\google\protobuf\compiler\plugin.proto
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.proto" include\google\protobuf\descriptor.proto
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\duration.proto" include\google\protobuf\duration.proto
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\empty.proto" include\google\protobuf\empty.proto
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_mask.proto" include\google\protobuf\field_mask.proto
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.proto" include\google\protobuf\source_context.proto
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.proto" include\google\protobuf\struct.proto
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.proto" include\google\protobuf\timestamp.proto
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.proto" include\google\protobuf\type.proto
|
|
||||||
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wrappers.proto" include\google\protobuf\wrappers.proto
|
|
@ -1,156 +0,0 @@
|
|||||||
include(GNUInstallDirs)
|
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/protobuf.pc.cmake
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/protobuf.pc @ONLY)
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/protobuf-lite.pc.cmake
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/protobuf-lite.pc @ONLY)
|
|
||||||
|
|
||||||
set(_protobuf_libraries libprotobuf-lite libprotobuf)
|
|
||||||
if (protobuf_BUILD_LIBPROTOC)
|
|
||||||
list(APPEND _protobuf_libraries libprotoc)
|
|
||||||
endif (protobuf_BUILD_LIBPROTOC)
|
|
||||||
|
|
||||||
foreach(_library ${_protobuf_libraries})
|
|
||||||
set_property(TARGET ${_library}
|
|
||||||
PROPERTY INTERFACE_INCLUDE_DIRECTORIES
|
|
||||||
$<BUILD_INTERFACE:${protobuf_SOURCE_DIR}/src>
|
|
||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
set_property(TARGET ${_library}
|
|
||||||
PROPERTY INSTALL_RPATH "$ORIGIN")
|
|
||||||
elseif (APPLE)
|
|
||||||
set_property(TARGET ${_library}
|
|
||||||
PROPERTY INSTALL_RPATH "@loader_path")
|
|
||||||
endif()
|
|
||||||
install(TARGETS ${_library} EXPORT protobuf-targets
|
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${_library}
|
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library}
|
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library})
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if (protobuf_BUILD_PROTOC_BINARIES)
|
|
||||||
install(TARGETS protoc EXPORT protobuf-targets
|
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc
|
|
||||||
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc)
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
set_property(TARGET protoc
|
|
||||||
PROPERTY INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}")
|
|
||||||
elseif (APPLE)
|
|
||||||
set_property(TARGET protoc
|
|
||||||
PROPERTY INSTALL_RPATH "@loader_path/../lib")
|
|
||||||
endif()
|
|
||||||
endif (protobuf_BUILD_PROTOC_BINARIES)
|
|
||||||
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/protobuf.pc ${CMAKE_CURRENT_BINARY_DIR}/protobuf-lite.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
|
||||||
|
|
||||||
file(STRINGS ${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in _extract_strings
|
|
||||||
REGEX "^copy")
|
|
||||||
foreach(_extract_string ${_extract_strings})
|
|
||||||
string(REGEX REPLACE "^.* .+ include\\\\(.+)$" "\\1"
|
|
||||||
_header ${_extract_string})
|
|
||||||
string(REPLACE "\\" "/" _header ${_header})
|
|
||||||
get_filename_component(_extract_from "${protobuf_SOURCE_DIR}/src/${_header}" ABSOLUTE)
|
|
||||||
get_filename_component(_extract_name ${_header} NAME)
|
|
||||||
get_filename_component(_extract_to "${CMAKE_INSTALL_INCLUDEDIR}/${_header}" DIRECTORY)
|
|
||||||
if(EXISTS "${_extract_from}")
|
|
||||||
install(FILES "${_extract_from}"
|
|
||||||
DESTINATION "${_extract_to}"
|
|
||||||
COMPONENT protobuf-headers
|
|
||||||
RENAME "${_extract_name}")
|
|
||||||
else()
|
|
||||||
message(AUTHOR_WARNING "The file \"${_extract_from}\" is listed in "
|
|
||||||
"\"${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in\" "
|
|
||||||
"but there not exists. The file will not be installed.")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Internal function for parsing auto tools scripts
|
|
||||||
function(_protobuf_auto_list FILE_NAME VARIABLE)
|
|
||||||
file(STRINGS ${FILE_NAME} _strings)
|
|
||||||
set(_list)
|
|
||||||
foreach(_string ${_strings})
|
|
||||||
set(_found)
|
|
||||||
string(REGEX MATCH "^[ \t]*${VARIABLE}[ \t]*=[ \t]*" _found "${_string}")
|
|
||||||
if(_found)
|
|
||||||
string(LENGTH "${_found}" _length)
|
|
||||||
string(SUBSTRING "${_string}" ${_length} -1 _draft_list)
|
|
||||||
foreach(_item ${_draft_list})
|
|
||||||
string(STRIP "${_item}" _item)
|
|
||||||
list(APPEND _list "${_item}")
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
set(${VARIABLE} ${_list} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Install well-known type proto files
|
|
||||||
_protobuf_auto_list("${protobuf_SOURCE_DIR}/src/Makefile.am" nobase_dist_proto_DATA)
|
|
||||||
foreach(_file ${nobase_dist_proto_DATA})
|
|
||||||
get_filename_component(_file_from "${protobuf_SOURCE_DIR}/src/${_file}" ABSOLUTE)
|
|
||||||
get_filename_component(_file_name ${_file} NAME)
|
|
||||||
get_filename_component(_dir ${_file} DIRECTORY)
|
|
||||||
if(EXISTS "${_file_from}")
|
|
||||||
install(FILES "${_file_from}"
|
|
||||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_dir}"
|
|
||||||
COMPONENT protobuf-protos
|
|
||||||
RENAME "${_file_name}")
|
|
||||||
else()
|
|
||||||
message(AUTHOR_WARNING "The file \"${_file_from}\" is listed in "
|
|
||||||
"\"${protobuf_SOURCE_DIR}/src/Makefile.am\" as nobase_dist_proto_DATA "
|
|
||||||
"but there not exists. The file will not be installed.")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Install configuration
|
|
||||||
set(_cmakedir_desc "Directory relative to CMAKE_INSTALL to install the cmake configuration files")
|
|
||||||
set(_exampledir_desc "Directory relative to CMAKE_INSTALL_DATA to install examples")
|
|
||||||
if(NOT MSVC)
|
|
||||||
set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/protobuf" CACHE STRING "${_cmakedir_desc}")
|
|
||||||
set(CMAKE_INSTALL_EXAMPLEDIR "${CMAKE_INSTALL_DATADIR}/protobuf/examples" CACHE STRING "${_exampledir_desc}")
|
|
||||||
else()
|
|
||||||
set(CMAKE_INSTALL_CMAKEDIR "cmake" CACHE STRING "${_cmakedir_desc}")
|
|
||||||
set(CMAKE_INSTALL_EXAMPLEDIR "examples" CACHE STRING "${_exampledir_desc}")
|
|
||||||
endif()
|
|
||||||
mark_as_advanced(CMAKE_INSTALL_CMAKEDIR)
|
|
||||||
mark_as_advanced(CMAKE_INSTALL_EXAMPLEDIR)
|
|
||||||
|
|
||||||
configure_file(${protobuf_SOURCE_DIR}/cmake/protobuf-config.cmake.in
|
|
||||||
${CMAKE_INSTALL_CMAKEDIR}/protobuf-config.cmake @ONLY)
|
|
||||||
configure_file(${protobuf_SOURCE_DIR}/cmake/protobuf-config-version.cmake.in
|
|
||||||
${CMAKE_INSTALL_CMAKEDIR}/protobuf-config-version.cmake @ONLY)
|
|
||||||
configure_file(${protobuf_SOURCE_DIR}/cmake/protobuf-module.cmake.in
|
|
||||||
${CMAKE_INSTALL_CMAKEDIR}/protobuf-module.cmake @ONLY)
|
|
||||||
configure_file(${protobuf_SOURCE_DIR}/cmake/protobuf-options.cmake
|
|
||||||
${CMAKE_INSTALL_CMAKEDIR}/protobuf-options.cmake @ONLY)
|
|
||||||
|
|
||||||
# Allows the build directory to be used as a find directory.
|
|
||||||
|
|
||||||
if (protobuf_BUILD_PROTOC_BINARIES)
|
|
||||||
export(TARGETS libprotobuf-lite libprotobuf libprotoc protoc
|
|
||||||
NAMESPACE protobuf::
|
|
||||||
FILE ${CMAKE_INSTALL_CMAKEDIR}/protobuf-targets.cmake
|
|
||||||
)
|
|
||||||
else (protobuf_BUILD_PROTOC_BINARIES)
|
|
||||||
export(TARGETS libprotobuf-lite libprotobuf
|
|
||||||
NAMESPACE protobuf::
|
|
||||||
FILE ${CMAKE_INSTALL_CMAKEDIR}/protobuf-targets.cmake
|
|
||||||
)
|
|
||||||
endif (protobuf_BUILD_PROTOC_BINARIES)
|
|
||||||
|
|
||||||
install(EXPORT protobuf-targets
|
|
||||||
DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
|
|
||||||
NAMESPACE protobuf::
|
|
||||||
COMPONENT protobuf-export)
|
|
||||||
|
|
||||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}/
|
|
||||||
DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
|
|
||||||
COMPONENT protobuf-export
|
|
||||||
PATTERN protobuf-targets.cmake EXCLUDE
|
|
||||||
)
|
|
||||||
|
|
||||||
option(protobuf_INSTALL_EXAMPLES "Install the examples folder" OFF)
|
|
||||||
if(protobuf_INSTALL_EXAMPLES)
|
|
||||||
install(DIRECTORY examples/
|
|
||||||
DESTINATION "${CMAKE_INSTALL_EXAMPLEDIR}"
|
|
||||||
COMPONENT protobuf-examples)
|
|
||||||
endif()
|
|
@ -1,118 +0,0 @@
|
|||||||
set(libprotobuf_lite_files
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/any_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/arena.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/arenastring.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/arenaz_sampler.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_enum_util.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_util.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/implicit_weak_message.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/inlined_string_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/coded_stream.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/io_win32.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/strtod.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_impl.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/message_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/parse_context.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_ptr_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/bytestream.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/common.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/int128.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/status.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/statusor.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stringpiece.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stringprintf.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/structurally_valid.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/strutil.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/time.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_lite.cc
|
|
||||||
)
|
|
||||||
|
|
||||||
set(libprotobuf_lite_includes
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/any.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/arena.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/arena_impl.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/arenastring.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/arenaz_sampler.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/endian.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/explicitly_constructed.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set_inl.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_enum_util.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_decl.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_impl.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_util.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/has_bits.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/implicit_weak_message.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/inlined_string_field.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/coded_stream.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/io_win32.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/strtod.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_impl.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_impl_lite.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_entry_lite.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_field_lite.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_type_handler.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/message_lite.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/metadata_lite.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/parse_context.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/port.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_ptr_field.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/bytestream.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/callback.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/casts.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/common.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/hash.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/logging.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/macros.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/map_util.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/mutex.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/once.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/platform_macros.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/port.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/status.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stl_util.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stringpiece.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/strutil.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/template_util.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_lite.h
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(libprotobuf-lite ${protobuf_SHARED_OR_STATIC}
|
|
||||||
${libprotobuf_lite_files} ${libprotobuf_lite_includes} ${protobuf_version_rc_file})
|
|
||||||
if(protobuf_HAVE_LD_VERSION_SCRIPT)
|
|
||||||
if(${CMAKE_VERSION} VERSION_GREATER 3.13 OR ${CMAKE_VERSION} VERSION_EQUAL 3.13)
|
|
||||||
target_link_options(libprotobuf-lite PRIVATE -Wl,--version-script=${protobuf_SOURCE_DIR}/src/libprotobuf-lite.map)
|
|
||||||
elseif(protobuf_BUILD_SHARED_LIBS)
|
|
||||||
target_link_libraries(libprotobuf-lite PRIVATE -Wl,--version-script=${protobuf_SOURCE_DIR}/src/libprotobuf-lite.map)
|
|
||||||
endif()
|
|
||||||
set_target_properties(libprotobuf-lite PROPERTIES
|
|
||||||
LINK_DEPENDS ${protobuf_SOURCE_DIR}/src/libprotobuf-lite.map)
|
|
||||||
endif()
|
|
||||||
target_link_libraries(libprotobuf-lite PRIVATE ${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
if(protobuf_LINK_LIBATOMIC)
|
|
||||||
target_link_libraries(libprotobuf-lite PRIVATE atomic)
|
|
||||||
endif()
|
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
|
|
||||||
target_link_libraries(libprotobuf-lite PRIVATE log)
|
|
||||||
endif()
|
|
||||||
target_include_directories(libprotobuf-lite PUBLIC ${protobuf_SOURCE_DIR}/src)
|
|
||||||
if(protobuf_BUILD_SHARED_LIBS)
|
|
||||||
target_compile_definitions(libprotobuf-lite
|
|
||||||
PUBLIC PROTOBUF_USE_DLLS
|
|
||||||
PRIVATE LIBPROTOBUF_EXPORTS)
|
|
||||||
endif()
|
|
||||||
set_target_properties(libprotobuf-lite PROPERTIES
|
|
||||||
VERSION ${protobuf_VERSION}
|
|
||||||
SOVERSION 32
|
|
||||||
OUTPUT_NAME ${LIB_PREFIX}protobuf-lite
|
|
||||||
DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}")
|
|
||||||
add_library(protobuf::libprotobuf-lite ALIAS libprotobuf-lite)
|
|
@ -1,134 +0,0 @@
|
|||||||
set(libprotobuf_files
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/any.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/any.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/api.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/importer.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/parser.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_database.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/duration.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/dynamic_message.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/empty.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set_heavy.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/field_mask.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_bases.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_reflection.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_full.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/gzip_stream.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/printer.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/tokenizer.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/message.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_ops.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/service.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/source_context.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/struct.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/substitute.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/text_format.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/timestamp.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/type.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unknown_field_set.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/delimited_message_util.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_comparator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_mask_util.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/datapiece.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/default_value_objectwriter.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/error_listener.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/field_mask_utility.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_escaping.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_objectwriter.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_stream_parser.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/object_writer.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/proto_writer.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/protostream_objectsource.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/protostream_objectwriter.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/type_info.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/utility.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_util.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/time_util.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver_util.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.pb.cc
|
|
||||||
)
|
|
||||||
|
|
||||||
set(libprotobuf_includes
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/any.pb.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/api.pb.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/importer.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/parser.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.pb.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_database.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/duration.pb.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/dynamic_message.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/empty.pb.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/field_access_listener.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/field_mask.pb.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_enum_reflection.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_bases.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_reflection.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/gzip_stream.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/printer.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/tokenizer.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_entry.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_field.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_field_inl.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/message.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/metadata.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/reflection.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_internal.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_ops.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/service.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/source_context.pb.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/struct.pb.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/text_format.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/timestamp.pb.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/type.pb.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unknown_field_set.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/delimited_message_util.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_comparator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_mask_util.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_util.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/time_util.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver_util.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.pb.h
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(libprotobuf ${protobuf_SHARED_OR_STATIC}
|
|
||||||
${libprotobuf_lite_files} ${libprotobuf_files} ${libprotobuf_includes} ${protobuf_version_rc_file})
|
|
||||||
if(protobuf_HAVE_LD_VERSION_SCRIPT)
|
|
||||||
if(${CMAKE_VERSION} VERSION_GREATER 3.13 OR ${CMAKE_VERSION} VERSION_EQUAL 3.13)
|
|
||||||
target_link_options(libprotobuf PRIVATE -Wl,--version-script=${protobuf_SOURCE_DIR}/src/libprotobuf.map)
|
|
||||||
elseif(protobuf_BUILD_SHARED_LIBS)
|
|
||||||
target_link_libraries(libprotobuf PRIVATE -Wl,--version-script=${protobuf_SOURCE_DIR}/src/libprotobuf.map)
|
|
||||||
endif()
|
|
||||||
set_target_properties(libprotobuf PROPERTIES
|
|
||||||
LINK_DEPENDS ${protobuf_SOURCE_DIR}/src/libprotobuf.map)
|
|
||||||
endif()
|
|
||||||
target_link_libraries(libprotobuf PRIVATE ${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
if(protobuf_WITH_ZLIB)
|
|
||||||
target_link_libraries(libprotobuf PRIVATE ${ZLIB_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
if(protobuf_LINK_LIBATOMIC)
|
|
||||||
target_link_libraries(libprotobuf PRIVATE atomic)
|
|
||||||
endif()
|
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
|
|
||||||
target_link_libraries(libprotobuf PRIVATE log)
|
|
||||||
endif()
|
|
||||||
target_include_directories(libprotobuf PUBLIC ${protobuf_SOURCE_DIR}/src)
|
|
||||||
if(protobuf_BUILD_SHARED_LIBS)
|
|
||||||
target_compile_definitions(libprotobuf
|
|
||||||
PUBLIC PROTOBUF_USE_DLLS
|
|
||||||
PRIVATE LIBPROTOBUF_EXPORTS)
|
|
||||||
endif()
|
|
||||||
set_target_properties(libprotobuf PROPERTIES
|
|
||||||
VERSION ${protobuf_VERSION}
|
|
||||||
SOVERSION 32
|
|
||||||
OUTPUT_NAME ${LIB_PREFIX}protobuf
|
|
||||||
DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}")
|
|
||||||
add_library(protobuf::libprotobuf ALIAS libprotobuf)
|
|
@ -1,136 +0,0 @@
|
|||||||
set(libprotoc_files
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/command_line_interface.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/enum.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/enum_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/extension.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/file.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/helpers.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/map_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/padding_optimizer.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/parse_function_generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/primitive_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/service.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/string_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_enum.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_field_base.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_helpers.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_map_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_message.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_message_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/context.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/doc_comment.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum_field_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/extension.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/extension_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/file.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator_factory.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/helpers.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/kotlin_generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/map_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/map_field_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_builder.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_builder_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_field_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/name_resolver.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/primitive_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/primitive_field_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/service.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/shared_code_generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/string_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/string_field_lite.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_file.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_message.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/php/php_generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.pb.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/helpers.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/pyi_generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/ruby/ruby_generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/subprocess.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/zip_writer.cc
|
|
||||||
)
|
|
||||||
|
|
||||||
set(libprotoc_headers
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/command_line_interface.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/cpp_generator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/file.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/generator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/helpers.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/names.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_doc_comment.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_generator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_names.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_options.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/java_generator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/kotlin_generator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/names.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_generator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/php/php_generator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/generator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/pyi_generator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/python_generator.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/ruby/ruby_generator.h
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(libprotoc ${protobuf_SHARED_OR_STATIC}
|
|
||||||
${libprotoc_files} ${libprotoc_headers} ${protobuf_version_rc_file})
|
|
||||||
if(protobuf_HAVE_LD_VERSION_SCRIPT)
|
|
||||||
if(${CMAKE_VERSION} VERSION_GREATER 3.13 OR ${CMAKE_VERSION} VERSION_EQUAL 3.13)
|
|
||||||
target_link_options(libprotoc PRIVATE -Wl,--version-script=${protobuf_SOURCE_DIR}/src/libprotoc.map)
|
|
||||||
elseif(protobuf_BUILD_SHARED_LIBS)
|
|
||||||
target_link_libraries(libprotoc PRIVATE -Wl,--version-script=${protobuf_SOURCE_DIR}/src/libprotoc.map)
|
|
||||||
endif()
|
|
||||||
set_target_properties(libprotoc PROPERTIES
|
|
||||||
LINK_DEPENDS ${protobuf_SOURCE_DIR}/src/libprotoc.map)
|
|
||||||
endif()
|
|
||||||
target_link_libraries(libprotoc PRIVATE libprotobuf)
|
|
||||||
if(protobuf_BUILD_SHARED_LIBS)
|
|
||||||
target_compile_definitions(libprotoc
|
|
||||||
PUBLIC PROTOBUF_USE_DLLS
|
|
||||||
PRIVATE LIBPROTOC_EXPORTS)
|
|
||||||
endif()
|
|
||||||
set_target_properties(libprotoc PROPERTIES
|
|
||||||
COMPILE_DEFINITIONS LIBPROTOC_EXPORTS
|
|
||||||
VERSION ${protobuf_VERSION}
|
|
||||||
SOVERSION 32
|
|
||||||
OUTPUT_NAME ${LIB_PREFIX}protoc
|
|
||||||
DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}")
|
|
||||||
add_library(protobuf::libprotoc ALIAS libprotoc)
|
|
@ -1,60 +0,0 @@
|
|||||||
set(PACKAGE_VERSION "@protobuf_VERSION@")
|
|
||||||
set(${PACKAGE_FIND_NAME}_VERSION_PRERELEASE "@protobuf_VERSION_PRERELEASE@" PARENT_SCOPE)
|
|
||||||
|
|
||||||
# Prerelease versions cannot be passed in directly via the find_package command,
|
|
||||||
# so we allow users to specify it in a variable
|
|
||||||
if(NOT DEFINED "${PACKAGE_FIND_NAME}_FIND_VERSION_PRERELEASE")
|
|
||||||
set("${${PACKAGE_FIND_NAME}_FIND_VERSION_PRERELEASE}" "")
|
|
||||||
else()
|
|
||||||
set(PACKAGE_FIND_VERSION ${PACKAGE_FIND_VERSION}-${${PACKAGE_FIND_NAME}_FIND_VERSION_PRERELEASE})
|
|
||||||
endif()
|
|
||||||
set(PACKAGE_FIND_VERSION_PRERELEASE "${${PACKAGE_FIND_NAME}_FIND_VERSION_PRERELEASE}")
|
|
||||||
|
|
||||||
# VERSION_EQUAL ignores the prerelease strings, so we use STREQUAL.
|
|
||||||
if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
|
|
||||||
set(PACKAGE_VERSION_EXACT TRUE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(PACKAGE_VERSION_COMPATIBLE TRUE) #Assume true until shown otherwise
|
|
||||||
|
|
||||||
if(PACKAGE_FIND_VERSION) #Only perform version checks if one is given
|
|
||||||
if(NOT PACKAGE_FIND_VERSION_MAJOR EQUAL "@protobuf_VERSION_MAJOR@")
|
|
||||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
|
||||||
elseif(PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION)
|
|
||||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
|
||||||
elseif(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
|
|
||||||
# Do not match prerelease versions to non-prerelease version requests.
|
|
||||||
if(NOT "@protobuf_VERSION_PRERELEASE@" STREQUAL "" AND PACKAGE_FIND_VERSION_PRERELEASE STREQUAL "")
|
|
||||||
message(AUTHOR_WARNING "To use this prerelease version of ${PACKAGE_FIND_NAME}, set ${PACKAGE_FIND_NAME}_FIND_VERSION_PRERELEASE to '@protobuf_VERSION_PRERELEASE@' or greater.")
|
|
||||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Not robustly SemVer compliant, but protobuf never uses '.' separated prerelease identifiers.
|
|
||||||
if(PACKAGE_FIND_VERSION_PRERELEASE STRGREATER "@protobuf_VERSION_PRERELEASE@")
|
|
||||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Check and save build options used to create this package
|
|
||||||
macro(_check_and_save_build_option OPTION VALUE)
|
|
||||||
if(DEFINED ${PACKAGE_FIND_NAME}_${OPTION} AND
|
|
||||||
NOT ${PACKAGE_FIND_NAME}_${OPTION} STREQUAL ${VALUE})
|
|
||||||
set(PACKAGE_VERSION_UNSUITABLE TRUE)
|
|
||||||
endif()
|
|
||||||
set(${PACKAGE_FIND_NAME}_${OPTION} ${VALUE} PARENT_SCOPE)
|
|
||||||
endmacro()
|
|
||||||
_check_and_save_build_option(WITH_ZLIB @protobuf_WITH_ZLIB@)
|
|
||||||
_check_and_save_build_option(MSVC_STATIC_RUNTIME @protobuf_MSVC_STATIC_RUNTIME@)
|
|
||||||
_check_and_save_build_option(BUILD_SHARED_LIBS @protobuf_BUILD_SHARED_LIBS@)
|
|
||||||
|
|
||||||
# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
|
|
||||||
if(CMAKE_SIZEOF_VOID_P AND "@CMAKE_SIZEOF_VOID_P@")
|
|
||||||
# check that the installed version has the same 32/64bit-ness as the one which is currently searching:
|
|
||||||
if(NOT CMAKE_SIZEOF_VOID_P EQUAL "@CMAKE_SIZEOF_VOID_P@")
|
|
||||||
math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8")
|
|
||||||
set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
|
|
||||||
set(PACKAGE_VERSION_UNSUITABLE TRUE)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
@ -1,169 +0,0 @@
|
|||||||
# User options
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/protobuf-options.cmake")
|
|
||||||
|
|
||||||
# Depend packages
|
|
||||||
@_protobuf_FIND_ZLIB@
|
|
||||||
|
|
||||||
# Imported targets
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/protobuf-targets.cmake")
|
|
||||||
|
|
||||||
function(protobuf_generate)
|
|
||||||
include(CMakeParseArguments)
|
|
||||||
|
|
||||||
set(_options APPEND_PATH)
|
|
||||||
set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN PLUGIN_OPTIONS)
|
|
||||||
if(COMMAND target_sources)
|
|
||||||
list(APPEND _singleargs TARGET)
|
|
||||||
endif()
|
|
||||||
set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS PROTOC_OPTIONS)
|
|
||||||
|
|
||||||
cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
|
|
||||||
|
|
||||||
if(NOT protobuf_generate_PROTOS AND NOT protobuf_generate_TARGET)
|
|
||||||
message(SEND_ERROR "Error: protobuf_generate called without any targets or source files")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT protobuf_generate_OUT_VAR AND NOT protobuf_generate_TARGET)
|
|
||||||
message(SEND_ERROR "Error: protobuf_generate called without a target or output variable")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT protobuf_generate_LANGUAGE)
|
|
||||||
set(protobuf_generate_LANGUAGE cpp)
|
|
||||||
endif()
|
|
||||||
string(TOLOWER ${protobuf_generate_LANGUAGE} protobuf_generate_LANGUAGE)
|
|
||||||
|
|
||||||
if(NOT protobuf_generate_PROTOC_OUT_DIR)
|
|
||||||
set(protobuf_generate_PROTOC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(protobuf_generate_EXPORT_MACRO AND protobuf_generate_LANGUAGE STREQUAL cpp)
|
|
||||||
set(_dll_export_decl "dllexport_decl=${protobuf_generate_EXPORT_MACRO}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
foreach(_option ${_dll_export_decl} ${protobuf_generate_PLUGIN_OPTIONS})
|
|
||||||
# append comma - not using CMake lists and string replacement as users
|
|
||||||
# might have semicolons in options
|
|
||||||
if(_plugin_options)
|
|
||||||
set( _plugin_options "${_plugin_options},")
|
|
||||||
endif()
|
|
||||||
set(_plugin_options "${_plugin_options}${_option}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(protobuf_generate_PLUGIN)
|
|
||||||
set(_plugin "--plugin=${protobuf_generate_PLUGIN}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT protobuf_generate_GENERATE_EXTENSIONS)
|
|
||||||
if(protobuf_generate_LANGUAGE STREQUAL cpp)
|
|
||||||
set(protobuf_generate_GENERATE_EXTENSIONS .pb.h .pb.cc)
|
|
||||||
elseif(protobuf_generate_LANGUAGE STREQUAL python)
|
|
||||||
set(protobuf_generate_GENERATE_EXTENSIONS _pb2.py)
|
|
||||||
else()
|
|
||||||
message(SEND_ERROR "Error: protobuf_generate given unknown Language ${LANGUAGE}, please provide a value for GENERATE_EXTENSIONS")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(protobuf_generate_TARGET)
|
|
||||||
get_target_property(_source_list ${protobuf_generate_TARGET} SOURCES)
|
|
||||||
foreach(_file ${_source_list})
|
|
||||||
if(_file MATCHES "proto$")
|
|
||||||
list(APPEND protobuf_generate_PROTOS ${_file})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT protobuf_generate_PROTOS)
|
|
||||||
message(SEND_ERROR "Error: protobuf_generate could not find any .proto files")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(protobuf_generate_APPEND_PATH)
|
|
||||||
# Create an include path for each file specified
|
|
||||||
foreach(_file ${protobuf_generate_PROTOS})
|
|
||||||
get_filename_component(_abs_file ${_file} ABSOLUTE)
|
|
||||||
get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
|
|
||||||
list(FIND _protobuf_include_path ${_abs_dir} _contains_already)
|
|
||||||
if(${_contains_already} EQUAL -1)
|
|
||||||
list(APPEND _protobuf_include_path -I ${_abs_dir})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
foreach(DIR ${protobuf_generate_IMPORT_DIRS})
|
|
||||||
get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
|
|
||||||
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
|
|
||||||
if(${_contains_already} EQUAL -1)
|
|
||||||
list(APPEND _protobuf_include_path -I ${ABS_PATH})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(NOT _protobuf_include_path)
|
|
||||||
set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(_generated_srcs_all)
|
|
||||||
foreach(_proto ${protobuf_generate_PROTOS})
|
|
||||||
get_filename_component(_abs_file ${_proto} ABSOLUTE)
|
|
||||||
get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
|
|
||||||
|
|
||||||
get_filename_component(_file_full_name ${_proto} NAME)
|
|
||||||
string(FIND "${_file_full_name}" "." _file_last_ext_pos REVERSE)
|
|
||||||
string(SUBSTRING "${_file_full_name}" 0 ${_file_last_ext_pos} _basename)
|
|
||||||
|
|
||||||
set(_suitable_include_found FALSE)
|
|
||||||
foreach(DIR ${_protobuf_include_path})
|
|
||||||
if(NOT DIR STREQUAL "-I")
|
|
||||||
file(RELATIVE_PATH _rel_dir ${DIR} ${_abs_dir})
|
|
||||||
string(FIND "${_rel_dir}" "../" _is_in_parent_folder)
|
|
||||||
if (NOT ${_is_in_parent_folder} EQUAL 0)
|
|
||||||
set(_suitable_include_found TRUE)
|
|
||||||
break()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(NOT _suitable_include_found)
|
|
||||||
message(SEND_ERROR "Error: protobuf_generate could not find any correct proto include directory.")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(_generated_srcs)
|
|
||||||
foreach(_ext ${protobuf_generate_GENERATE_EXTENSIONS})
|
|
||||||
list(APPEND _generated_srcs "${protobuf_generate_PROTOC_OUT_DIR}/${_rel_dir}/${_basename}${_ext}")
|
|
||||||
endforeach()
|
|
||||||
list(APPEND _generated_srcs_all ${_generated_srcs})
|
|
||||||
|
|
||||||
set(_comment "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}")
|
|
||||||
if(protobuf_generate_PROTOC_OPTIONS)
|
|
||||||
set(_comment "${_comment}, protoc-options: ${protobuf_generate_PROTOC_OPTIONS}")
|
|
||||||
endif()
|
|
||||||
if(_plugin_options)
|
|
||||||
set(_comment "${_comment}, plugin-options: ${_plugin_options}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${_generated_srcs}
|
|
||||||
COMMAND protobuf::protoc
|
|
||||||
ARGS ${protobuf_generate_PROTOC_OPTIONS} --${protobuf_generate_LANGUAGE}_out ${_plugin_options}:${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file}
|
|
||||||
DEPENDS ${_abs_file} protobuf::protoc
|
|
||||||
COMMENT ${_comment}
|
|
||||||
VERBATIM )
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
set_source_files_properties(${_generated_srcs_all} PROPERTIES GENERATED TRUE)
|
|
||||||
if(protobuf_generate_OUT_VAR)
|
|
||||||
set(${protobuf_generate_OUT_VAR} ${_generated_srcs_all} PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
if(protobuf_generate_TARGET)
|
|
||||||
target_sources(${protobuf_generate_TARGET} PRIVATE ${_generated_srcs_all})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# CMake FindProtobuf module compatible file
|
|
||||||
if(protobuf_MODULE_COMPATIBLE)
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/protobuf-module.cmake")
|
|
||||||
endif()
|
|
@ -1,11 +0,0 @@
|
|||||||
prefix=@CMAKE_INSTALL_PREFIX@
|
|
||||||
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
|
||||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
|
||||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
|
||||||
|
|
||||||
Name: Protocol Buffers
|
|
||||||
Description: Google's Data Interchange Format
|
|
||||||
Version: @protobuf_VERSION@
|
|
||||||
Libs: -L${libdir} -lprotobuf-lite @CMAKE_THREAD_LIBS_INIT@
|
|
||||||
Cflags: -I${includedir}
|
|
||||||
Conflicts: protobuf
|
|
@ -1,189 +0,0 @@
|
|||||||
# This file contains backwards compatibility patches for various legacy functions and variables
|
|
||||||
# Functions
|
|
||||||
|
|
||||||
function(PROTOBUF_GENERATE_CPP SRCS HDRS)
|
|
||||||
cmake_parse_arguments(protobuf_generate_cpp "" "EXPORT_MACRO" "" ${ARGN})
|
|
||||||
|
|
||||||
set(_proto_files "${protobuf_generate_cpp_UNPARSED_ARGUMENTS}")
|
|
||||||
if(NOT _proto_files)
|
|
||||||
message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
|
|
||||||
set(_append_arg APPEND_PATH)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(DEFINED Protobuf_IMPORT_DIRS)
|
|
||||||
set(_import_arg IMPORT_DIRS ${Protobuf_IMPORT_DIRS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(_outvar)
|
|
||||||
protobuf_generate(${_append_arg} LANGUAGE cpp EXPORT_MACRO ${protobuf_generate_cpp_EXPORT_MACRO} OUT_VAR _outvar ${_import_arg} PROTOS ${_proto_files})
|
|
||||||
|
|
||||||
set(${SRCS})
|
|
||||||
set(${HDRS})
|
|
||||||
foreach(_file ${_outvar})
|
|
||||||
if(_file MATCHES "cc$")
|
|
||||||
list(APPEND ${SRCS} ${_file})
|
|
||||||
else()
|
|
||||||
list(APPEND ${HDRS} ${_file})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
set(${SRCS} ${${SRCS}} PARENT_SCOPE)
|
|
||||||
set(${HDRS} ${${HDRS}} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
function(PROTOBUF_GENERATE_PYTHON SRCS)
|
|
||||||
if(NOT ARGN)
|
|
||||||
message(SEND_ERROR "Error: PROTOBUF_GENERATE_PYTHON() called without any proto files")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
|
|
||||||
set(_append_arg APPEND_PATH)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(DEFINED Protobuf_IMPORT_DIRS)
|
|
||||||
set(_import_arg IMPORT_DIRS ${Protobuf_IMPORT_DIRS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(_outvar)
|
|
||||||
protobuf_generate(${_append_arg} LANGUAGE python OUT_VAR _outvar ${_import_arg} PROTOS ${ARGN})
|
|
||||||
set(${SRCS} ${_outvar} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Environment
|
|
||||||
|
|
||||||
# Backwards compatibility
|
|
||||||
# Define camel case versions of input variables
|
|
||||||
foreach(UPPER
|
|
||||||
PROTOBUF_SRC_ROOT_FOLDER
|
|
||||||
PROTOBUF_IMPORT_DIRS
|
|
||||||
PROTOBUF_DEBUG
|
|
||||||
PROTOBUF_LIBRARY
|
|
||||||
PROTOBUF_PROTOC_LIBRARY
|
|
||||||
PROTOBUF_INCLUDE_DIR
|
|
||||||
PROTOBUF_PROTOC_EXECUTABLE
|
|
||||||
PROTOBUF_LIBRARY_DEBUG
|
|
||||||
PROTOBUF_PROTOC_LIBRARY_DEBUG
|
|
||||||
PROTOBUF_LITE_LIBRARY
|
|
||||||
PROTOBUF_LITE_LIBRARY_DEBUG
|
|
||||||
)
|
|
||||||
if (DEFINED ${UPPER})
|
|
||||||
string(REPLACE "PROTOBUF_" "Protobuf_" Camel ${UPPER})
|
|
||||||
if (NOT DEFINED ${Camel})
|
|
||||||
set(${Camel} ${${UPPER}})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(DEFINED Protobuf_SRC_ROOT_FOLDER)
|
|
||||||
message(AUTHOR_WARNING "Variable Protobuf_SRC_ROOT_FOLDER defined, but not"
|
|
||||||
" used in CONFIG mode")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(SelectLibraryConfigurations)
|
|
||||||
|
|
||||||
# Internal function: search for normal library as well as a debug one
|
|
||||||
# if the debug one is specified also include debug/optimized keywords
|
|
||||||
# in *_LIBRARIES variable
|
|
||||||
function(_protobuf_find_libraries name filename)
|
|
||||||
if(${name}_LIBRARIES)
|
|
||||||
# Use result recorded by a previous call.
|
|
||||||
elseif(${name}_LIBRARY)
|
|
||||||
# Honor cache entry used by CMake 3.5 and lower.
|
|
||||||
set(${name}_LIBRARIES "${${name}_LIBRARY}" PARENT_SCOPE)
|
|
||||||
elseif(TARGET protobuf::lib${filename})
|
|
||||||
get_target_property(${name}_LIBRARY_RELEASE protobuf::lib${filename}
|
|
||||||
LOCATION_RELEASE)
|
|
||||||
get_target_property(${name}_LIBRARY_RELWITHDEBINFO protobuf::lib${filename}
|
|
||||||
LOCATION_RELWITHDEBINFO)
|
|
||||||
get_target_property(${name}_LIBRARY_MINSIZEREL protobuf::lib${filename}
|
|
||||||
LOCATION_MINSIZEREL)
|
|
||||||
get_target_property(${name}_LIBRARY_DEBUG protobuf::lib${filename}
|
|
||||||
LOCATION_DEBUG)
|
|
||||||
|
|
||||||
select_library_configurations(${name})
|
|
||||||
set(${name}_LIBRARY ${${name}_LIBRARY} PARENT_SCOPE)
|
|
||||||
set(${name}_LIBRARIES ${${name}_LIBRARIES} PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
#
|
|
||||||
# Main.
|
|
||||||
#
|
|
||||||
|
|
||||||
# By default have PROTOBUF_GENERATE_CPP macro pass -I to protoc
|
|
||||||
# for each directory where a proto file is referenced.
|
|
||||||
if(NOT DEFINED PROTOBUF_GENERATE_CPP_APPEND_PATH)
|
|
||||||
set(PROTOBUF_GENERATE_CPP_APPEND_PATH TRUE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# The Protobuf library
|
|
||||||
_protobuf_find_libraries(Protobuf protobuf)
|
|
||||||
|
|
||||||
# The Protobuf Lite library
|
|
||||||
_protobuf_find_libraries(Protobuf_LITE protobuf-lite)
|
|
||||||
|
|
||||||
# The Protobuf Protoc Library
|
|
||||||
_protobuf_find_libraries(Protobuf_PROTOC protoc)
|
|
||||||
|
|
||||||
# Set the include directory
|
|
||||||
get_target_property(Protobuf_INCLUDE_DIRS protobuf::libprotobuf
|
|
||||||
INTERFACE_INCLUDE_DIRECTORIES)
|
|
||||||
|
|
||||||
# Set the protoc Executable
|
|
||||||
if(NOT Protobuf_PROTOC_EXECUTABLE AND TARGET protobuf::protoc)
|
|
||||||
get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
|
|
||||||
IMPORTED_LOCATION_RELEASE)
|
|
||||||
if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
|
|
||||||
get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
|
|
||||||
IMPORTED_LOCATION_RELWITHDEBINFO)
|
|
||||||
endif()
|
|
||||||
if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
|
|
||||||
get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
|
|
||||||
IMPORTED_LOCATION_MINSIZEREL)
|
|
||||||
endif()
|
|
||||||
if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
|
|
||||||
get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
|
|
||||||
IMPORTED_LOCATION_DEBUG)
|
|
||||||
endif()
|
|
||||||
if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
|
|
||||||
get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
|
|
||||||
IMPORTED_LOCATION_NOCONFIG)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Version info variable
|
|
||||||
set(Protobuf_VERSION "@protobuf_VERSION@")
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Protobuf
|
|
||||||
REQUIRED_VARS Protobuf_PROTOC_EXECUTABLE Protobuf_LIBRARIES Protobuf_INCLUDE_DIRS
|
|
||||||
VERSION_VAR Protobuf_VERSION
|
|
||||||
)
|
|
||||||
|
|
||||||
# Backwards compatibility
|
|
||||||
# Define upper case versions of output variables
|
|
||||||
foreach(Camel
|
|
||||||
Protobuf_VERSION
|
|
||||||
Protobuf_SRC_ROOT_FOLDER
|
|
||||||
Protobuf_IMPORT_DIRS
|
|
||||||
Protobuf_DEBUG
|
|
||||||
Protobuf_INCLUDE_DIRS
|
|
||||||
Protobuf_LIBRARIES
|
|
||||||
Protobuf_PROTOC_LIBRARIES
|
|
||||||
Protobuf_LITE_LIBRARIES
|
|
||||||
Protobuf_LIBRARY
|
|
||||||
Protobuf_PROTOC_LIBRARY
|
|
||||||
Protobuf_INCLUDE_DIR
|
|
||||||
Protobuf_PROTOC_EXECUTABLE
|
|
||||||
Protobuf_LIBRARY_DEBUG
|
|
||||||
Protobuf_PROTOC_LIBRARY_DEBUG
|
|
||||||
Protobuf_LITE_LIBRARY
|
|
||||||
Protobuf_LITE_LIBRARY_DEBUG
|
|
||||||
)
|
|
||||||
string(TOUPPER ${Camel} UPPER)
|
|
||||||
set(${UPPER} ${${Camel}})
|
|
||||||
endforeach()
|
|
@ -1,7 +0,0 @@
|
|||||||
# Verbose output
|
|
||||||
option(protobuf_VERBOSE "Enable for verbose output" OFF)
|
|
||||||
mark_as_advanced(protobuf_VERBOSE)
|
|
||||||
|
|
||||||
# FindProtobuf module compatible
|
|
||||||
option(protobuf_MODULE_COMPATIBLE "CMake built-in FindProtobuf.cmake module compatible" OFF)
|
|
||||||
mark_as_advanced(protobuf_MODULE_COMPATIBLE)
|
|
@ -1,11 +0,0 @@
|
|||||||
prefix=@CMAKE_INSTALL_PREFIX@
|
|
||||||
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
|
||||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
|
||||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
|
||||||
|
|
||||||
Name: Protocol Buffers
|
|
||||||
Description: Google's Data Interchange Format
|
|
||||||
Version: @protobuf_VERSION@
|
|
||||||
Libs: -L${libdir} -lprotobuf @CMAKE_THREAD_LIBS_INIT@
|
|
||||||
Cflags: -I${includedir}
|
|
||||||
Conflicts: protobuf-lite
|
|
@ -1,13 +0,0 @@
|
|||||||
set(protoc_files
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/main.cc
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(protoc ${protoc_files} ${protobuf_version_rc_file})
|
|
||||||
target_link_libraries(protoc
|
|
||||||
libprotoc
|
|
||||||
libprotobuf
|
|
||||||
)
|
|
||||||
add_executable(protobuf::protoc ALIAS protoc)
|
|
||||||
|
|
||||||
set_target_properties(protoc PROPERTIES
|
|
||||||
VERSION ${protobuf_VERSION})
|
|
@ -1,294 +0,0 @@
|
|||||||
option(protobuf_USE_EXTERNAL_GTEST "Use external Google Test (i.e. not the one in third_party/googletest)" OFF)
|
|
||||||
|
|
||||||
option(protobuf_TEST_XML_OUTDIR "Output directory for XML logs from tests." "")
|
|
||||||
|
|
||||||
option(protobuf_ABSOLUTE_TEST_PLUGIN_PATH
|
|
||||||
"Using absolute test_plugin path in tests" ON)
|
|
||||||
mark_as_advanced(protobuf_ABSOLUTE_TEST_PLUGIN_PATH)
|
|
||||||
|
|
||||||
if (protobuf_USE_EXTERNAL_GTEST)
|
|
||||||
find_package(GTest REQUIRED)
|
|
||||||
else()
|
|
||||||
if (NOT EXISTS "${protobuf_SOURCE_DIR}/third_party/googletest/CMakeLists.txt")
|
|
||||||
message(FATAL_ERROR
|
|
||||||
"Cannot find third_party/googletest directory that's needed to "
|
|
||||||
"build tests. If you use git, make sure you have cloned submodules:\n"
|
|
||||||
" git submodule update --init --recursive\n"
|
|
||||||
"If instead you want to skip tests, run cmake with:\n"
|
|
||||||
" cmake -Dprotobuf_BUILD_TESTS=OFF\n")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(googlemock_source_dir "${protobuf_SOURCE_DIR}/third_party/googletest/googlemock")
|
|
||||||
set(googletest_source_dir "${protobuf_SOURCE_DIR}/third_party/googletest/googletest")
|
|
||||||
include_directories(
|
|
||||||
${googlemock_source_dir}
|
|
||||||
${googletest_source_dir}
|
|
||||||
${googletest_source_dir}/include
|
|
||||||
${googlemock_source_dir}/include
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(gmock STATIC
|
|
||||||
"${googlemock_source_dir}/src/gmock-all.cc"
|
|
||||||
"${googletest_source_dir}/src/gtest-all.cc"
|
|
||||||
)
|
|
||||||
target_link_libraries(gmock ${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
add_library(gmock_main STATIC "${googlemock_source_dir}/src/gmock_main.cc")
|
|
||||||
target_link_libraries(gmock_main gmock)
|
|
||||||
|
|
||||||
add_library(GTest::gmock ALIAS gmock)
|
|
||||||
add_library(GTest::gmock_main ALIAS gmock_main)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(lite_test_protos
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_lite_unittest.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_lite.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_public_lite.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lite.proto
|
|
||||||
)
|
|
||||||
|
|
||||||
set(tests_protos
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/any_test.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/test_bad_identifiers.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/test_large_enum_value.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_proto2_unittest.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_unittest.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_arena.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_custom_options.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_drop_unknown_fields.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_embed_optimize_for.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_empty.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_enormous_descriptor.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_public.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies_custom_option.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies_enum.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lite_imports_nonlite.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_mset.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_mset_wire_format.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_no_field_presence.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_no_generic_services.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_optimize_for.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_preserve_unknown_enum.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_preserve_unknown_enum2.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_arena.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_arena_lite.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_lite.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_optional.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_well_known_types.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/anys.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/books.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/default_value.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/default_value_test.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/field_mask.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/maps.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/oneofs.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/proto3.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/struct.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/timestamp_duration.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/wrappers.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_format.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_format_proto3.proto
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer_unittest.proto
|
|
||||||
)
|
|
||||||
|
|
||||||
macro(compile_proto_file filename)
|
|
||||||
string(REPLACE .proto .pb.cc pb_file ${filename})
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${pb_file}
|
|
||||||
DEPENDS ${protobuf_PROTOC_EXE} ${filename}
|
|
||||||
COMMAND ${protobuf_PROTOC_EXE} ${filename}
|
|
||||||
--proto_path=${protobuf_SOURCE_DIR}/src
|
|
||||||
--cpp_out=${protobuf_SOURCE_DIR}/src
|
|
||||||
--experimental_allow_proto3_optional
|
|
||||||
)
|
|
||||||
endmacro(compile_proto_file)
|
|
||||||
|
|
||||||
set(lite_test_proto_files)
|
|
||||||
foreach(proto_file ${lite_test_protos})
|
|
||||||
compile_proto_file(${proto_file})
|
|
||||||
set(lite_test_proto_files ${lite_test_proto_files} ${pb_file})
|
|
||||||
endforeach(proto_file)
|
|
||||||
|
|
||||||
set(tests_proto_files)
|
|
||||||
foreach(proto_file ${tests_protos})
|
|
||||||
compile_proto_file(${proto_file})
|
|
||||||
set(tests_proto_files ${tests_proto_files} ${pb_file})
|
|
||||||
endforeach(proto_file)
|
|
||||||
|
|
||||||
set(common_lite_test_files
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/arena_test_util.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_lite_test_util.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/test_util_lite.cc
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(protobuf-lite-test-common STATIC
|
|
||||||
${common_lite_test_files} ${lite_test_proto_files})
|
|
||||||
target_link_libraries(protobuf-lite-test-common libprotobuf-lite GTest::gmock)
|
|
||||||
|
|
||||||
set(common_test_files
|
|
||||||
${common_lite_test_files}
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/mock_code_generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_test_util.inc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_tester.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/test_util.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/testing/file.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/testing/googletest.cc
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(protobuf-test-common STATIC
|
|
||||||
${common_test_files} ${tests_proto_files})
|
|
||||||
target_link_libraries(protobuf-test-common libprotobuf GTest::gmock)
|
|
||||||
|
|
||||||
set(tests_files
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/any_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/arena_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/arenastring_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/arenaz_sampler_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/annotation_test_util.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/annotation_test_util.h
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/command_line_interface_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/bootstrap_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message_size_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/metadata_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/move_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/plugin_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/unittest.inc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/importer_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/doc_comment_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/plugin_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/parser_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/plugin_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_database_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/drop_unknown_fields_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/dynamic_message_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_reflection_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_lite_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/inlined_string_field_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/coded_stream_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/io_win32_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/printer_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/tokenizer_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_field_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/map_test.inc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/message_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/message_unittest.inc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/no_field_presence_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/preserve_unknown_enum_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/proto3_arena_lite_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/proto3_arena_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/proto3_lite_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/proto3_lite_unittest.inc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_ops_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field_reflection_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/bytestream_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/common_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/int128_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/status_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/statusor_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stringpiece_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stringprintf_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/structurally_valid_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/strutil_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/template_util_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/time_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/text_format_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/unknown_field_set_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/delimited_message_util_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_comparator_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_mask_util_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_objectwriter_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_stream_parser_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/protostream_objectsource_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/type_info_test_helper.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_util_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/time_util_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver_util_test.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/well_known_types_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_unittest.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_unittest.inc
|
|
||||||
)
|
|
||||||
|
|
||||||
if(protobuf_ABSOLUTE_TEST_PLUGIN_PATH)
|
|
||||||
add_compile_options(-DGOOGLE_PROTOBUF_TEST_PLUGIN_PATH="$<TARGET_FILE:test_plugin>")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(MINGW)
|
|
||||||
set_source_files_properties(${tests_files} PROPERTIES COMPILE_FLAGS "-Wno-narrowing")
|
|
||||||
|
|
||||||
# required for tests on MinGW Win64
|
|
||||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack,16777216")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(protobuf_TEST_XML_OUTDIR)
|
|
||||||
if(NOT "${protobuf_TEST_XML_OUTDIR}" MATCHES "[/\\]$")
|
|
||||||
string(APPEND protobuf_TEST_XML_OUTDIR "/")
|
|
||||||
endif()
|
|
||||||
set(protobuf_GTEST_ARGS "--gtest_output=xml:${protobuf_TEST_XML_OUTDIR}")
|
|
||||||
else()
|
|
||||||
set(protobuf_GTEST_ARGS)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_executable(tests ${tests_files})
|
|
||||||
if (MSVC)
|
|
||||||
target_compile_options(tests PRIVATE
|
|
||||||
/wd4146 # unary minus operator applied to unsigned type, result still unsigned
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
target_link_libraries(tests protobuf-lite-test-common protobuf-test-common libprotoc libprotobuf GTest::gmock_main)
|
|
||||||
|
|
||||||
set(test_plugin_files
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/mock_code_generator.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/test_plugin.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/testing/file.cc
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/testing/file.h
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(test_plugin ${test_plugin_files})
|
|
||||||
target_link_libraries(test_plugin libprotoc libprotobuf GTest::gmock)
|
|
||||||
|
|
||||||
set(lite_test_files
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/lite_unittest.cc
|
|
||||||
)
|
|
||||||
add_executable(lite-test ${lite_test_files})
|
|
||||||
target_link_libraries(lite-test protobuf-lite-test-common libprotobuf-lite GTest::gmock_main)
|
|
||||||
|
|
||||||
add_test(NAME lite-test
|
|
||||||
COMMAND lite-test ${protobuf_GTEST_ARGS})
|
|
||||||
|
|
||||||
set(lite_arena_test_files
|
|
||||||
${protobuf_SOURCE_DIR}/src/google/protobuf/lite_arena_unittest.cc
|
|
||||||
)
|
|
||||||
add_executable(lite-arena-test ${lite_arena_test_files})
|
|
||||||
target_link_libraries(lite-arena-test protobuf-lite-test-common libprotobuf-lite GTest::gmock_main)
|
|
||||||
|
|
||||||
add_test(NAME lite-arena-test
|
|
||||||
COMMAND lite-arena-test ${protobuf_GTEST_ARGS})
|
|
||||||
|
|
||||||
add_custom_target(check
|
|
||||||
COMMAND tests
|
|
||||||
DEPENDS tests test_plugin
|
|
||||||
WORKING_DIRECTORY ${protobuf_SOURCE_DIR})
|
|
||||||
|
|
||||||
add_test(NAME check
|
|
||||||
COMMAND tests ${protobuf_GTEST_ARGS}
|
|
||||||
WORKING_DIRECTORY "${protobuf_SOURCE_DIR}")
|
|
@ -1,45 +0,0 @@
|
|||||||
#define VS_FF_DEBUG 0x1L
|
|
||||||
#define VS_VERSION_INFO 0x1L
|
|
||||||
#define VS_FFI_FILEFLAGSMASK 0x17L
|
|
||||||
#define VER_PRIVATEBUILD 0x0L
|
|
||||||
#define VER_PRERELEASE 0x0L
|
|
||||||
#define VOS__WINDOWS32 0x4L
|
|
||||||
#define VFT_DLL 0x2L
|
|
||||||
#define VFT2_UNKNOWN 0x0L
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
|
||||||
#define VER_DEBUG 0
|
|
||||||
#else
|
|
||||||
#define VER_DEBUG VS_FF_DEBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
|
||||||
FILEVERSION @protobuf_RC_FILEVERSION@
|
|
||||||
PRODUCTVERSION @protobuf_RC_FILEVERSION@
|
|
||||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
|
||||||
FILEFLAGS VER_DEBUG
|
|
||||||
FILEOS VOS__WINDOWS32
|
|
||||||
FILETYPE VFT_DLL
|
|
||||||
BEGIN
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
BEGIN
|
|
||||||
// English language (0x409) and the Windows Unicode codepage (1200)
|
|
||||||
VALUE "Translation", 0x409, 1200
|
|
||||||
END
|
|
||||||
BLOCK "StringFileInfo"
|
|
||||||
BEGIN
|
|
||||||
BLOCK "040904b0"
|
|
||||||
BEGIN
|
|
||||||
VALUE "FileDescription", "Compiled with @CMAKE_CXX_COMPILER_ID@ @CMAKE_CXX_COMPILER_VERSION@\0"
|
|
||||||
VALUE "ProductVersion", "@protobuf_VERSION@\0"
|
|
||||||
VALUE "FileVersion", "@protobuf_VERSION@\0"
|
|
||||||
VALUE "InternalName", "protobuf\0"
|
|
||||||
VALUE "ProductName", "Protocol Buffers - Google's Data Interchange Format\0"
|
|
||||||
VALUE "CompanyName", "Google Inc.\0"
|
|
||||||
VALUE "LegalCopyright", "Copyright 2008 Google Inc. All rights reserved.\0"
|
|
||||||
VALUE "Licence", "BSD\0"
|
|
||||||
VALUE "Info", "https://developers.google.com/protocol-buffers/\0"
|
|
||||||
END
|
|
||||||
END
|
|
||||||
END
|
|
File diff suppressed because it is too large
Load Diff
@ -1,218 +1,12 @@
|
|||||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
#define HASH_MAP_H @HASH_MAP_H@
|
||||||
|
#define HASH_SET_H @HASH_SET_H@
|
||||||
/* the name of <hash_map> */
|
#define HASH_MAP_CLASS @HASH_MAP_CLASS@
|
||||||
#undef HASH_MAP_CLASS
|
#define HASH_SET_CLASS @HASH_SET_CLASS@
|
||||||
|
#define HASH_NAMESPACE @HASH_NAMESPACE@
|
||||||
/* the location of <unordered_map> or <hash_map> */
|
#define HAVE_HASH_MAP @HAVE_HASH_MAP@
|
||||||
#undef HASH_MAP_H
|
#define HAVE_HASH_SET @HAVE_HASH_SET@
|
||||||
|
#define HAVE_PTHREAD @CMAKE_USE_PTHREADS_INIT@
|
||||||
/* the namespace of hash_map/hash_set */
|
|
||||||
#undef HASH_NAMESPACE
|
/* define if you want to use zlib. See readme.txt for additional
|
||||||
|
* requirements. */
|
||||||
/* the name of <hash_set> */
|
#define HAVE_ZLIB 1
|
||||||
#undef HASH_SET_CLASS
|
|
||||||
|
|
||||||
/* the location of <unordered_set> or <hash_set> */
|
|
||||||
#undef HASH_SET_H
|
|
||||||
|
|
||||||
/* define if the compiler supports basic C++11 syntax */
|
|
||||||
#undef HAVE_CXX11
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
|
||||||
#undef HAVE_DLFCN_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
|
||||||
#undef HAVE_FCNTL_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `ftruncate' function. */
|
|
||||||
#undef HAVE_FTRUNCATE
|
|
||||||
|
|
||||||
/* define if the compiler has hash_map */
|
|
||||||
#undef HAVE_HASH_MAP
|
|
||||||
|
|
||||||
/* define if the compiler has hash_set */
|
|
||||||
#undef HAVE_HASH_SET
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#undef HAVE_INTTYPES_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <limits.h> header file. */
|
|
||||||
#undef HAVE_LIMITS_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `memset' function. */
|
|
||||||
#undef HAVE_MEMSET
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <minix/config.h> header file. */
|
|
||||||
#undef HAVE_MINIX_CONFIG_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `mkdir' function. */
|
|
||||||
#undef HAVE_MKDIR
|
|
||||||
|
|
||||||
/* Define if you have POSIX threads libraries and header files. */
|
|
||||||
#undef HAVE_PTHREAD
|
|
||||||
|
|
||||||
/* Have PTHREAD_PRIO_INHERIT. */
|
|
||||||
#undef HAVE_PTHREAD_PRIO_INHERIT
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#undef HAVE_STDINT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdio.h> header file. */
|
|
||||||
#undef HAVE_STDIO_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#undef HAVE_STDLIB_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strchr' function. */
|
|
||||||
#undef HAVE_STRCHR
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strerror' function. */
|
|
||||||
#undef HAVE_STRERROR
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#undef HAVE_STRINGS_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#undef HAVE_STRING_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtol' function. */
|
|
||||||
#undef HAVE_STRTOL
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#undef HAVE_SYS_STAT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#undef HAVE_SYS_TYPES_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#undef HAVE_UNISTD_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <wchar.h> header file. */
|
|
||||||
#undef HAVE_WCHAR_H
|
|
||||||
|
|
||||||
/* Enable classes using zlib compression. */
|
|
||||||
#undef HAVE_ZLIB
|
|
||||||
|
|
||||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
|
||||||
#undef LT_OBJDIR
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#undef PACKAGE
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#undef PACKAGE_BUGREPORT
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#undef PACKAGE_NAME
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#undef PACKAGE_STRING
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#undef PACKAGE_TARNAME
|
|
||||||
|
|
||||||
/* Define to the home page for this package. */
|
|
||||||
#undef PACKAGE_URL
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#undef PACKAGE_VERSION
|
|
||||||
|
|
||||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
|
||||||
your system. */
|
|
||||||
#undef PTHREAD_CREATE_JOINABLE
|
|
||||||
|
|
||||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
|
||||||
required in a freestanding environment). This macro is provided for
|
|
||||||
backward compatibility; new code need not use it. */
|
|
||||||
#undef STDC_HEADERS
|
|
||||||
|
|
||||||
/* Enable extensions on AIX 3, Interix. */
|
|
||||||
#ifndef _ALL_SOURCE
|
|
||||||
# undef _ALL_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Enable general extensions on macOS. */
|
|
||||||
#ifndef _DARWIN_C_SOURCE
|
|
||||||
# undef _DARWIN_C_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Enable general extensions on Solaris. */
|
|
||||||
#ifndef __EXTENSIONS__
|
|
||||||
# undef __EXTENSIONS__
|
|
||||||
#endif
|
|
||||||
/* Enable GNU extensions on systems that have them. */
|
|
||||||
#ifndef _GNU_SOURCE
|
|
||||||
# undef _GNU_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Enable X/Open compliant socket functions that do not require linking
|
|
||||||
with -lxnet on HP-UX 11.11. */
|
|
||||||
#ifndef _HPUX_ALT_XOPEN_SOCKET_API
|
|
||||||
# undef _HPUX_ALT_XOPEN_SOCKET_API
|
|
||||||
#endif
|
|
||||||
/* Identify the host operating system as Minix.
|
|
||||||
This macro does not affect the system headers' behavior.
|
|
||||||
A future release of Autoconf may stop defining this macro. */
|
|
||||||
#ifndef _MINIX
|
|
||||||
# undef _MINIX
|
|
||||||
#endif
|
|
||||||
/* Enable general extensions on NetBSD.
|
|
||||||
Enable NetBSD compatibility extensions on Minix. */
|
|
||||||
#ifndef _NETBSD_SOURCE
|
|
||||||
# undef _NETBSD_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Enable OpenBSD compatibility extensions on NetBSD.
|
|
||||||
Oddly enough, this does nothing on OpenBSD. */
|
|
||||||
#ifndef _OPENBSD_SOURCE
|
|
||||||
# undef _OPENBSD_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Define to 1 if needed for POSIX-compatible behavior. */
|
|
||||||
#ifndef _POSIX_SOURCE
|
|
||||||
# undef _POSIX_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Define to 2 if needed for POSIX-compatible behavior. */
|
|
||||||
#ifndef _POSIX_1_SOURCE
|
|
||||||
# undef _POSIX_1_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Enable POSIX-compatible threading on Solaris. */
|
|
||||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
|
||||||
# undef _POSIX_PTHREAD_SEMANTICS
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
|
|
||||||
#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
|
||||||
# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
|
|
||||||
#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
|
|
||||||
# undef __STDC_WANT_IEC_60559_BFP_EXT__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
|
|
||||||
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
|
|
||||||
# undef __STDC_WANT_IEC_60559_DFP_EXT__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
|
|
||||||
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
|
||||||
# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
|
|
||||||
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
|
|
||||||
# undef __STDC_WANT_IEC_60559_TYPES_EXT__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
|
|
||||||
#ifndef __STDC_WANT_LIB_EXT2__
|
|
||||||
# undef __STDC_WANT_LIB_EXT2__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC 24747:2009. */
|
|
||||||
#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
|
|
||||||
# undef __STDC_WANT_MATH_SPEC_FUNCS__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions on HP NonStop. */
|
|
||||||
#ifndef _TANDEM_SOURCE
|
|
||||||
# undef _TANDEM_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Enable X/Open extensions. Define to 500 only if necessary
|
|
||||||
to make mbstate_t available. */
|
|
||||||
#ifndef _XOPEN_SOURCE
|
|
||||||
# undef _XOPEN_SOURCE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#undef VERSION
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,247 +0,0 @@
|
|||||||
## Process this file with autoconf to produce configure.
|
|
||||||
## In general, the safest way to proceed is to run ./autogen.sh
|
|
||||||
|
|
||||||
AC_PREREQ(2.59)
|
|
||||||
|
|
||||||
# Note: If you change the version, you must also update it in:
|
|
||||||
# * Protobuf.podspec
|
|
||||||
# * csharp/Google.Protobuf.Tools.nuspec
|
|
||||||
# * csharp/src/*/AssemblyInfo.cs
|
|
||||||
# * csharp/src/Google.Protobuf/Google.Protobuf.nuspec
|
|
||||||
# * java/*/pom.xml
|
|
||||||
# * python/google/protobuf/__init__.py
|
|
||||||
# * protoc-artifacts/pom.xml
|
|
||||||
# * src/google/protobuf/stubs/common.h
|
|
||||||
# * src/Makefile.am (Update -version-info for LDFLAGS if needed)
|
|
||||||
#
|
|
||||||
# In the SVN trunk, the version should always be the next anticipated release
|
|
||||||
# version with the "-pre" suffix. (We used to use "-SNAPSHOT" but this pushed
|
|
||||||
# the size of one file name in the dist tarfile over the 99-char limit.)
|
|
||||||
AC_INIT([Protocol Buffers],[3.21.10],[protobuf@googlegroups.com],[protobuf])
|
|
||||||
|
|
||||||
AM_MAINTAINER_MODE([enable])
|
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR(src/google/protobuf/message.cc)
|
|
||||||
# The config file is generated but not used by the source code, since we only
|
|
||||||
# need very few of them, e.g. HAVE_PTHREAD and HAVE_ZLIB. Those macros are
|
|
||||||
# passed down in CXXFLAGS manually in src/Makefile.am
|
|
||||||
AC_CONFIG_HEADERS([config.h])
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
|
||||||
|
|
||||||
AC_ARG_VAR(DIST_LANG, [language to include in the distribution package (i.e., make dist)])
|
|
||||||
case "$DIST_LANG" in
|
|
||||||
"") DIST_LANG=all ;;
|
|
||||||
all | cpp | csharp | java | python | javanano | objectivec | ruby | php) ;;
|
|
||||||
*) AC_MSG_FAILURE([unknown language: $DIST_LANG]) ;;
|
|
||||||
esac
|
|
||||||
AC_SUBST(DIST_LANG)
|
|
||||||
|
|
||||||
# autoconf's default CXXFLAGS are usually "-g -O2". These aren't necessarily
|
|
||||||
# the best choice for libprotobuf.
|
|
||||||
AS_IF([test "x${ac_cv_env_CFLAGS_set}" = "x"],
|
|
||||||
[CFLAGS=""])
|
|
||||||
AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"],
|
|
||||||
[CXXFLAGS=""])
|
|
||||||
|
|
||||||
AC_CANONICAL_TARGET
|
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([1.9 tar-ustar subdir-objects])
|
|
||||||
|
|
||||||
# Silent rules enabled: the output is minimal but informative.
|
|
||||||
# In particular, the warnings from the compiler stick out very clearly.
|
|
||||||
# To see all logs, use the --disable-silent-rules on configure or via make V=1
|
|
||||||
AM_SILENT_RULES([yes])
|
|
||||||
|
|
||||||
AC_ARG_WITH([zlib],
|
|
||||||
[AS_HELP_STRING([--with-zlib],
|
|
||||||
[include classes for streaming compressed data in and out @<:@default=check@:>@])],
|
|
||||||
[],[with_zlib=check])
|
|
||||||
|
|
||||||
AC_ARG_WITH([zlib-include],
|
|
||||||
[AS_HELP_STRING([--with-zlib-include=PATH],
|
|
||||||
[zlib include directory])],
|
|
||||||
[CPPFLAGS="-I$withval $CPPFLAGS"])
|
|
||||||
|
|
||||||
AC_ARG_WITH([zlib-lib],
|
|
||||||
[AS_HELP_STRING([--with-zlib-lib=PATH],
|
|
||||||
[zlib lib directory])],
|
|
||||||
[LDFLAGS="-L$withval $LDFLAGS"])
|
|
||||||
|
|
||||||
AC_ARG_WITH([protoc],
|
|
||||||
[AS_HELP_STRING([--with-protoc=COMMAND],
|
|
||||||
[use the given protoc command instead of building a new one when building tests (useful for cross-compiling)])],
|
|
||||||
[],[with_protoc=no])
|
|
||||||
|
|
||||||
# Checks for programs.
|
|
||||||
AC_PROG_CC
|
|
||||||
AC_PROG_CXX
|
|
||||||
AC_PROG_CXX_FOR_BUILD
|
|
||||||
AC_LANG([C++])
|
|
||||||
ACX_USE_SYSTEM_EXTENSIONS
|
|
||||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
|
||||||
AM_CONDITIONAL(GCC, test "$GCC" = yes) # let the Makefile know if we're gcc
|
|
||||||
AS_CASE([$target_os], [darwin*], [AC_PROG_OBJC], [AM_CONDITIONAL([am__fastdepOBJC], [false])])
|
|
||||||
|
|
||||||
# test_util.cc takes forever to compile with GCC and optimization turned on.
|
|
||||||
AC_MSG_CHECKING([C++ compiler flags...])
|
|
||||||
AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"],[
|
|
||||||
AS_IF([test "$GCC" = "yes"],[
|
|
||||||
PROTOBUF_OPT_FLAG="-O2"
|
|
||||||
CXXFLAGS="${CXXFLAGS} -g"
|
|
||||||
])
|
|
||||||
|
|
||||||
# Protocol Buffers contains several checks that are intended to be used only
|
|
||||||
# for debugging and which might hurt performance. Most users are probably
|
|
||||||
# end users who don't want these checks, so add -DNDEBUG by default.
|
|
||||||
CXXFLAGS="$CXXFLAGS -std=c++11 -DNDEBUG"
|
|
||||||
|
|
||||||
AC_MSG_RESULT([use default: $PROTOBUF_OPT_FLAG $CXXFLAGS])
|
|
||||||
],[
|
|
||||||
AC_MSG_RESULT([use user-supplied: $CXXFLAGS])
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_SUBST(PROTOBUF_OPT_FLAG)
|
|
||||||
|
|
||||||
ACX_CHECK_SUNCC
|
|
||||||
|
|
||||||
# Have to do libtool after SUNCC, other wise it "helpfully" adds Crun Cstd
|
|
||||||
# to the link
|
|
||||||
AC_PROG_LIBTOOL
|
|
||||||
|
|
||||||
# Check whether the linker supports version scripts
|
|
||||||
AC_MSG_CHECKING([whether the linker supports version scripts])
|
|
||||||
save_LDFLAGS=$LDFLAGS
|
|
||||||
LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map"
|
|
||||||
cat > conftest.map <<EOF
|
|
||||||
{
|
|
||||||
global:
|
|
||||||
main;
|
|
||||||
local:
|
|
||||||
*;
|
|
||||||
};
|
|
||||||
EOF
|
|
||||||
AC_LINK_IFELSE(
|
|
||||||
[AC_LANG_SOURCE([int main() { return 0; }])],
|
|
||||||
[have_ld_version_script=yes; AC_MSG_RESULT(yes)],
|
|
||||||
[have_ld_version_script=no; AC_MSG_RESULT(no)])
|
|
||||||
LDFLAGS=$save_LDFLAGS
|
|
||||||
AM_CONDITIONAL([HAVE_LD_VERSION_SCRIPT], [test "$have_ld_version_script" = "yes"])
|
|
||||||
|
|
||||||
# Checks for header files.
|
|
||||||
AC_HEADER_STDC
|
|
||||||
AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h stdlib.h unistd.h])
|
|
||||||
|
|
||||||
# Checks for library functions.
|
|
||||||
AC_FUNC_MEMCMP
|
|
||||||
AC_FUNC_STRTOD
|
|
||||||
AC_CHECK_FUNCS([ftruncate memset mkdir strchr strerror strtol])
|
|
||||||
|
|
||||||
# Check for zlib.
|
|
||||||
HAVE_ZLIB=0
|
|
||||||
AS_IF([test "$with_zlib" != no], [
|
|
||||||
AC_MSG_CHECKING([zlib version])
|
|
||||||
|
|
||||||
# First check the zlib header version.
|
|
||||||
AC_COMPILE_IFELSE(
|
|
||||||
[AC_LANG_PROGRAM([[
|
|
||||||
#include <zlib.h>
|
|
||||||
#if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204)
|
|
||||||
# error zlib version too old
|
|
||||||
#endif
|
|
||||||
]], [])], [
|
|
||||||
AC_MSG_RESULT([ok (1.2.0.4 or later)])
|
|
||||||
|
|
||||||
# Also need to add -lz to the linker flags and make sure this succeeds.
|
|
||||||
AC_SEARCH_LIBS([zlibVersion], [z], [
|
|
||||||
AC_DEFINE([HAVE_ZLIB], [1], [Enable classes using zlib compression.])
|
|
||||||
HAVE_ZLIB=1
|
|
||||||
], [
|
|
||||||
AS_IF([test "$with_zlib" != check], [
|
|
||||||
AC_MSG_FAILURE([--with-zlib was given, but no working zlib library was found])
|
|
||||||
])
|
|
||||||
])
|
|
||||||
], [
|
|
||||||
AS_IF([test "$with_zlib" = check], [
|
|
||||||
AC_MSG_RESULT([headers missing or too old (requires 1.2.0.4)])
|
|
||||||
], [
|
|
||||||
AC_MSG_FAILURE([--with-zlib was given, but zlib headers were not present or were too old (requires 1.2.0.4)])
|
|
||||||
])
|
|
||||||
])
|
|
||||||
])
|
|
||||||
AM_CONDITIONAL([HAVE_ZLIB], [test $HAVE_ZLIB = 1])
|
|
||||||
|
|
||||||
# Add -std=c++11 if necesssary. It is important for us to do this before the
|
|
||||||
# libatomic check below, since that also depends on C++11.
|
|
||||||
AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])
|
|
||||||
|
|
||||||
dnl On some platforms, std::atomic needs a helper library
|
|
||||||
AC_MSG_CHECKING(whether -latomic is needed)
|
|
||||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[
|
|
||||||
#include <atomic>
|
|
||||||
#include <cstdint>
|
|
||||||
std::atomic<std::int64_t> v;
|
|
||||||
int main() {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
]])], STD_ATOMIC_NEED_LIBATOMIC=no, STD_ATOMIC_NEED_LIBATOMIC=yes)
|
|
||||||
AC_MSG_RESULT($STD_ATOMIC_NEED_LIBATOMIC)
|
|
||||||
if test "x$STD_ATOMIC_NEED_LIBATOMIC" = xyes; then
|
|
||||||
LIBATOMIC_LIBS="-latomic"
|
|
||||||
fi
|
|
||||||
AC_SUBST([LIBATOMIC_LIBS])
|
|
||||||
|
|
||||||
AS_IF([test "$with_protoc" != "no"], [
|
|
||||||
PROTOC=$with_protoc
|
|
||||||
AS_IF([test "$with_protoc" = "yes"], [
|
|
||||||
# No argument given. Use system protoc.
|
|
||||||
PROTOC=protoc
|
|
||||||
])
|
|
||||||
AS_IF([echo "$PROTOC" | grep -q '^@<:@^/@:>@.*/'], [
|
|
||||||
# Does not start with a slash, but contains a slash. So, it's a relative
|
|
||||||
# path (as opposed to an absolute path or an executable in $PATH).
|
|
||||||
# Since it will actually be executed from the src directory, prefix with
|
|
||||||
# the current directory. We also insert $ac_top_build_prefix in case this
|
|
||||||
# is a nested package and --with-protoc was actually given on the outer
|
|
||||||
# package's configure script.
|
|
||||||
PROTOC=`pwd`/${ac_top_build_prefix}$PROTOC
|
|
||||||
])
|
|
||||||
AC_SUBST([PROTOC])
|
|
||||||
])
|
|
||||||
AM_CONDITIONAL([USE_EXTERNAL_PROTOC], [test "$with_protoc" != "no"])
|
|
||||||
|
|
||||||
AX_PTHREAD
|
|
||||||
AM_CONDITIONAL([HAVE_PTHREAD], [test "x$ax_pthread_ok" = "xyes"])
|
|
||||||
# We still keep this for improving pbconfig.h for unsupported platforms.
|
|
||||||
AC_CXX_STL_HASH
|
|
||||||
|
|
||||||
# Enable ObjC support for conformance directory on OS X.
|
|
||||||
OBJC_CONFORMANCE_TEST=0
|
|
||||||
case "$target_os" in
|
|
||||||
darwin*)
|
|
||||||
OBJC_CONFORMANCE_TEST=1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
AM_CONDITIONAL([OBJC_CONFORMANCE_TEST], [test $OBJC_CONFORMANCE_TEST = 1])
|
|
||||||
|
|
||||||
AC_MSG_CHECKING(whether -llog is needed)
|
|
||||||
ANDROID_TEST=no
|
|
||||||
case "$target_os" in
|
|
||||||
*android*)
|
|
||||||
ANDROID_TEST=yes
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
AC_MSG_RESULT($ANDROID_TEST)
|
|
||||||
if test "x$ANDROID_TEST" = xyes; then
|
|
||||||
LIBLOG_LIBS="-llog"
|
|
||||||
fi
|
|
||||||
AC_SUBST([LIBLOG_LIBS])
|
|
||||||
|
|
||||||
# HACK: Make gmock's configure script pick up our copy of CFLAGS and CXXFLAGS,
|
|
||||||
# since the flags added by ACX_CHECK_SUNCC must be used when compiling gmock
|
|
||||||
# too.
|
|
||||||
export CFLAGS
|
|
||||||
export CXXFLAGS
|
|
||||||
AC_CONFIG_SUBDIRS([third_party/googletest])
|
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile src/Makefile benchmarks/Makefile conformance/Makefile protobuf.pc protobuf-lite.pc])
|
|
||||||
AC_OUTPUT
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,318 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
//
|
||||||
|
// 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 FileDescriptor; // descriptor.h
|
||||||
|
class DescriptorPool; // 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Parse all command-line arguments.
|
||||||
|
bool 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.
|
||||||
|
bool 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.
|
||||||
|
static void GetTransitiveDependencies(
|
||||||
|
const FileDescriptor* file,
|
||||||
|
set<const FileDescriptor*>* already_seen,
|
||||||
|
RepeatedPtrField<FileDescriptorProto>* output);
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
// The name of the executable as invoked (i.e. argv[0]).
|
||||||
|
string executable_name_;
|
||||||
|
|
||||||
|
// Version info set with SetVersionInfo().
|
||||||
|
string version_info_;
|
||||||
|
|
||||||
|
// Map from flag names to registered generators.
|
||||||
|
struct GeneratorInfo {
|
||||||
|
CodeGenerator* generator;
|
||||||
|
string help_text;
|
||||||
|
};
|
||||||
|
typedef map<string, GeneratorInfo> GeneratorMap;
|
||||||
|
GeneratorMap generators_;
|
||||||
|
|
||||||
|
// 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 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_;
|
||||||
|
|
||||||
|
// 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,258 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_enum.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
|
||||||
|
const string& dllexport_decl)
|
||||||
|
: descriptor_(descriptor),
|
||||||
|
classname_(ClassName(descriptor, false)),
|
||||||
|
dllexport_decl_(dllexport_decl) {
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumGenerator::~EnumGenerator() {}
|
||||||
|
|
||||||
|
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
|
||||||
|
map<string, string> vars;
|
||||||
|
vars["classname"] = classname_;
|
||||||
|
vars["short_name"] = descriptor_->name();
|
||||||
|
|
||||||
|
printer->Print(vars, "enum $classname$ {\n");
|
||||||
|
printer->Indent();
|
||||||
|
|
||||||
|
const EnumValueDescriptor* min_value = descriptor_->value(0);
|
||||||
|
const EnumValueDescriptor* max_value = descriptor_->value(0);
|
||||||
|
|
||||||
|
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||||
|
vars["name"] = descriptor_->value(i)->name();
|
||||||
|
vars["number"] = SimpleItoa(descriptor_->value(i)->number());
|
||||||
|
vars["prefix"] = (descriptor_->containing_type() == NULL) ?
|
||||||
|
"" : classname_ + "_";
|
||||||
|
|
||||||
|
if (i > 0) printer->Print(",\n");
|
||||||
|
printer->Print(vars, "$prefix$$name$ = $number$");
|
||||||
|
|
||||||
|
if (descriptor_->value(i)->number() < min_value->number()) {
|
||||||
|
min_value = descriptor_->value(i);
|
||||||
|
}
|
||||||
|
if (descriptor_->value(i)->number() > max_value->number()) {
|
||||||
|
max_value = descriptor_->value(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("\n};\n");
|
||||||
|
|
||||||
|
vars["min_name"] = min_value->name();
|
||||||
|
vars["max_name"] = max_value->name();
|
||||||
|
|
||||||
|
if (dllexport_decl_.empty()) {
|
||||||
|
vars["dllexport"] = "";
|
||||||
|
} else {
|
||||||
|
vars["dllexport"] = dllexport_decl_ + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(vars,
|
||||||
|
"$dllexport$bool $classname$_IsValid(int value);\n"
|
||||||
|
"const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
|
||||||
|
"const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"
|
||||||
|
"const int $prefix$$short_name$_ARRAYSIZE = $prefix$$short_name$_MAX + 1;\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
if (HasDescriptorMethods(descriptor_->file())) {
|
||||||
|
printer->Print(vars,
|
||||||
|
"$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n");
|
||||||
|
// The _Name and _Parse methods
|
||||||
|
printer->Print(vars,
|
||||||
|
"inline const ::std::string& $classname$_Name($classname$ value) {\n"
|
||||||
|
" return ::google::protobuf::internal::NameOfEnum(\n"
|
||||||
|
" $classname$_descriptor(), value);\n"
|
||||||
|
"}\n");
|
||||||
|
printer->Print(vars,
|
||||||
|
"inline bool $classname$_Parse(\n"
|
||||||
|
" const ::std::string& name, $classname$* value) {\n"
|
||||||
|
" return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n"
|
||||||
|
" $classname$_descriptor(), name, value);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumGenerator::
|
||||||
|
GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
|
||||||
|
if (HasDescriptorMethods(descriptor_->file())) {
|
||||||
|
printer->Print(
|
||||||
|
"template <>\n"
|
||||||
|
"inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
|
||||||
|
" return $classname$_descriptor();\n"
|
||||||
|
"}\n",
|
||||||
|
"classname", ClassName(descriptor_, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
|
||||||
|
map<string, string> vars;
|
||||||
|
vars["nested_name"] = descriptor_->name();
|
||||||
|
vars["classname"] = classname_;
|
||||||
|
printer->Print(vars, "typedef $classname$ $nested_name$;\n");
|
||||||
|
|
||||||
|
for (int j = 0; j < descriptor_->value_count(); j++) {
|
||||||
|
vars["tag"] = descriptor_->value(j)->name();
|
||||||
|
printer->Print(vars,
|
||||||
|
"static const $nested_name$ $tag$ = $classname$_$tag$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(vars,
|
||||||
|
"static inline bool $nested_name$_IsValid(int value) {\n"
|
||||||
|
" return $classname$_IsValid(value);\n"
|
||||||
|
"}\n"
|
||||||
|
"static const $nested_name$ $nested_name$_MIN =\n"
|
||||||
|
" $classname$_$nested_name$_MIN;\n"
|
||||||
|
"static const $nested_name$ $nested_name$_MAX =\n"
|
||||||
|
" $classname$_$nested_name$_MAX;\n"
|
||||||
|
"static const int $nested_name$_ARRAYSIZE =\n"
|
||||||
|
" $classname$_$nested_name$_ARRAYSIZE;\n");
|
||||||
|
|
||||||
|
if (HasDescriptorMethods(descriptor_->file())) {
|
||||||
|
printer->Print(vars,
|
||||||
|
"static inline const ::google::protobuf::EnumDescriptor*\n"
|
||||||
|
"$nested_name$_descriptor() {\n"
|
||||||
|
" return $classname$_descriptor();\n"
|
||||||
|
"}\n");
|
||||||
|
printer->Print(vars,
|
||||||
|
"static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
|
||||||
|
" return $classname$_Name(value);\n"
|
||||||
|
"}\n");
|
||||||
|
printer->Print(vars,
|
||||||
|
"static inline bool $nested_name$_Parse(const ::std::string& name,\n"
|
||||||
|
" $nested_name$* value) {\n"
|
||||||
|
" return $classname$_Parse(name, value);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumGenerator::GenerateDescriptorInitializer(
|
||||||
|
io::Printer* printer, int index) {
|
||||||
|
map<string, string> vars;
|
||||||
|
vars["classname"] = classname_;
|
||||||
|
vars["index"] = SimpleItoa(index);
|
||||||
|
|
||||||
|
if (descriptor_->containing_type() == NULL) {
|
||||||
|
printer->Print(vars,
|
||||||
|
"$classname$_descriptor_ = file->enum_type($index$);\n");
|
||||||
|
} else {
|
||||||
|
vars["parent"] = ClassName(descriptor_->containing_type(), false);
|
||||||
|
printer->Print(vars,
|
||||||
|
"$classname$_descriptor_ = $parent$_descriptor_->enum_type($index$);\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumGenerator::GenerateMethods(io::Printer* printer) {
|
||||||
|
map<string, string> vars;
|
||||||
|
vars["classname"] = classname_;
|
||||||
|
|
||||||
|
if (HasDescriptorMethods(descriptor_->file())) {
|
||||||
|
printer->Print(vars,
|
||||||
|
"const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
|
||||||
|
" protobuf_AssignDescriptorsOnce();\n"
|
||||||
|
" return $classname$_descriptor_;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(vars,
|
||||||
|
"bool $classname$_IsValid(int value) {\n"
|
||||||
|
" switch(value) {\n");
|
||||||
|
|
||||||
|
// Multiple values may have the same number. Make sure we only cover
|
||||||
|
// each number once by first constructing a set containing all valid
|
||||||
|
// numbers, then printing a case statement for each element.
|
||||||
|
|
||||||
|
set<int> numbers;
|
||||||
|
for (int j = 0; j < descriptor_->value_count(); j++) {
|
||||||
|
const EnumValueDescriptor* value = descriptor_->value(j);
|
||||||
|
numbers.insert(value->number());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (set<int>::iterator iter = numbers.begin();
|
||||||
|
iter != numbers.end(); ++iter) {
|
||||||
|
printer->Print(
|
||||||
|
" case $number$:\n",
|
||||||
|
"number", SimpleItoa(*iter));
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(vars,
|
||||||
|
" return true;\n"
|
||||||
|
" default:\n"
|
||||||
|
" return false;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
if (descriptor_->containing_type() != NULL) {
|
||||||
|
// We need to "define" the static constants which were declared in the
|
||||||
|
// header, to give the linker a place to put them. Or at least the C++
|
||||||
|
// standard says we have to. MSVC actually insists tha we do _not_ define
|
||||||
|
// them again in the .cc file.
|
||||||
|
printer->Print("#ifndef _MSC_VER\n");
|
||||||
|
|
||||||
|
vars["parent"] = ClassName(descriptor_->containing_type(), false);
|
||||||
|
vars["nested_name"] = descriptor_->name();
|
||||||
|
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||||
|
vars["value"] = descriptor_->value(i)->name();
|
||||||
|
printer->Print(vars,
|
||||||
|
"const $classname$ $parent$::$value$;\n");
|
||||||
|
}
|
||||||
|
printer->Print(vars,
|
||||||
|
"const $classname$ $parent$::$nested_name$_MIN;\n"
|
||||||
|
"const $classname$ $parent$::$nested_name$_MAX;\n"
|
||||||
|
"const int $parent$::$nested_name$_ARRAYSIZE;\n");
|
||||||
|
|
||||||
|
printer->Print("#endif // _MSC_VER\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,361 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void SetEnumVariables(const FieldDescriptor* descriptor,
|
||||||
|
map<string, string>* variables) {
|
||||||
|
SetCommonFieldVariables(descriptor, variables);
|
||||||
|
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
|
||||||
|
(*variables)["type"] = ClassName(descriptor->enum_type(), true);
|
||||||
|
(*variables)["default"] = SimpleItoa(default_value->number());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
EnumFieldGenerator::
|
||||||
|
EnumFieldGenerator(const FieldDescriptor* descriptor)
|
||||||
|
: descriptor_(descriptor) {
|
||||||
|
SetEnumVariables(descriptor, &variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumFieldGenerator::~EnumFieldGenerator() {}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GeneratePrivateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "int $name$_;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline $type$ $name$() const$deprecation$;\n"
|
||||||
|
"inline void set_$name$($type$ value)$deprecation$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline $type$ $classname$::$name$() const {\n"
|
||||||
|
" return static_cast< $type$ >($name$_);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::set_$name$($type$ value) {\n"
|
||||||
|
" GOOGLE_DCHECK($type$_IsValid(value));\n"
|
||||||
|
" set_has_$name$();\n"
|
||||||
|
" $name$_ = value;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateClearingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "set_$name$(from.$name$());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateSwappingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateConstructorCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"int value;\n"
|
||||||
|
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||||
|
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
|
||||||
|
" input, &value)));\n"
|
||||||
|
"if ($type$_IsValid(value)) {\n"
|
||||||
|
" set_$name$(static_cast< $type$ >(value));\n");
|
||||||
|
if (HasUnknownFields(descriptor_->file())) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"} else {\n"
|
||||||
|
" mutable_unknown_fields()->AddVarint($number$, value);\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
|
||||||
|
" $number$, this->$name$(), output);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
|
||||||
|
" $number$, this->$name$(), target);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumFieldGenerator::
|
||||||
|
GenerateByteSize(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"total_size += $tag_size$ +\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
RepeatedEnumFieldGenerator::
|
||||||
|
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor)
|
||||||
|
: descriptor_(descriptor) {
|
||||||
|
SetEnumVariables(descriptor, &variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GeneratePrivateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::RepeatedField<int> $name$_;\n");
|
||||||
|
if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"mutable int _$name$_cached_byte_size_;\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline $type$ $name$(int index) const$deprecation$;\n"
|
||||||
|
"inline void set_$name$(int index, $type$ value)$deprecation$;\n"
|
||||||
|
"inline void add_$name$($type$ value)$deprecation$;\n");
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
|
||||||
|
"inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline $type$ $classname$::$name$(int index) const {\n"
|
||||||
|
" return static_cast< $type$ >($name$_.Get(index));\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::set_$name$(int index, $type$ value) {\n"
|
||||||
|
" GOOGLE_DCHECK($type$_IsValid(value));\n"
|
||||||
|
" $name$_.Set(index, value);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::add_$name$($type$ value) {\n"
|
||||||
|
" GOOGLE_DCHECK($type$_IsValid(value));\n"
|
||||||
|
" $name$_.Add(value);\n"
|
||||||
|
"}\n");
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const ::google::protobuf::RepeatedField<int>&\n"
|
||||||
|
"$classname$::$name$() const {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline ::google::protobuf::RepeatedField<int>*\n"
|
||||||
|
"$classname$::mutable_$name$() {\n"
|
||||||
|
" return &$name$_;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateClearingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_.Clear();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateSwappingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateConstructorCode(io::Printer* printer) const {
|
||||||
|
// Not needed for repeated fields.
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||||
|
// Don't use ReadRepeatedPrimitive here so that the enum can be validated.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"int value;\n"
|
||||||
|
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||||
|
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
|
||||||
|
" input, &value)));\n"
|
||||||
|
"if ($type$_IsValid(value)) {\n"
|
||||||
|
" add_$name$(static_cast< $type$ >(value));\n");
|
||||||
|
if (HasUnknownFields(descriptor_->file())) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"} else {\n"
|
||||||
|
" mutable_unknown_fields()->AddVarint($number$, value);\n");
|
||||||
|
}
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
|
||||||
|
if (!descriptor_->options().packed()) {
|
||||||
|
// We use a non-inlined implementation in this case, since this path will
|
||||||
|
// rarely be executed.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n"
|
||||||
|
" input,\n"
|
||||||
|
" &$type$_IsValid,\n"
|
||||||
|
" this->mutable_$name$())));\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::uint32 length;\n"
|
||||||
|
"DO_(input->ReadVarint32(&length));\n"
|
||||||
|
"::google::protobuf::io::CodedInputStream::Limit limit = "
|
||||||
|
"input->PushLimit(length);\n"
|
||||||
|
"while (input->BytesUntilLimit() > 0) {\n"
|
||||||
|
" int value;\n"
|
||||||
|
" DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||||
|
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
|
||||||
|
" input, &value)));\n"
|
||||||
|
" if ($type$_IsValid(value)) {\n"
|
||||||
|
" add_$name$(static_cast< $type$ >(value));\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"input->PopLimit(limit);\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
// Write the tag and the size.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (this->$name$_size() > 0) {\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::WriteTag(\n"
|
||||||
|
" $number$,\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
|
||||||
|
" output);\n"
|
||||||
|
" output->WriteVarint32(_$name$_cached_byte_size_);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n"
|
||||||
|
" this->$name$(i), output);\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
|
||||||
|
" $number$, this->$name$(i), output);\n");
|
||||||
|
}
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
// Write the tag and the size.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (this->$name$_size() > 0) {\n"
|
||||||
|
" target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
|
||||||
|
" $number$,\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
|
||||||
|
" target);\n"
|
||||||
|
" target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
|
||||||
|
" _$name$_cached_byte_size_, target);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
" target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
|
||||||
|
" this->$name$(i), target);\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
" target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
|
||||||
|
" $number$, this->$name$(i), target);\n");
|
||||||
|
}
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator::
|
||||||
|
GenerateByteSize(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"{\n"
|
||||||
|
" int data_size = 0;\n");
|
||||||
|
printer->Indent();
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||||
|
" data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n"
|
||||||
|
" this->$name$(i));\n"
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (data_size > 0) {\n"
|
||||||
|
" total_size += $tag_size$ +\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
|
||||||
|
"}\n"
|
||||||
|
"_$name$_cached_byte_size_ = data_size;\n"
|
||||||
|
"total_size += data_size;\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"total_size += $tag_size$ * this->$name$_size() + data_size;\n");
|
||||||
|
}
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,103 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
class EnumFieldGenerator : public FieldGenerator {
|
||||||
|
public:
|
||||||
|
explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
|
||||||
|
~EnumFieldGenerator();
|
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||||
|
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||||
|
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||||
|
void GenerateClearingCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
|
void GenerateSwappingCode(io::Printer* printer) const;
|
||||||
|
void GenerateConstructorCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||||
|
void GenerateByteSize(io::Printer* printer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const FieldDescriptor* descriptor_;
|
||||||
|
map<string, string> variables_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
class RepeatedEnumFieldGenerator : public FieldGenerator {
|
||||||
|
public:
|
||||||
|
explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
|
||||||
|
~RepeatedEnumFieldGenerator();
|
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||||
|
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||||
|
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||||
|
void GenerateClearingCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
|
void GenerateSwappingCode(io::Printer* printer) const;
|
||||||
|
void GenerateConstructorCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||||
|
void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||||
|
void GenerateByteSize(io::Printer* printer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const FieldDescriptor* descriptor_;
|
||||||
|
map<string, string> variables_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
|
@ -0,0 +1,210 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_extension.h>
|
||||||
|
#include <map>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Returns the fully-qualified class name of the message that this field
|
||||||
|
// extends. This function is used in the Google-internal code to handle some
|
||||||
|
// legacy cases.
|
||||||
|
string ExtendeeClassName(const FieldDescriptor* descriptor) {
|
||||||
|
const Descriptor* extendee = descriptor->containing_type();
|
||||||
|
return ClassName(extendee, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
|
||||||
|
const string& dllexport_decl)
|
||||||
|
: descriptor_(descriptor),
|
||||||
|
dllexport_decl_(dllexport_decl) {
|
||||||
|
// Construct type_traits_.
|
||||||
|
if (descriptor_->is_repeated()) {
|
||||||
|
type_traits_ = "Repeated";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (descriptor_->cpp_type()) {
|
||||||
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
|
type_traits_.append("EnumTypeTraits< ");
|
||||||
|
type_traits_.append(ClassName(descriptor_->enum_type(), true));
|
||||||
|
type_traits_.append(", ");
|
||||||
|
type_traits_.append(ClassName(descriptor_->enum_type(), true));
|
||||||
|
type_traits_.append("_IsValid>");
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
|
type_traits_.append("StringTypeTraits");
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
|
type_traits_.append("MessageTypeTraits< ");
|
||||||
|
type_traits_.append(ClassName(descriptor_->message_type(), true));
|
||||||
|
type_traits_.append(" >");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
type_traits_.append("PrimitiveTypeTraits< ");
|
||||||
|
type_traits_.append(PrimitiveTypeName(descriptor_->cpp_type()));
|
||||||
|
type_traits_.append(" >");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtensionGenerator::~ExtensionGenerator() {}
|
||||||
|
|
||||||
|
void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
|
||||||
|
map<string, string> vars;
|
||||||
|
vars["extendee" ] = ExtendeeClassName(descriptor_);
|
||||||
|
vars["number" ] = SimpleItoa(descriptor_->number());
|
||||||
|
vars["type_traits" ] = type_traits_;
|
||||||
|
vars["name" ] = descriptor_->name();
|
||||||
|
vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
|
||||||
|
vars["packed" ] = descriptor_->options().packed() ? "true" : "false";
|
||||||
|
vars["constant_name"] = FieldConstantName(descriptor_);
|
||||||
|
|
||||||
|
// If this is a class member, it needs to be declared "static". Otherwise,
|
||||||
|
// it needs to be "extern". In the latter case, it also needs the DLL
|
||||||
|
// export/import specifier.
|
||||||
|
if (descriptor_->extension_scope() == NULL) {
|
||||||
|
vars["qualifier"] = "extern";
|
||||||
|
if (!dllexport_decl_.empty()) {
|
||||||
|
vars["qualifier"] = dllexport_decl_ + " " + vars["qualifier"];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vars["qualifier"] = "static";
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(vars,
|
||||||
|
"static const int $constant_name$ = $number$;\n"
|
||||||
|
"$qualifier$ ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
|
||||||
|
" ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
|
||||||
|
" $name$;\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
|
||||||
|
// If this is a class member, it needs to be declared in its class scope.
|
||||||
|
string scope = (descriptor_->extension_scope() == NULL) ? "" :
|
||||||
|
ClassName(descriptor_->extension_scope(), false) + "::";
|
||||||
|
string name = scope + descriptor_->name();
|
||||||
|
|
||||||
|
map<string, string> vars;
|
||||||
|
vars["extendee" ] = ExtendeeClassName(descriptor_);
|
||||||
|
vars["type_traits" ] = type_traits_;
|
||||||
|
vars["name" ] = name;
|
||||||
|
vars["constant_name"] = FieldConstantName(descriptor_);
|
||||||
|
vars["default" ] = DefaultValue(descriptor_);
|
||||||
|
vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
|
||||||
|
vars["packed" ] = descriptor_->options().packed() ? "true" : "false";
|
||||||
|
vars["scope" ] = scope;
|
||||||
|
|
||||||
|
if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
||||||
|
// We need to declare a global string which will contain the default value.
|
||||||
|
// We cannot declare it at class scope because that would require exposing
|
||||||
|
// it in the header which would be annoying for other reasons. So we
|
||||||
|
// replace :: with _ in the name and declare it as a global.
|
||||||
|
string global_name = StringReplace(name, "::", "_", true);
|
||||||
|
vars["global_name"] = global_name;
|
||||||
|
printer->Print(vars,
|
||||||
|
"const ::std::string $global_name$_default($default$);\n");
|
||||||
|
|
||||||
|
// Update the default to refer to the string global.
|
||||||
|
vars["default"] = global_name + "_default";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Likewise, class members need to declare the field constant variable.
|
||||||
|
if (descriptor_->extension_scope() != NULL) {
|
||||||
|
printer->Print(vars,
|
||||||
|
"#ifndef _MSC_VER\n"
|
||||||
|
"const int $scope$$constant_name$;\n"
|
||||||
|
"#endif\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(vars,
|
||||||
|
"::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
|
||||||
|
" ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
|
||||||
|
" $name$($constant_name$, $default$);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
|
||||||
|
map<string, string> vars;
|
||||||
|
vars["extendee" ] = ExtendeeClassName(descriptor_);
|
||||||
|
vars["number" ] = SimpleItoa(descriptor_->number());
|
||||||
|
vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
|
||||||
|
vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false";
|
||||||
|
vars["is_packed" ] = (descriptor_->is_repeated() &&
|
||||||
|
descriptor_->options().packed())
|
||||||
|
? "true" : "false";
|
||||||
|
|
||||||
|
switch (descriptor_->cpp_type()) {
|
||||||
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
|
printer->Print(vars,
|
||||||
|
"::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
|
||||||
|
" &$extendee$::default_instance(),\n"
|
||||||
|
" $number$, $field_type$, $is_repeated$, $is_packed$,\n");
|
||||||
|
printer->Print(
|
||||||
|
" &$type$_IsValid);\n",
|
||||||
|
"type", ClassName(descriptor_->enum_type(), true));
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
|
printer->Print(vars,
|
||||||
|
"::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
|
||||||
|
" &$extendee$::default_instance(),\n"
|
||||||
|
" $number$, $field_type$, $is_repeated$, $is_packed$,\n");
|
||||||
|
printer->Print(
|
||||||
|
" &$type$::default_instance());\n",
|
||||||
|
"type", ClassName(descriptor_->message_type(), true));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printer->Print(vars,
|
||||||
|
"::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
|
||||||
|
" &$extendee$::default_instance(),\n"
|
||||||
|
" $number$, $field_type$, $is_repeated$, $is_packed$);\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,139 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
|
||||||
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
#include <google/protobuf/wire_format.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
using internal::WireFormat;
|
||||||
|
|
||||||
|
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||||
|
map<string, string>* variables) {
|
||||||
|
(*variables)["name"] = FieldName(descriptor);
|
||||||
|
(*variables)["index"] = SimpleItoa(descriptor->index());
|
||||||
|
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||||
|
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
|
||||||
|
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
|
||||||
|
|
||||||
|
(*variables)["tag_size"] = SimpleItoa(
|
||||||
|
WireFormat::TagSize(descriptor->number(), descriptor->type()));
|
||||||
|
(*variables)["deprecation"] = descriptor->options().deprecated()
|
||||||
|
? " PROTOBUF_DEPRECATED" : "";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldGenerator::~FieldGenerator() {}
|
||||||
|
|
||||||
|
void FieldGenerator::
|
||||||
|
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
|
||||||
|
// Reaching here indicates a bug. Cases are:
|
||||||
|
// - This FieldGenerator should support packing, but this method should be
|
||||||
|
// overridden.
|
||||||
|
// - This FieldGenerator doesn't support packing, and this method should
|
||||||
|
// never have been called.
|
||||||
|
GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() "
|
||||||
|
<< "called on field generator that does not support packing.";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
|
||||||
|
: descriptor_(descriptor),
|
||||||
|
field_generators_(
|
||||||
|
new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
|
||||||
|
// Construct all the FieldGenerators.
|
||||||
|
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||||
|
field_generators_[i].reset(MakeGenerator(descriptor->field(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
|
||||||
|
if (field->is_repeated()) {
|
||||||
|
switch (field->cpp_type()) {
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
|
return new RepeatedMessageFieldGenerator(field);
|
||||||
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
|
switch (field->options().ctype()) {
|
||||||
|
default: // RepeatedStringFieldGenerator handles unknown ctypes.
|
||||||
|
case FieldOptions::STRING:
|
||||||
|
return new RepeatedStringFieldGenerator(field);
|
||||||
|
}
|
||||||
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
|
return new RepeatedEnumFieldGenerator(field);
|
||||||
|
default:
|
||||||
|
return new RepeatedPrimitiveFieldGenerator(field);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (field->cpp_type()) {
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
|
return new MessageFieldGenerator(field);
|
||||||
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
|
switch (field->options().ctype()) {
|
||||||
|
default: // StringFieldGenerator handles unknown ctypes.
|
||||||
|
case FieldOptions::STRING:
|
||||||
|
return new StringFieldGenerator(field);
|
||||||
|
}
|
||||||
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
|
return new EnumFieldGenerator(field);
|
||||||
|
default:
|
||||||
|
return new PrimitiveFieldGenerator(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldGeneratorMap::~FieldGeneratorMap() {}
|
||||||
|
|
||||||
|
const FieldGenerator& FieldGeneratorMap::get(
|
||||||
|
const FieldDescriptor* field) const {
|
||||||
|
GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
|
||||||
|
return *field_generators_[field->index()];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,167 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace io {
|
||||||
|
class Printer; // printer.h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
// Helper function: set variables in the map that are the same for all
|
||||||
|
// field code generators.
|
||||||
|
// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
|
||||||
|
// 'deprecation'].
|
||||||
|
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||||
|
map<string, string>* variables);
|
||||||
|
|
||||||
|
class FieldGenerator {
|
||||||
|
public:
|
||||||
|
FieldGenerator() {}
|
||||||
|
virtual ~FieldGenerator();
|
||||||
|
|
||||||
|
// Generate lines of code declaring members fields of the message class
|
||||||
|
// needed to represent this field. These are placed inside the message
|
||||||
|
// class.
|
||||||
|
virtual void GeneratePrivateMembers(io::Printer* printer) const = 0;
|
||||||
|
|
||||||
|
// Generate prototypes for all of the accessor functions related to this
|
||||||
|
// field. These are placed inside the class definition.
|
||||||
|
virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0;
|
||||||
|
|
||||||
|
// Generate inline definitions of accessor functions for this field.
|
||||||
|
// These are placed inside the header after all class definitions.
|
||||||
|
virtual void GenerateInlineAccessorDefinitions(
|
||||||
|
io::Printer* printer) const = 0;
|
||||||
|
|
||||||
|
// Generate definitions of accessors that aren't inlined. These are
|
||||||
|
// placed somewhere in the .cc file.
|
||||||
|
// Most field types don't need this, so the default implementation is empty.
|
||||||
|
virtual void GenerateNonInlineAccessorDefinitions(
|
||||||
|
io::Printer* printer) const {}
|
||||||
|
|
||||||
|
// Generate lines of code (statements, not declarations) which clear the
|
||||||
|
// field. This is used to define the clear_$name$() method as well as
|
||||||
|
// the Clear() method for the whole message.
|
||||||
|
virtual void GenerateClearingCode(io::Printer* printer) const = 0;
|
||||||
|
|
||||||
|
// Generate lines of code (statements, not declarations) which merges the
|
||||||
|
// contents of the field from the current message to the target message,
|
||||||
|
// which is stored in the generated code variable "from".
|
||||||
|
// This is used to fill in the MergeFrom method for the whole message.
|
||||||
|
// Details of this usage can be found in message.cc under the
|
||||||
|
// GenerateMergeFrom method.
|
||||||
|
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
|
||||||
|
|
||||||
|
// Generate lines of code (statements, not declarations) which swaps
|
||||||
|
// this field and the corresponding field of another message, which
|
||||||
|
// is stored in the generated code variable "other". This is used to
|
||||||
|
// define the Swap method. Details of usage can be found in
|
||||||
|
// message.cc under the GenerateSwap method.
|
||||||
|
virtual void GenerateSwappingCode(io::Printer* printer) const = 0;
|
||||||
|
|
||||||
|
// Generate initialization code for private members declared by
|
||||||
|
// GeneratePrivateMembers(). These go into the message class's SharedCtor()
|
||||||
|
// method, invoked by each of the generated constructors.
|
||||||
|
virtual void GenerateConstructorCode(io::Printer* printer) const = 0;
|
||||||
|
|
||||||
|
// Generate any code that needs to go in the class's SharedDtor() method,
|
||||||
|
// invoked by the destructor.
|
||||||
|
// Most field types don't need this, so the default implementation is empty.
|
||||||
|
virtual void GenerateDestructorCode(io::Printer* printer) const {}
|
||||||
|
|
||||||
|
// Generate lines to decode this field, which will be placed inside the
|
||||||
|
// message's MergeFromCodedStream() method.
|
||||||
|
virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
|
||||||
|
|
||||||
|
// Generate lines to decode this field from a packed value, which will be
|
||||||
|
// placed inside the message's MergeFromCodedStream() method.
|
||||||
|
virtual void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer)
|
||||||
|
const;
|
||||||
|
|
||||||
|
// Generate lines to serialize this field, which are placed within the
|
||||||
|
// message's SerializeWithCachedSizes() method.
|
||||||
|
virtual void GenerateSerializeWithCachedSizes(io::Printer* printer) const = 0;
|
||||||
|
|
||||||
|
// Generate lines to serialize this field directly to the array "target",
|
||||||
|
// which are placed within the message's SerializeWithCachedSizesToArray()
|
||||||
|
// method. This must also advance "target" past the written bytes.
|
||||||
|
virtual void GenerateSerializeWithCachedSizesToArray(
|
||||||
|
io::Printer* printer) const = 0;
|
||||||
|
|
||||||
|
// Generate lines to compute the serialized size of this field, which
|
||||||
|
// are placed in the message's ByteSize() method.
|
||||||
|
virtual void GenerateByteSize(io::Printer* printer) const = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convenience class which constructs FieldGenerators for a Descriptor.
|
||||||
|
class FieldGeneratorMap {
|
||||||
|
public:
|
||||||
|
explicit FieldGeneratorMap(const Descriptor* descriptor);
|
||||||
|
~FieldGeneratorMap();
|
||||||
|
|
||||||
|
const FieldGenerator& get(const FieldDescriptor* field) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Descriptor* descriptor_;
|
||||||
|
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
|
||||||
|
|
||||||
|
static FieldGenerator* MakeGenerator(const FieldDescriptor* field);
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
|
@ -0,0 +1,611 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_file.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_enum.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_service.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_extension.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_message.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
FileGenerator::FileGenerator(const FileDescriptor* file,
|
||||||
|
const string& dllexport_decl)
|
||||||
|
: file_(file),
|
||||||
|
message_generators_(
|
||||||
|
new scoped_ptr<MessageGenerator>[file->message_type_count()]),
|
||||||
|
enum_generators_(
|
||||||
|
new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
|
||||||
|
service_generators_(
|
||||||
|
new scoped_ptr<ServiceGenerator>[file->service_count()]),
|
||||||
|
extension_generators_(
|
||||||
|
new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
|
||||||
|
dllexport_decl_(dllexport_decl) {
|
||||||
|
|
||||||
|
for (int i = 0; i < file->message_type_count(); i++) {
|
||||||
|
message_generators_[i].reset(
|
||||||
|
new MessageGenerator(file->message_type(i), dllexport_decl));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < file->enum_type_count(); i++) {
|
||||||
|
enum_generators_[i].reset(
|
||||||
|
new EnumGenerator(file->enum_type(i), dllexport_decl));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < file->service_count(); i++) {
|
||||||
|
service_generators_[i].reset(
|
||||||
|
new ServiceGenerator(file->service(i), dllexport_decl));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < file->extension_count(); i++) {
|
||||||
|
extension_generators_[i].reset(
|
||||||
|
new ExtensionGenerator(file->extension(i), dllexport_decl));
|
||||||
|
}
|
||||||
|
|
||||||
|
SplitStringUsing(file_->package(), ".", &package_parts_);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileGenerator::~FileGenerator() {}
|
||||||
|
|
||||||
|
void FileGenerator::GenerateHeader(io::Printer* printer) {
|
||||||
|
string filename_identifier = FilenameIdentifier(file_->name());
|
||||||
|
|
||||||
|
// Generate top of header.
|
||||||
|
printer->Print(
|
||||||
|
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
||||||
|
"// source: $filename$\n"
|
||||||
|
"\n"
|
||||||
|
"#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
|
||||||
|
"#define PROTOBUF_$filename_identifier$__INCLUDED\n"
|
||||||
|
"\n"
|
||||||
|
"#include <string>\n"
|
||||||
|
"\n",
|
||||||
|
"filename", file_->name(),
|
||||||
|
"filename_identifier", filename_identifier);
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"#include <google/protobuf/stubs/common.h>\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
// Verify the protobuf library header version is compatible with the protoc
|
||||||
|
// version before going any further.
|
||||||
|
printer->Print(
|
||||||
|
"#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
|
||||||
|
"#error This file was generated by a newer version of protoc which is\n"
|
||||||
|
"#error incompatible with your Protocol Buffer headers. Please update\n"
|
||||||
|
"#error your headers.\n"
|
||||||
|
"#endif\n"
|
||||||
|
"#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
|
||||||
|
"#error This file was generated by an older version of protoc which is\n"
|
||||||
|
"#error incompatible with your Protocol Buffer headers. Please\n"
|
||||||
|
"#error regenerate this file with a newer version of protoc.\n"
|
||||||
|
"#endif\n"
|
||||||
|
"\n",
|
||||||
|
"min_header_version",
|
||||||
|
SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
|
||||||
|
"protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
|
||||||
|
|
||||||
|
// OK, it's now safe to #include other files.
|
||||||
|
printer->Print(
|
||||||
|
"#include <google/protobuf/generated_message_util.h>\n"
|
||||||
|
"#include <google/protobuf/repeated_field.h>\n"
|
||||||
|
"#include <google/protobuf/extension_set.h>\n");
|
||||||
|
|
||||||
|
if (HasDescriptorMethods(file_)) {
|
||||||
|
printer->Print(
|
||||||
|
"#include <google/protobuf/generated_message_reflection.h>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasGenericServices(file_)) {
|
||||||
|
printer->Print(
|
||||||
|
"#include <google/protobuf/service.h>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < file_->dependency_count(); i++) {
|
||||||
|
printer->Print(
|
||||||
|
"#include \"$dependency$.pb.h\"\n",
|
||||||
|
"dependency", StripProto(file_->dependency(i)->name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"// @@protoc_insertion_point(includes)\n");
|
||||||
|
|
||||||
|
// Open namespace.
|
||||||
|
GenerateNamespaceOpeners(printer);
|
||||||
|
|
||||||
|
// Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
|
||||||
|
// functions, so that we can declare them to be friends of each class.
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"// Internal implementation detail -- do not call these.\n"
|
||||||
|
"void $dllexport_decl$ $adddescriptorsname$();\n",
|
||||||
|
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
|
||||||
|
"dllexport_decl", dllexport_decl_);
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
// Note that we don't put dllexport_decl on these because they are only
|
||||||
|
// called by the .pb.cc file in which they are defined.
|
||||||
|
"void $assigndescriptorsname$();\n"
|
||||||
|
"void $shutdownfilename$();\n"
|
||||||
|
"\n",
|
||||||
|
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
|
||||||
|
"shutdownfilename", GlobalShutdownFileName(file_->name()));
|
||||||
|
|
||||||
|
// Generate forward declarations of classes.
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
|
message_generators_[i]->GenerateForwardDeclaration(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print("\n");
|
||||||
|
|
||||||
|
// Generate enum definitions.
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
|
message_generators_[i]->GenerateEnumDefinitions(printer);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||||
|
enum_generators_[i]->GenerateDefinition(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(kThickSeparator);
|
||||||
|
printer->Print("\n");
|
||||||
|
|
||||||
|
// Generate class definitions.
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
printer->Print("\n");
|
||||||
|
printer->Print(kThinSeparator);
|
||||||
|
printer->Print("\n");
|
||||||
|
}
|
||||||
|
message_generators_[i]->GenerateClassDefinition(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print("\n");
|
||||||
|
printer->Print(kThickSeparator);
|
||||||
|
printer->Print("\n");
|
||||||
|
|
||||||
|
if (HasGenericServices(file_)) {
|
||||||
|
// Generate service definitions.
|
||||||
|
for (int i = 0; i < file_->service_count(); i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
printer->Print("\n");
|
||||||
|
printer->Print(kThinSeparator);
|
||||||
|
printer->Print("\n");
|
||||||
|
}
|
||||||
|
service_generators_[i]->GenerateDeclarations(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print("\n");
|
||||||
|
printer->Print(kThickSeparator);
|
||||||
|
printer->Print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Declare extension identifiers.
|
||||||
|
for (int i = 0; i < file_->extension_count(); i++) {
|
||||||
|
extension_generators_[i]->GenerateDeclaration(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print("\n");
|
||||||
|
printer->Print(kThickSeparator);
|
||||||
|
printer->Print("\n");
|
||||||
|
|
||||||
|
// Generate class inline methods.
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
printer->Print(kThinSeparator);
|
||||||
|
printer->Print("\n");
|
||||||
|
}
|
||||||
|
message_generators_[i]->GenerateInlineMethods(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"// @@protoc_insertion_point(namespace_scope)\n");
|
||||||
|
|
||||||
|
// Close up namespace.
|
||||||
|
GenerateNamespaceClosers(printer);
|
||||||
|
|
||||||
|
// Emit GetEnumDescriptor specializations into google::protobuf namespace:
|
||||||
|
if (HasDescriptorMethods(file_)) {
|
||||||
|
// The SWIG conditional is to avoid a null-pointer dereference
|
||||||
|
// (bug 1984964) in swig-1.3.21 resulting from the following syntax:
|
||||||
|
// namespace X { void Y<Z::W>(); }
|
||||||
|
// which appears in GetEnumDescriptor() specializations.
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"#ifndef SWIG\n"
|
||||||
|
"namespace google {\nnamespace protobuf {\n"
|
||||||
|
"\n");
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
|
message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||||
|
enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
|
||||||
|
}
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"} // namespace google\n} // namespace protobuf\n"
|
||||||
|
"#endif // SWIG\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"// @@protoc_insertion_point(global_scope)\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
|
||||||
|
"filename_identifier", filename_identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileGenerator::GenerateSource(io::Printer* printer) {
|
||||||
|
printer->Print(
|
||||||
|
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
|
// The generated code calls accessors that might be deprecated. We don't
|
||||||
|
// want the compiler to warn in generated code.
|
||||||
|
"#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
|
||||||
|
"#include \"$basename$.pb.h\"\n"
|
||||||
|
"\n"
|
||||||
|
"#include <algorithm>\n" // for swap()
|
||||||
|
"\n"
|
||||||
|
"#include <google/protobuf/stubs/once.h>\n"
|
||||||
|
"#include <google/protobuf/io/coded_stream.h>\n"
|
||||||
|
"#include <google/protobuf/wire_format_lite_inl.h>\n",
|
||||||
|
"basename", StripProto(file_->name()));
|
||||||
|
|
||||||
|
if (HasDescriptorMethods(file_)) {
|
||||||
|
printer->Print(
|
||||||
|
"#include <google/protobuf/descriptor.h>\n"
|
||||||
|
"#include <google/protobuf/reflection_ops.h>\n"
|
||||||
|
"#include <google/protobuf/wire_format.h>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"// @@protoc_insertion_point(includes)\n");
|
||||||
|
|
||||||
|
GenerateNamespaceOpeners(printer);
|
||||||
|
|
||||||
|
if (HasDescriptorMethods(file_)) {
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"namespace {\n"
|
||||||
|
"\n");
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
|
message_generators_[i]->GenerateDescriptorDeclarations(printer);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||||
|
printer->Print(
|
||||||
|
"const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
|
||||||
|
"name", ClassName(file_->enum_type(i), false));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasGenericServices(file_)) {
|
||||||
|
for (int i = 0; i < file_->service_count(); i++) {
|
||||||
|
printer->Print(
|
||||||
|
"const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
|
||||||
|
"name", file_->service(i)->name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"} // namespace\n"
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define our externally-visible BuildDescriptors() function. (For the lite
|
||||||
|
// library, all this does is initialize default instances.)
|
||||||
|
GenerateBuildDescriptors(printer);
|
||||||
|
|
||||||
|
// Generate enums.
|
||||||
|
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||||
|
enum_generators_[i]->GenerateMethods(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate classes.
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
|
printer->Print("\n");
|
||||||
|
printer->Print(kThickSeparator);
|
||||||
|
printer->Print("\n");
|
||||||
|
message_generators_[i]->GenerateClassMethods(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasGenericServices(file_)) {
|
||||||
|
// Generate services.
|
||||||
|
for (int i = 0; i < file_->service_count(); i++) {
|
||||||
|
if (i == 0) printer->Print("\n");
|
||||||
|
printer->Print(kThickSeparator);
|
||||||
|
printer->Print("\n");
|
||||||
|
service_generators_[i]->GenerateImplementation(printer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define extensions.
|
||||||
|
for (int i = 0; i < file_->extension_count(); i++) {
|
||||||
|
extension_generators_[i]->GenerateDefinition(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"// @@protoc_insertion_point(namespace_scope)\n");
|
||||||
|
|
||||||
|
GenerateNamespaceClosers(printer);
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"// @@protoc_insertion_point(global_scope)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
|
||||||
|
// AddDescriptors() is a file-level procedure which adds the encoded
|
||||||
|
// FileDescriptorProto for this .proto file to the global DescriptorPool
|
||||||
|
// for generated files (DescriptorPool::generated_pool()). It always runs
|
||||||
|
// at static initialization time, so all files will be registered before
|
||||||
|
// main() starts. This procedure also constructs default instances and
|
||||||
|
// registers extensions.
|
||||||
|
//
|
||||||
|
// Its sibling, AssignDescriptors(), actually pulls the compiled
|
||||||
|
// FileDescriptor from the DescriptorPool and uses it to populate all of
|
||||||
|
// the global variables which store pointers to the descriptor objects.
|
||||||
|
// It also constructs the reflection objects. It is called the first time
|
||||||
|
// anyone calls descriptor() or GetReflection() on one of the types defined
|
||||||
|
// in the file.
|
||||||
|
|
||||||
|
// In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
|
||||||
|
// and we only use AddDescriptors() to allocate default instances.
|
||||||
|
if (HasDescriptorMethods(file_)) {
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"void $assigndescriptorsname$() {\n",
|
||||||
|
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
|
||||||
|
printer->Indent();
|
||||||
|
|
||||||
|
// Make sure the file has found its way into the pool. If a descriptor
|
||||||
|
// is requested *during* static init then AddDescriptors() may not have
|
||||||
|
// been called yet, so we call it manually. Note that it's fine if
|
||||||
|
// AddDescriptors() is called multiple times.
|
||||||
|
printer->Print(
|
||||||
|
"$adddescriptorsname$();\n",
|
||||||
|
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
|
||||||
|
|
||||||
|
// Get the file's descriptor from the pool.
|
||||||
|
printer->Print(
|
||||||
|
"const ::google::protobuf::FileDescriptor* file =\n"
|
||||||
|
" ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
|
||||||
|
" \"$filename$\");\n"
|
||||||
|
// Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
|
||||||
|
// being unused when compiling an empty .proto file.
|
||||||
|
"GOOGLE_CHECK(file != NULL);\n",
|
||||||
|
"filename", file_->name());
|
||||||
|
|
||||||
|
// Go through all the stuff defined in this file and generated code to
|
||||||
|
// assign the global descriptor pointers based on the file descriptor.
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
|
message_generators_[i]->GenerateDescriptorInitializer(printer, i);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||||
|
enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
|
||||||
|
}
|
||||||
|
if (HasGenericServices(file_)) {
|
||||||
|
for (int i = 0; i < file_->service_count(); i++) {
|
||||||
|
service_generators_[i]->GenerateDescriptorInitializer(printer, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print(
|
||||||
|
"}\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
// protobuf_AssignDescriptorsOnce(): The first time it is called, calls
|
||||||
|
// AssignDescriptors(). All later times, waits for the first call to
|
||||||
|
// complete and then returns.
|
||||||
|
printer->Print(
|
||||||
|
"namespace {\n"
|
||||||
|
"\n"
|
||||||
|
"GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
|
||||||
|
"inline void protobuf_AssignDescriptorsOnce() {\n"
|
||||||
|
" ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
|
||||||
|
" &$assigndescriptorsname$);\n"
|
||||||
|
"}\n"
|
||||||
|
"\n",
|
||||||
|
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
|
||||||
|
|
||||||
|
// protobuf_RegisterTypes(): Calls
|
||||||
|
// MessageFactory::InternalRegisterGeneratedType() for each message type.
|
||||||
|
printer->Print(
|
||||||
|
"void protobuf_RegisterTypes(const ::std::string&) {\n"
|
||||||
|
" protobuf_AssignDescriptorsOnce();\n");
|
||||||
|
printer->Indent();
|
||||||
|
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
|
message_generators_[i]->GenerateTypeRegistrations(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print(
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"} // namespace\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
// ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown.
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"void $shutdownfilename$() {\n",
|
||||||
|
"shutdownfilename", GlobalShutdownFileName(file_->name()));
|
||||||
|
printer->Indent();
|
||||||
|
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
|
message_generators_[i]->GenerateShutdownCode(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print(
|
||||||
|
"}\n");
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
// Now generate the AddDescriptors() function.
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"void $adddescriptorsname$() {\n"
|
||||||
|
// We don't need any special synchronization here because this code is
|
||||||
|
// called at static init time before any threads exist.
|
||||||
|
" static bool already_here = false;\n"
|
||||||
|
" if (already_here) return;\n"
|
||||||
|
" already_here = true;\n"
|
||||||
|
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
|
||||||
|
"\n",
|
||||||
|
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
|
||||||
|
printer->Indent();
|
||||||
|
|
||||||
|
// Call the AddDescriptors() methods for all of our dependencies, to make
|
||||||
|
// sure they get added first.
|
||||||
|
for (int i = 0; i < file_->dependency_count(); i++) {
|
||||||
|
const FileDescriptor* dependency = file_->dependency(i);
|
||||||
|
// Print the namespace prefix for the dependency.
|
||||||
|
vector<string> dependency_package_parts;
|
||||||
|
SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
|
||||||
|
printer->Print("::");
|
||||||
|
for (int i = 0; i < dependency_package_parts.size(); i++) {
|
||||||
|
printer->Print("$name$::",
|
||||||
|
"name", dependency_package_parts[i]);
|
||||||
|
}
|
||||||
|
// Call its AddDescriptors function.
|
||||||
|
printer->Print(
|
||||||
|
"$name$();\n",
|
||||||
|
"name", GlobalAddDescriptorsName(dependency->name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasDescriptorMethods(file_)) {
|
||||||
|
// Embed the descriptor. We simply serialize the entire FileDescriptorProto
|
||||||
|
// and embed it as a string literal, which is parsed and built into real
|
||||||
|
// descriptors at initialization time.
|
||||||
|
FileDescriptorProto file_proto;
|
||||||
|
file_->CopyTo(&file_proto);
|
||||||
|
string file_data;
|
||||||
|
file_proto.SerializeToString(&file_data);
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
|
||||||
|
|
||||||
|
// Only write 40 bytes per line.
|
||||||
|
static const int kBytesPerLine = 40;
|
||||||
|
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
|
||||||
|
printer->Print("\n \"$data$\"",
|
||||||
|
"data", EscapeTrigraphs(CEscape(file_data.substr(i, kBytesPerLine))));
|
||||||
|
}
|
||||||
|
printer->Print(
|
||||||
|
", $size$);\n",
|
||||||
|
"size", SimpleItoa(file_data.size()));
|
||||||
|
|
||||||
|
// Call MessageFactory::InternalRegisterGeneratedFile().
|
||||||
|
printer->Print(
|
||||||
|
"::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
|
||||||
|
" \"$filename$\", &protobuf_RegisterTypes);\n",
|
||||||
|
"filename", file_->name());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate and initialize default instances. This can't be done lazily
|
||||||
|
// since default instances are returned by simple accessors and are used with
|
||||||
|
// extensions. Speaking of which, we also register extensions at this time.
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
|
message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < file_->extension_count(); i++) {
|
||||||
|
extension_generators_[i]->GenerateRegistration(printer);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||||
|
message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
|
||||||
|
"shutdownfilename", GlobalShutdownFileName(file_->name()));
|
||||||
|
|
||||||
|
printer->Outdent();
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"// Force AddDescriptors() to be called at static initialization time.\n"
|
||||||
|
"struct StaticDescriptorInitializer_$filename$ {\n"
|
||||||
|
" StaticDescriptorInitializer_$filename$() {\n"
|
||||||
|
" $adddescriptorsname$();\n"
|
||||||
|
" }\n"
|
||||||
|
"} static_descriptor_initializer_$filename$_;\n"
|
||||||
|
"\n",
|
||||||
|
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
|
||||||
|
"filename", FilenameIdentifier(file_->name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
|
||||||
|
if (package_parts_.size() > 0) printer->Print("\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < package_parts_.size(); i++) {
|
||||||
|
printer->Print("namespace $part$ {\n",
|
||||||
|
"part", package_parts_[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
|
||||||
|
if (package_parts_.size() > 0) printer->Print("\n");
|
||||||
|
|
||||||
|
for (int i = package_parts_.size() - 1; i >= 0; i--) {
|
||||||
|
printer->Print("} // namespace $part$\n",
|
||||||
|
"part", package_parts_[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,122 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_generator.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_file.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
CppGenerator::CppGenerator() {}
|
||||||
|
CppGenerator::~CppGenerator() {}
|
||||||
|
|
||||||
|
bool CppGenerator::Generate(const FileDescriptor* file,
|
||||||
|
const string& parameter,
|
||||||
|
GeneratorContext* generator_context,
|
||||||
|
string* error) const {
|
||||||
|
vector<pair<string, string> > options;
|
||||||
|
ParseGeneratorParameter(parameter, &options);
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// parse generator options
|
||||||
|
|
||||||
|
// TODO(kenton): If we ever have more options, we may want to create a
|
||||||
|
// class that encapsulates them which we can pass down to all the
|
||||||
|
// generator classes. Currently we pass dllexport_decl down to all of
|
||||||
|
// them via the constructors, but we don't want to have to add another
|
||||||
|
// constructor parameter for every option.
|
||||||
|
|
||||||
|
// If the dllexport_decl option is passed to the compiler, we need to write
|
||||||
|
// it in front of every symbol that should be exported if this .proto is
|
||||||
|
// compiled into a Windows DLL. E.g., if the user invokes the protocol
|
||||||
|
// compiler as:
|
||||||
|
// protoc --cpp_out=dllexport_decl=FOO_EXPORT:outdir foo.proto
|
||||||
|
// then we'll define classes like this:
|
||||||
|
// class FOO_EXPORT Foo {
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
// FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
|
||||||
|
// __declspec(dllimport) depending on what is being compiled.
|
||||||
|
string dllexport_decl;
|
||||||
|
|
||||||
|
for (int i = 0; i < options.size(); i++) {
|
||||||
|
if (options[i].first == "dllexport_decl") {
|
||||||
|
dllexport_decl = options[i].second;
|
||||||
|
} else {
|
||||||
|
*error = "Unknown generator option: " + options[i].first;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
string basename = StripProto(file->name());
|
||||||
|
basename.append(".pb");
|
||||||
|
|
||||||
|
FileGenerator file_generator(file, dllexport_decl);
|
||||||
|
|
||||||
|
// Generate header.
|
||||||
|
{
|
||||||
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
|
generator_context->Open(basename + ".h"));
|
||||||
|
io::Printer printer(output.get(), '$');
|
||||||
|
file_generator.GenerateHeader(&printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate cc file.
|
||||||
|
{
|
||||||
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
|
generator_context->Open(basename + ".cc"));
|
||||||
|
io::Printer printer(output.get(), '$');
|
||||||
|
file_generator.GenerateSource(&printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,347 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
#include <google/protobuf/stubs/hash.h>
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
#include <google/protobuf/stubs/substitute.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
string DotsToUnderscores(const string& name) {
|
||||||
|
return StringReplace(name, ".", "_", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
string DotsToColons(const string& name) {
|
||||||
|
return StringReplace(name, ".", "::", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* const kKeywordList[] = {
|
||||||
|
"and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case",
|
||||||
|
"catch", "char", "class", "compl", "const", "const_cast", "continue",
|
||||||
|
"default", "delete", "do", "double", "dynamic_cast", "else", "enum",
|
||||||
|
"explicit", "extern", "false", "float", "for", "friend", "goto", "if",
|
||||||
|
"inline", "int", "long", "mutable", "namespace", "new", "not", "not_eq",
|
||||||
|
"operator", "or", "or_eq", "private", "protected", "public", "register",
|
||||||
|
"reinterpret_cast", "return", "short", "signed", "sizeof", "static",
|
||||||
|
"static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
|
||||||
|
"typedef", "typeid", "typename", "union", "unsigned", "using", "virtual",
|
||||||
|
"void", "volatile", "wchar_t", "while", "xor", "xor_eq"
|
||||||
|
};
|
||||||
|
|
||||||
|
hash_set<string> MakeKeywordsMap() {
|
||||||
|
hash_set<string> result;
|
||||||
|
for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); i++) {
|
||||||
|
result.insert(kKeywordList[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_set<string> kKeywords = MakeKeywordsMap();
|
||||||
|
|
||||||
|
string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
|
||||||
|
string result;
|
||||||
|
// Note: I distrust ctype.h due to locales.
|
||||||
|
for (int i = 0; i < input.size(); i++) {
|
||||||
|
if ('a' <= input[i] && input[i] <= 'z') {
|
||||||
|
if (cap_next_letter) {
|
||||||
|
result += input[i] + ('A' - 'a');
|
||||||
|
} else {
|
||||||
|
result += input[i];
|
||||||
|
}
|
||||||
|
cap_next_letter = false;
|
||||||
|
} else if ('A' <= input[i] && input[i] <= 'Z') {
|
||||||
|
// Capital letters are left as-is.
|
||||||
|
result += input[i];
|
||||||
|
cap_next_letter = false;
|
||||||
|
} else if ('0' <= input[i] && input[i] <= '9') {
|
||||||
|
result += input[i];
|
||||||
|
cap_next_letter = true;
|
||||||
|
} else {
|
||||||
|
cap_next_letter = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
const char kThickSeparator[] =
|
||||||
|
"// ===================================================================\n";
|
||||||
|
const char kThinSeparator[] =
|
||||||
|
"// -------------------------------------------------------------------\n";
|
||||||
|
|
||||||
|
string ClassName(const Descriptor* descriptor, bool qualified) {
|
||||||
|
|
||||||
|
// Find "outer", the descriptor of the top-level message in which
|
||||||
|
// "descriptor" is embedded.
|
||||||
|
const Descriptor* outer = descriptor;
|
||||||
|
while (outer->containing_type() != NULL) outer = outer->containing_type();
|
||||||
|
|
||||||
|
const string& outer_name = outer->full_name();
|
||||||
|
string inner_name = descriptor->full_name().substr(outer_name.size());
|
||||||
|
|
||||||
|
if (qualified) {
|
||||||
|
return "::" + DotsToColons(outer_name) + DotsToUnderscores(inner_name);
|
||||||
|
} else {
|
||||||
|
return outer->name() + DotsToUnderscores(inner_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
|
||||||
|
if (enum_descriptor->containing_type() == NULL) {
|
||||||
|
if (qualified) {
|
||||||
|
return DotsToColons(enum_descriptor->full_name());
|
||||||
|
} else {
|
||||||
|
return enum_descriptor->name();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
string result = ClassName(enum_descriptor->containing_type(), qualified);
|
||||||
|
result += '_';
|
||||||
|
result += enum_descriptor->name();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string SuperClassName(const Descriptor* descriptor) {
|
||||||
|
return HasDescriptorMethods(descriptor->file()) ?
|
||||||
|
"::google::protobuf::Message" : "::google::protobuf::MessageLite";
|
||||||
|
}
|
||||||
|
|
||||||
|
string FieldName(const FieldDescriptor* field) {
|
||||||
|
string result = field->name();
|
||||||
|
LowerString(&result);
|
||||||
|
if (kKeywords.count(result) > 0) {
|
||||||
|
result.append("_");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
string FieldConstantName(const FieldDescriptor *field) {
|
||||||
|
string field_name = UnderscoresToCamelCase(field->name(), true);
|
||||||
|
string result = "k" + field_name + "FieldNumber";
|
||||||
|
|
||||||
|
if (!field->is_extension() &&
|
||||||
|
field->containing_type()->FindFieldByCamelcaseName(
|
||||||
|
field->camelcase_name()) != field) {
|
||||||
|
// This field's camelcase name is not unique. As a hack, add the field
|
||||||
|
// number to the constant name. This makes the constant rather useless,
|
||||||
|
// but what can we do?
|
||||||
|
result += "_" + SimpleItoa(field->number());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
string FieldMessageTypeName(const FieldDescriptor* field) {
|
||||||
|
// Note: The Google-internal version of Protocol Buffers uses this function
|
||||||
|
// as a hook point for hacks to support legacy code.
|
||||||
|
return ClassName(field->message_type(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
string StripProto(const string& filename) {
|
||||||
|
if (HasSuffixString(filename, ".protodevel")) {
|
||||||
|
return StripSuffixString(filename, ".protodevel");
|
||||||
|
} else {
|
||||||
|
return StripSuffixString(filename, ".proto");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* PrimitiveTypeName(FieldDescriptor::CppType type) {
|
||||||
|
switch (type) {
|
||||||
|
case FieldDescriptor::CPPTYPE_INT32 : return "::google::protobuf::int32";
|
||||||
|
case FieldDescriptor::CPPTYPE_INT64 : return "::google::protobuf::int64";
|
||||||
|
case FieldDescriptor::CPPTYPE_UINT32 : return "::google::protobuf::uint32";
|
||||||
|
case FieldDescriptor::CPPTYPE_UINT64 : return "::google::protobuf::uint64";
|
||||||
|
case FieldDescriptor::CPPTYPE_DOUBLE : return "double";
|
||||||
|
case FieldDescriptor::CPPTYPE_FLOAT : return "float";
|
||||||
|
case FieldDescriptor::CPPTYPE_BOOL : return "bool";
|
||||||
|
case FieldDescriptor::CPPTYPE_ENUM : return "int";
|
||||||
|
case FieldDescriptor::CPPTYPE_STRING : return "::std::string";
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE: return NULL;
|
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// CppTypes are added.
|
||||||
|
}
|
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
|
||||||
|
switch (type) {
|
||||||
|
case FieldDescriptor::TYPE_INT32 : return "Int32";
|
||||||
|
case FieldDescriptor::TYPE_INT64 : return "Int64";
|
||||||
|
case FieldDescriptor::TYPE_UINT32 : return "UInt32";
|
||||||
|
case FieldDescriptor::TYPE_UINT64 : return "UInt64";
|
||||||
|
case FieldDescriptor::TYPE_SINT32 : return "SInt32";
|
||||||
|
case FieldDescriptor::TYPE_SINT64 : return "SInt64";
|
||||||
|
case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
|
||||||
|
case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
|
||||||
|
case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
|
||||||
|
case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
|
||||||
|
case FieldDescriptor::TYPE_FLOAT : return "Float";
|
||||||
|
case FieldDescriptor::TYPE_DOUBLE : return "Double";
|
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_BOOL : return "Bool";
|
||||||
|
case FieldDescriptor::TYPE_ENUM : return "Enum";
|
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_STRING : return "String";
|
||||||
|
case FieldDescriptor::TYPE_BYTES : return "Bytes";
|
||||||
|
case FieldDescriptor::TYPE_GROUP : return "Group";
|
||||||
|
case FieldDescriptor::TYPE_MESSAGE : return "Message";
|
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// types are added.
|
||||||
|
}
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string DefaultValue(const FieldDescriptor* field) {
|
||||||
|
switch (field->cpp_type()) {
|
||||||
|
case FieldDescriptor::CPPTYPE_INT32:
|
||||||
|
return SimpleItoa(field->default_value_int32());
|
||||||
|
case FieldDescriptor::CPPTYPE_UINT32:
|
||||||
|
return SimpleItoa(field->default_value_uint32()) + "u";
|
||||||
|
case FieldDescriptor::CPPTYPE_INT64:
|
||||||
|
return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")";
|
||||||
|
case FieldDescriptor::CPPTYPE_UINT64:
|
||||||
|
return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
|
||||||
|
case FieldDescriptor::CPPTYPE_DOUBLE: {
|
||||||
|
double value = field->default_value_double();
|
||||||
|
if (value == numeric_limits<double>::infinity()) {
|
||||||
|
return "::google::protobuf::internal::Infinity()";
|
||||||
|
} else if (value == -numeric_limits<double>::infinity()) {
|
||||||
|
return "-::google::protobuf::internal::Infinity()";
|
||||||
|
} else if (value != value) {
|
||||||
|
return "::google::protobuf::internal::NaN()";
|
||||||
|
} else {
|
||||||
|
return SimpleDtoa(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||||
|
{
|
||||||
|
float value = field->default_value_float();
|
||||||
|
if (value == numeric_limits<float>::infinity()) {
|
||||||
|
return "static_cast<float>(::google::protobuf::internal::Infinity())";
|
||||||
|
} else if (value == -numeric_limits<float>::infinity()) {
|
||||||
|
return "static_cast<float>(-::google::protobuf::internal::Infinity())";
|
||||||
|
} else if (value != value) {
|
||||||
|
return "static_cast<float>(::google::protobuf::internal::NaN())";
|
||||||
|
} else {
|
||||||
|
string float_value = SimpleFtoa(value);
|
||||||
|
// If floating point value contains a period (.) or an exponent
|
||||||
|
// (either E or e), then append suffix 'f' to make it a float
|
||||||
|
// literal.
|
||||||
|
if (float_value.find_first_of(".eE") != string::npos) {
|
||||||
|
float_value.push_back('f');
|
||||||
|
}
|
||||||
|
return float_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case FieldDescriptor::CPPTYPE_BOOL:
|
||||||
|
return field->default_value_bool() ? "true" : "false";
|
||||||
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
|
// Lazy: Generate a static_cast because we don't have a helper function
|
||||||
|
// that constructs the full name of an enum value.
|
||||||
|
return strings::Substitute(
|
||||||
|
"static_cast< $0 >($1)",
|
||||||
|
ClassName(field->enum_type(), true),
|
||||||
|
field->default_value_enum()->number());
|
||||||
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
|
return "\"" + EscapeTrigraphs(CEscape(field->default_value_string())) +
|
||||||
|
"\"";
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
|
return FieldMessageTypeName(field) + "::default_instance()";
|
||||||
|
}
|
||||||
|
// Can't actually get here; make compiler happy. (We could add a default
|
||||||
|
// case above but then we wouldn't get the nice compiler warning when a
|
||||||
|
// new type is added.)
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a file name into a valid identifier.
|
||||||
|
string FilenameIdentifier(const string& filename) {
|
||||||
|
string result;
|
||||||
|
for (int i = 0; i < filename.size(); i++) {
|
||||||
|
if (ascii_isalnum(filename[i])) {
|
||||||
|
result.push_back(filename[i]);
|
||||||
|
} else {
|
||||||
|
// Not alphanumeric. To avoid any possibility of name conflicts we
|
||||||
|
// use the hex code for the character.
|
||||||
|
result.push_back('_');
|
||||||
|
char buffer[kFastToBufferSize];
|
||||||
|
result.append(FastHexToBuffer(static_cast<uint8>(filename[i]), buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the name of the AddDescriptors() function for a given file.
|
||||||
|
string GlobalAddDescriptorsName(const string& filename) {
|
||||||
|
return "protobuf_AddDesc_" + FilenameIdentifier(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the name of the AssignDescriptors() function for a given file.
|
||||||
|
string GlobalAssignDescriptorsName(const string& filename) {
|
||||||
|
return "protobuf_AssignDesc_" + FilenameIdentifier(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the name of the ShutdownFile() function for a given file.
|
||||||
|
string GlobalShutdownFileName(const string& filename) {
|
||||||
|
return "protobuf_ShutdownFile_" + FilenameIdentifier(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escape C++ trigraphs by escaping question marks to \?
|
||||||
|
string EscapeTrigraphs(const string& to_escape) {
|
||||||
|
return StringReplace(to_escape, "?", "\\?", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,159 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
// Commonly-used separator comments. Thick is a line of '=', thin is a line
|
||||||
|
// of '-'.
|
||||||
|
extern const char kThickSeparator[];
|
||||||
|
extern const char kThinSeparator[];
|
||||||
|
|
||||||
|
// Returns the non-nested type name for the given type. If "qualified" is
|
||||||
|
// true, prefix the type with the full namespace. For example, if you had:
|
||||||
|
// package foo.bar;
|
||||||
|
// message Baz { message Qux {} }
|
||||||
|
// Then the qualified ClassName for Qux would be:
|
||||||
|
// ::foo::bar::Baz_Qux
|
||||||
|
// While the non-qualified version would be:
|
||||||
|
// Baz_Qux
|
||||||
|
string ClassName(const Descriptor* descriptor, bool qualified);
|
||||||
|
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
|
||||||
|
|
||||||
|
string SuperClassName(const Descriptor* descriptor);
|
||||||
|
|
||||||
|
// Get the (unqualified) name that should be used for this field in C++ code.
|
||||||
|
// The name is coerced to lower-case to emulate proto1 behavior. People
|
||||||
|
// should be using lowercase-with-underscores style for proto field names
|
||||||
|
// anyway, so normally this just returns field->name().
|
||||||
|
string FieldName(const FieldDescriptor* field);
|
||||||
|
|
||||||
|
// Get the unqualified name that should be used for a field's field
|
||||||
|
// number constant.
|
||||||
|
string FieldConstantName(const FieldDescriptor *field);
|
||||||
|
|
||||||
|
// Returns the scope where the field was defined (for extensions, this is
|
||||||
|
// different from the message type to which the field applies).
|
||||||
|
inline const Descriptor* FieldScope(const FieldDescriptor* field) {
|
||||||
|
return field->is_extension() ?
|
||||||
|
field->extension_scope() : field->containing_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the fully-qualified type name field->message_type(). Usually this
|
||||||
|
// is just ClassName(field->message_type(), true);
|
||||||
|
string FieldMessageTypeName(const FieldDescriptor* field);
|
||||||
|
|
||||||
|
// Strips ".proto" or ".protodevel" from the end of a filename.
|
||||||
|
string StripProto(const string& filename);
|
||||||
|
|
||||||
|
// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
|
||||||
|
// Note: non-built-in type names will be qualified, meaning they will start
|
||||||
|
// with a ::. If you are using the type as a template parameter, you will
|
||||||
|
// need to insure there is a space between the < and the ::, because the
|
||||||
|
// ridiculous C++ standard defines "<:" to be a synonym for "[".
|
||||||
|
const char* PrimitiveTypeName(FieldDescriptor::CppType type);
|
||||||
|
|
||||||
|
// Get the declared type name in CamelCase format, as is used e.g. for the
|
||||||
|
// methods of WireFormat. For example, TYPE_INT32 becomes "Int32".
|
||||||
|
const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
|
||||||
|
|
||||||
|
// Get code that evaluates to the field's default value.
|
||||||
|
string DefaultValue(const FieldDescriptor* field);
|
||||||
|
|
||||||
|
// Convert a file name into a valid identifier.
|
||||||
|
string FilenameIdentifier(const string& filename);
|
||||||
|
|
||||||
|
// Return the name of the AddDescriptors() function for a given file.
|
||||||
|
string GlobalAddDescriptorsName(const string& filename);
|
||||||
|
|
||||||
|
// Return the name of the AssignDescriptors() function for a given file.
|
||||||
|
string GlobalAssignDescriptorsName(const string& filename);
|
||||||
|
|
||||||
|
// Return the name of the ShutdownFile() function for a given file.
|
||||||
|
string GlobalShutdownFileName(const string& filename);
|
||||||
|
|
||||||
|
// Escape C++ trigraphs by escaping question marks to \?
|
||||||
|
string EscapeTrigraphs(const string& to_escape);
|
||||||
|
|
||||||
|
// Do message classes in this file keep track of unknown fields?
|
||||||
|
inline bool HasUnknownFields(const FileDescriptor *file) {
|
||||||
|
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does this file have generated parsing, serialization, and other
|
||||||
|
// standard methods for which reflection-based fallback implementations exist?
|
||||||
|
inline bool HasGeneratedMethods(const FileDescriptor *file) {
|
||||||
|
return file->options().optimize_for() != FileOptions::CODE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do message classes in this file have descriptor and refelction methods?
|
||||||
|
inline bool HasDescriptorMethods(const FileDescriptor *file) {
|
||||||
|
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should we generate generic services for this file?
|
||||||
|
inline bool HasGenericServices(const FileDescriptor *file) {
|
||||||
|
return file->service_count() > 0 &&
|
||||||
|
file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
|
||||||
|
file->options().cc_generic_services();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should string fields in this file verify that their contents are UTF-8?
|
||||||
|
inline bool HasUtf8Verification(const FileDescriptor* file) {
|
||||||
|
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should we generate a separate, super-optimized code path for serializing to
|
||||||
|
// flat arrays? We don't do this in Lite mode because we'd rather reduce code
|
||||||
|
// size.
|
||||||
|
inline bool HasFastArraySerialization(const FileDescriptor* file) {
|
||||||
|
return file->options().optimize_for() == FileOptions::SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,170 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace io {
|
||||||
|
class Printer; // printer.h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
class EnumGenerator; // enum.h
|
||||||
|
class ExtensionGenerator; // extension.h
|
||||||
|
|
||||||
|
class MessageGenerator {
|
||||||
|
public:
|
||||||
|
// See generator.cc for the meaning of dllexport_decl.
|
||||||
|
explicit MessageGenerator(const Descriptor* descriptor,
|
||||||
|
const string& dllexport_decl);
|
||||||
|
~MessageGenerator();
|
||||||
|
|
||||||
|
// Header stuff.
|
||||||
|
|
||||||
|
// Generate foward declarations for this class and all its nested types.
|
||||||
|
void GenerateForwardDeclaration(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generate definitions of all nested enums (must come before class
|
||||||
|
// definitions because those classes use the enums definitions).
|
||||||
|
void GenerateEnumDefinitions(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generate specializations of GetEnumDescriptor<MyEnum>().
|
||||||
|
// Precondition: in ::google::protobuf namespace.
|
||||||
|
void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generate definitions for this class and all its nested types.
|
||||||
|
void GenerateClassDefinition(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generate definitions of inline methods (placed at the end of the header
|
||||||
|
// file).
|
||||||
|
void GenerateInlineMethods(io::Printer* printer);
|
||||||
|
|
||||||
|
// Source file stuff.
|
||||||
|
|
||||||
|
// Generate code which declares all the global descriptor pointers which
|
||||||
|
// will be initialized by the methods below.
|
||||||
|
void GenerateDescriptorDeclarations(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generate code that initializes the global variable storing the message's
|
||||||
|
// descriptor.
|
||||||
|
void GenerateDescriptorInitializer(io::Printer* printer, int index);
|
||||||
|
|
||||||
|
// Generate code that calls MessageFactory::InternalRegisterGeneratedMessage()
|
||||||
|
// for all types.
|
||||||
|
void GenerateTypeRegistrations(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generates code that allocates the message's default instance.
|
||||||
|
void GenerateDefaultInstanceAllocator(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generates code that initializes the message's default instance. This
|
||||||
|
// is separate from allocating because all default instances must be
|
||||||
|
// allocated before any can be initialized.
|
||||||
|
void GenerateDefaultInstanceInitializer(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generates code that should be run when ShutdownProtobufLibrary() is called,
|
||||||
|
// to delete all dynamically-allocated objects.
|
||||||
|
void GenerateShutdownCode(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generate all non-inline methods for this class.
|
||||||
|
void GenerateClassMethods(io::Printer* printer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Generate declarations and definitions of accessors for fields.
|
||||||
|
void GenerateFieldAccessorDeclarations(io::Printer* printer);
|
||||||
|
void GenerateFieldAccessorDefinitions(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generate the field offsets array.
|
||||||
|
void GenerateOffsets(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generate constructors and destructor.
|
||||||
|
void GenerateStructors(io::Printer* printer);
|
||||||
|
|
||||||
|
// The compiler typically generates multiple copies of each constructor and
|
||||||
|
// destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx
|
||||||
|
// Placing common code in a separate method reduces the generated code size.
|
||||||
|
//
|
||||||
|
// Generate the shared constructor code.
|
||||||
|
void GenerateSharedConstructorCode(io::Printer* printer);
|
||||||
|
// Generate the shared destructor code.
|
||||||
|
void GenerateSharedDestructorCode(io::Printer* printer);
|
||||||
|
|
||||||
|
// Generate standard Message methods.
|
||||||
|
void GenerateClear(io::Printer* printer);
|
||||||
|
void GenerateMergeFromCodedStream(io::Printer* printer);
|
||||||
|
void GenerateSerializeWithCachedSizes(io::Printer* printer);
|
||||||
|
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer);
|
||||||
|
void GenerateSerializeWithCachedSizesBody(io::Printer* printer,
|
||||||
|
bool to_array);
|
||||||
|
void GenerateByteSize(io::Printer* printer);
|
||||||
|
void GenerateMergeFrom(io::Printer* printer);
|
||||||
|
void GenerateCopyFrom(io::Printer* printer);
|
||||||
|
void GenerateSwap(io::Printer* printer);
|
||||||
|
void GenerateIsInitialized(io::Printer* printer);
|
||||||
|
|
||||||
|
// Helpers for GenerateSerializeWithCachedSizes().
|
||||||
|
void GenerateSerializeOneField(io::Printer* printer,
|
||||||
|
const FieldDescriptor* field,
|
||||||
|
bool unbounded);
|
||||||
|
void GenerateSerializeOneExtensionRange(
|
||||||
|
io::Printer* printer, const Descriptor::ExtensionRange* range,
|
||||||
|
bool unbounded);
|
||||||
|
|
||||||
|
|
||||||
|
const Descriptor* descriptor_;
|
||||||
|
string classname_;
|
||||||
|
string dllexport_decl_;
|
||||||
|
FieldGeneratorMap field_generators_;
|
||||||
|
scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
|
||||||
|
scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
|
||||||
|
scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
|
@ -0,0 +1,277 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void SetMessageVariables(const FieldDescriptor* descriptor,
|
||||||
|
map<string, string>* variables) {
|
||||||
|
SetCommonFieldVariables(descriptor, variables);
|
||||||
|
(*variables)["type"] = FieldMessageTypeName(descriptor);
|
||||||
|
(*variables)["stream_writer"] = (*variables)["declared_type"] +
|
||||||
|
(HasFastArraySerialization(descriptor->message_type()->file()) ?
|
||||||
|
"MaybeToArray" :
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
MessageFieldGenerator::
|
||||||
|
MessageFieldGenerator(const FieldDescriptor* descriptor)
|
||||||
|
: descriptor_(descriptor) {
|
||||||
|
SetMessageVariables(descriptor, &variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageFieldGenerator::~MessageFieldGenerator() {}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GeneratePrivateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$type$* $name$_;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const $type$& $name$() const$deprecation$;\n"
|
||||||
|
"inline $type$* mutable_$name$()$deprecation$;\n"
|
||||||
|
"inline $type$* release_$name$()$deprecation$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const $type$& $classname$::$name$() const {\n"
|
||||||
|
" return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline $type$* $classname$::mutable_$name$() {\n"
|
||||||
|
" set_has_$name$();\n"
|
||||||
|
" if ($name$_ == NULL) $name$_ = new $type$;\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline $type$* $classname$::release_$name$() {\n"
|
||||||
|
" clear_has_$name$();\n"
|
||||||
|
" $type$* temp = $name$_;\n"
|
||||||
|
" $name$_ = NULL;\n"
|
||||||
|
" return temp;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateClearingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($name$_ != NULL) $name$_->$type$::Clear();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateSwappingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateConstructorCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = NULL;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||||
|
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
|
||||||
|
" input, mutable_$name$()));\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
|
||||||
|
" $number$, input, mutable_$name$()));\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
|
||||||
|
" $number$, this->$name$(), output);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||||
|
" Write$declared_type$NoVirtualToArray(\n"
|
||||||
|
" $number$, this->$name$(), target);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFieldGenerator::
|
||||||
|
GenerateByteSize(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"total_size += $tag_size$ +\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
|
||||||
|
" this->$name$());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
RepeatedMessageFieldGenerator::
|
||||||
|
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
|
||||||
|
: descriptor_(descriptor) {
|
||||||
|
SetMessageVariables(descriptor, &variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GeneratePrivateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const $type$& $name$(int index) const$deprecation$;\n"
|
||||||
|
"inline $type$* mutable_$name$(int index)$deprecation$;\n"
|
||||||
|
"inline $type$* add_$name$()$deprecation$;\n");
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
|
||||||
|
" $name$() const$deprecation$;\n"
|
||||||
|
"inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
|
||||||
|
" mutable_$name$()$deprecation$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const $type$& $classname$::$name$(int index) const {\n"
|
||||||
|
" return $name$_.Get(index);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline $type$* $classname$::mutable_$name$(int index) {\n"
|
||||||
|
" return $name$_.Mutable(index);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline $type$* $classname$::add_$name$() {\n"
|
||||||
|
" return $name$_.Add();\n"
|
||||||
|
"}\n");
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
|
||||||
|
"$classname$::$name$() const {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
|
||||||
|
"$classname$::mutable_$name$() {\n"
|
||||||
|
" return &$name$_;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateClearingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_.Clear();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateSwappingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateConstructorCode(io::Printer* printer) const {
|
||||||
|
// Not needed for repeated fields.
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||||
|
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
|
||||||
|
" input, add_$name$()));\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
|
||||||
|
" $number$, input, add_$name$()));\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
|
||||||
|
" $number$, this->$name$(i), output);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||||
|
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||||
|
" Write$declared_type$NoVirtualToArray(\n"
|
||||||
|
" $number$, this->$name$(i), target);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator::
|
||||||
|
GenerateByteSize(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"total_size += $tag_size$ * this->$name$_size();\n"
|
||||||
|
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||||
|
" total_size +=\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
|
||||||
|
" this->$name$(i));\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,102 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
class MessageFieldGenerator : public FieldGenerator {
|
||||||
|
public:
|
||||||
|
explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
|
||||||
|
~MessageFieldGenerator();
|
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||||
|
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||||
|
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||||
|
void GenerateClearingCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
|
void GenerateSwappingCode(io::Printer* printer) const;
|
||||||
|
void GenerateConstructorCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||||
|
void GenerateByteSize(io::Printer* printer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const FieldDescriptor* descriptor_;
|
||||||
|
map<string, string> variables_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
class RepeatedMessageFieldGenerator : public FieldGenerator {
|
||||||
|
public:
|
||||||
|
explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
|
||||||
|
~RepeatedMessageFieldGenerator();
|
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||||
|
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||||
|
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||||
|
void GenerateClearingCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
|
void GenerateSwappingCode(io::Printer* printer) const;
|
||||||
|
void GenerateConstructorCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||||
|
void GenerateByteSize(io::Printer* printer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const FieldDescriptor* descriptor_;
|
||||||
|
map<string, string> variables_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
|
@ -0,0 +1,382 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/wire_format.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
using internal::WireFormatLite;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// For encodings with fixed sizes, returns that size in bytes. Otherwise
|
||||||
|
// returns -1.
|
||||||
|
int FixedSize(FieldDescriptor::Type type) {
|
||||||
|
switch (type) {
|
||||||
|
case FieldDescriptor::TYPE_INT32 : return -1;
|
||||||
|
case FieldDescriptor::TYPE_INT64 : return -1;
|
||||||
|
case FieldDescriptor::TYPE_UINT32 : return -1;
|
||||||
|
case FieldDescriptor::TYPE_UINT64 : return -1;
|
||||||
|
case FieldDescriptor::TYPE_SINT32 : return -1;
|
||||||
|
case FieldDescriptor::TYPE_SINT64 : return -1;
|
||||||
|
case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
|
||||||
|
case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
|
||||||
|
case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
|
||||||
|
case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
|
||||||
|
case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
|
||||||
|
case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
|
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
|
||||||
|
case FieldDescriptor::TYPE_ENUM : return -1;
|
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_STRING : return -1;
|
||||||
|
case FieldDescriptor::TYPE_BYTES : return -1;
|
||||||
|
case FieldDescriptor::TYPE_GROUP : return -1;
|
||||||
|
case FieldDescriptor::TYPE_MESSAGE : return -1;
|
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// types are added.
|
||||||
|
}
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
|
||||||
|
map<string, string>* variables) {
|
||||||
|
SetCommonFieldVariables(descriptor, variables);
|
||||||
|
(*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
|
||||||
|
(*variables)["default"] = DefaultValue(descriptor);
|
||||||
|
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
|
||||||
|
int fixed_size = FixedSize(descriptor->type());
|
||||||
|
if (fixed_size != -1) {
|
||||||
|
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
|
||||||
|
}
|
||||||
|
(*variables)["wire_format_field_type"] =
|
||||||
|
"::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name(
|
||||||
|
static_cast<FieldDescriptorProto_Type>(descriptor->type()));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
PrimitiveFieldGenerator::
|
||||||
|
PrimitiveFieldGenerator(const FieldDescriptor* descriptor)
|
||||||
|
: descriptor_(descriptor) {
|
||||||
|
SetPrimitiveVariables(descriptor, &variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GeneratePrivateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$type$ $name$_;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline $type$ $name$() const$deprecation$;\n"
|
||||||
|
"inline void set_$name$($type$ value)$deprecation$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline $type$ $classname$::$name$() const {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::set_$name$($type$ value) {\n"
|
||||||
|
" set_has_$name$();\n"
|
||||||
|
" $name$_ = value;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateClearingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "set_$name$(from.$name$());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateSwappingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateConstructorCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||||
|
" $type$, $wire_format_field_type$>(\n"
|
||||||
|
" input, &$name$_)));\n"
|
||||||
|
"set_has_$name$();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::internal::WireFormatLite::Write$declared_type$("
|
||||||
|
"$number$, this->$name$(), output);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray("
|
||||||
|
"$number$, this->$name$(), target);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimitiveFieldGenerator::
|
||||||
|
GenerateByteSize(io::Printer* printer) const {
|
||||||
|
int fixed_size = FixedSize(descriptor_->type());
|
||||||
|
if (fixed_size == -1) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"total_size += $tag_size$ +\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||||
|
" this->$name$());\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"total_size += $tag_size$ + $fixed_size$;\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
RepeatedPrimitiveFieldGenerator::
|
||||||
|
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor)
|
||||||
|
: descriptor_(descriptor) {
|
||||||
|
SetPrimitiveVariables(descriptor, &variables_);
|
||||||
|
|
||||||
|
if (descriptor->options().packed()) {
|
||||||
|
variables_["packed_reader"] = "ReadPackedPrimitive";
|
||||||
|
variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
|
||||||
|
} else {
|
||||||
|
variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
|
||||||
|
variables_["repeated_reader"] = "ReadRepeatedPrimitive";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GeneratePrivateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::RepeatedField< $type$ > $name$_;\n");
|
||||||
|
if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"mutable int _$name$_cached_byte_size_;\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline $type$ $name$(int index) const$deprecation$;\n"
|
||||||
|
"inline void set_$name$(int index, $type$ value)$deprecation$;\n"
|
||||||
|
"inline void add_$name$($type$ value)$deprecation$;\n");
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const ::google::protobuf::RepeatedField< $type$ >&\n"
|
||||||
|
" $name$() const$deprecation$;\n"
|
||||||
|
"inline ::google::protobuf::RepeatedField< $type$ >*\n"
|
||||||
|
" mutable_$name$()$deprecation$;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline $type$ $classname$::$name$(int index) const {\n"
|
||||||
|
" return $name$_.Get(index);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::set_$name$(int index, $type$ value) {\n"
|
||||||
|
" $name$_.Set(index, value);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::add_$name$($type$ value) {\n"
|
||||||
|
" $name$_.Add(value);\n"
|
||||||
|
"}\n");
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const ::google::protobuf::RepeatedField< $type$ >&\n"
|
||||||
|
"$classname$::$name$() const {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline ::google::protobuf::RepeatedField< $type$ >*\n"
|
||||||
|
"$classname$::mutable_$name$() {\n"
|
||||||
|
" return &$name$_;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateClearingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_.Clear();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateSwappingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateConstructorCode(io::Printer* printer) const {
|
||||||
|
// Not needed for repeated fields.
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n"
|
||||||
|
" $type$, $wire_format_field_type$>(\n"
|
||||||
|
" $tag_size$, $tag$, input, this->mutable_$name$())));\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n"
|
||||||
|
" $type$, $wire_format_field_type$>(\n"
|
||||||
|
" input, this->mutable_$name$())));\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
// Write the tag and the size.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (this->$name$_size() > 0) {\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::WriteTag("
|
||||||
|
"$number$, "
|
||||||
|
"::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
|
||||||
|
"output);\n"
|
||||||
|
" output->WriteVarint32(_$name$_cached_byte_size_);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
|
||||||
|
" this->$name$(i), output);\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
|
||||||
|
" $number$, this->$name$(i), output);\n");
|
||||||
|
}
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
// Write the tag and the size.
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (this->$name$_size() > 0) {\n"
|
||||||
|
" target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
|
||||||
|
" $number$,\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
|
||||||
|
" target);\n"
|
||||||
|
" target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
|
||||||
|
" _$name$_cached_byte_size_, target);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||||
|
" Write$declared_type$NoTagToArray(this->$name$(i), target);\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||||
|
" Write$declared_type$ToArray($number$, this->$name$(i), target);\n");
|
||||||
|
}
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator::
|
||||||
|
GenerateByteSize(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"{\n"
|
||||||
|
" int data_size = 0;\n");
|
||||||
|
printer->Indent();
|
||||||
|
int fixed_size = FixedSize(descriptor_->type());
|
||||||
|
if (fixed_size == -1) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||||
|
" data_size += ::google::protobuf::internal::WireFormatLite::\n"
|
||||||
|
" $declared_type$Size(this->$name$(i));\n"
|
||||||
|
"}\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"data_size = $fixed_size$ * this->$name$_size();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descriptor_->options().packed()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if (data_size > 0) {\n"
|
||||||
|
" total_size += $tag_size$ +\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
|
||||||
|
"}\n"
|
||||||
|
"_$name$_cached_byte_size_ = data_size;\n"
|
||||||
|
"total_size += data_size;\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"total_size += $tag_size$ * this->$name$_size() + data_size;\n");
|
||||||
|
}
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,103 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
class PrimitiveFieldGenerator : public FieldGenerator {
|
||||||
|
public:
|
||||||
|
explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
|
||||||
|
~PrimitiveFieldGenerator();
|
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||||
|
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||||
|
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||||
|
void GenerateClearingCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
|
void GenerateSwappingCode(io::Printer* printer) const;
|
||||||
|
void GenerateConstructorCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||||
|
void GenerateByteSize(io::Printer* printer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const FieldDescriptor* descriptor_;
|
||||||
|
map<string, string> variables_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
|
||||||
|
public:
|
||||||
|
explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
|
||||||
|
~RepeatedPrimitiveFieldGenerator();
|
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||||
|
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||||
|
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||||
|
void GenerateClearingCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
|
void GenerateSwappingCode(io::Printer* printer) const;
|
||||||
|
void GenerateConstructorCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||||
|
void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||||
|
void GenerateByteSize(io::Printer* printer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const FieldDescriptor* descriptor_;
|
||||||
|
map<string, string> variables_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
|
@ -0,0 +1,334 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_service.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor,
|
||||||
|
const string& dllexport_decl)
|
||||||
|
: descriptor_(descriptor) {
|
||||||
|
vars_["classname"] = descriptor_->name();
|
||||||
|
vars_["full_name"] = descriptor_->full_name();
|
||||||
|
if (dllexport_decl.empty()) {
|
||||||
|
vars_["dllexport"] = "";
|
||||||
|
} else {
|
||||||
|
vars_["dllexport"] = dllexport_decl + " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceGenerator::~ServiceGenerator() {}
|
||||||
|
|
||||||
|
void ServiceGenerator::GenerateDeclarations(io::Printer* printer) {
|
||||||
|
// Forward-declare the stub type.
|
||||||
|
printer->Print(vars_,
|
||||||
|
"class $classname$_Stub;\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
GenerateInterface(printer);
|
||||||
|
GenerateStubDefinition(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceGenerator::GenerateInterface(io::Printer* printer) {
|
||||||
|
printer->Print(vars_,
|
||||||
|
"class $dllexport$$classname$ : public ::google::protobuf::Service {\n"
|
||||||
|
" protected:\n"
|
||||||
|
" // This class should be treated as an abstract interface.\n"
|
||||||
|
" inline $classname$() {};\n"
|
||||||
|
" public:\n"
|
||||||
|
" virtual ~$classname$();\n");
|
||||||
|
printer->Indent();
|
||||||
|
|
||||||
|
printer->Print(vars_,
|
||||||
|
"\n"
|
||||||
|
"typedef $classname$_Stub Stub;\n"
|
||||||
|
"\n"
|
||||||
|
"static const ::google::protobuf::ServiceDescriptor* descriptor();\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
GenerateMethodSignatures(VIRTUAL, printer);
|
||||||
|
|
||||||
|
printer->Print(
|
||||||
|
"\n"
|
||||||
|
"// implements Service ----------------------------------------------\n"
|
||||||
|
"\n"
|
||||||
|
"const ::google::protobuf::ServiceDescriptor* GetDescriptor();\n"
|
||||||
|
"void CallMethod(const ::google::protobuf::MethodDescriptor* method,\n"
|
||||||
|
" ::google::protobuf::RpcController* controller,\n"
|
||||||
|
" const ::google::protobuf::Message* request,\n"
|
||||||
|
" ::google::protobuf::Message* response,\n"
|
||||||
|
" ::google::protobuf::Closure* done);\n"
|
||||||
|
"const ::google::protobuf::Message& GetRequestPrototype(\n"
|
||||||
|
" const ::google::protobuf::MethodDescriptor* method) const;\n"
|
||||||
|
"const ::google::protobuf::Message& GetResponsePrototype(\n"
|
||||||
|
" const ::google::protobuf::MethodDescriptor* method) const;\n");
|
||||||
|
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print(vars_,
|
||||||
|
"\n"
|
||||||
|
" private:\n"
|
||||||
|
" GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n"
|
||||||
|
"};\n"
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceGenerator::GenerateStubDefinition(io::Printer* printer) {
|
||||||
|
printer->Print(vars_,
|
||||||
|
"class $dllexport$$classname$_Stub : public $classname$ {\n"
|
||||||
|
" public:\n");
|
||||||
|
|
||||||
|
printer->Indent();
|
||||||
|
|
||||||
|
printer->Print(vars_,
|
||||||
|
"$classname$_Stub(::google::protobuf::RpcChannel* channel);\n"
|
||||||
|
"$classname$_Stub(::google::protobuf::RpcChannel* channel,\n"
|
||||||
|
" ::google::protobuf::Service::ChannelOwnership ownership);\n"
|
||||||
|
"~$classname$_Stub();\n"
|
||||||
|
"\n"
|
||||||
|
"inline ::google::protobuf::RpcChannel* channel() { return channel_; }\n"
|
||||||
|
"\n"
|
||||||
|
"// implements $classname$ ------------------------------------------\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
GenerateMethodSignatures(NON_VIRTUAL, printer);
|
||||||
|
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print(vars_,
|
||||||
|
" private:\n"
|
||||||
|
" ::google::protobuf::RpcChannel* channel_;\n"
|
||||||
|
" bool owns_channel_;\n"
|
||||||
|
" GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$_Stub);\n"
|
||||||
|
"};\n"
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceGenerator::GenerateMethodSignatures(
|
||||||
|
VirtualOrNon virtual_or_non, io::Printer* printer) {
|
||||||
|
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||||
|
const MethodDescriptor* method = descriptor_->method(i);
|
||||||
|
map<string, string> sub_vars;
|
||||||
|
sub_vars["name"] = method->name();
|
||||||
|
sub_vars["input_type"] = ClassName(method->input_type(), true);
|
||||||
|
sub_vars["output_type"] = ClassName(method->output_type(), true);
|
||||||
|
sub_vars["virtual"] = virtual_or_non == VIRTUAL ? "virtual " : "";
|
||||||
|
|
||||||
|
printer->Print(sub_vars,
|
||||||
|
"$virtual$void $name$(::google::protobuf::RpcController* controller,\n"
|
||||||
|
" const $input_type$* request,\n"
|
||||||
|
" $output_type$* response,\n"
|
||||||
|
" ::google::protobuf::Closure* done);\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
void ServiceGenerator::GenerateDescriptorInitializer(
|
||||||
|
io::Printer* printer, int index) {
|
||||||
|
map<string, string> vars;
|
||||||
|
vars["classname"] = descriptor_->name();
|
||||||
|
vars["index"] = SimpleItoa(index);
|
||||||
|
|
||||||
|
printer->Print(vars,
|
||||||
|
"$classname$_descriptor_ = file->service($index$);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
void ServiceGenerator::GenerateImplementation(io::Printer* printer) {
|
||||||
|
printer->Print(vars_,
|
||||||
|
"$classname$::~$classname$() {}\n"
|
||||||
|
"\n"
|
||||||
|
"const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n"
|
||||||
|
" protobuf_AssignDescriptorsOnce();\n"
|
||||||
|
" return $classname$_descriptor_;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n"
|
||||||
|
" protobuf_AssignDescriptorsOnce();\n"
|
||||||
|
" return $classname$_descriptor_;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
// Generate methods of the interface.
|
||||||
|
GenerateNotImplementedMethods(printer);
|
||||||
|
GenerateCallMethod(printer);
|
||||||
|
GenerateGetPrototype(REQUEST, printer);
|
||||||
|
GenerateGetPrototype(RESPONSE, printer);
|
||||||
|
|
||||||
|
// Generate stub implementation.
|
||||||
|
printer->Print(vars_,
|
||||||
|
"$classname$_Stub::$classname$_Stub(::google::protobuf::RpcChannel* channel)\n"
|
||||||
|
" : channel_(channel), owns_channel_(false) {}\n"
|
||||||
|
"$classname$_Stub::$classname$_Stub(\n"
|
||||||
|
" ::google::protobuf::RpcChannel* channel,\n"
|
||||||
|
" ::google::protobuf::Service::ChannelOwnership ownership)\n"
|
||||||
|
" : channel_(channel),\n"
|
||||||
|
" owns_channel_(ownership == ::google::protobuf::Service::STUB_OWNS_CHANNEL) {}\n"
|
||||||
|
"$classname$_Stub::~$classname$_Stub() {\n"
|
||||||
|
" if (owns_channel_) delete channel_;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
GenerateStubMethods(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) {
|
||||||
|
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||||
|
const MethodDescriptor* method = descriptor_->method(i);
|
||||||
|
map<string, string> sub_vars;
|
||||||
|
sub_vars["classname"] = descriptor_->name();
|
||||||
|
sub_vars["name"] = method->name();
|
||||||
|
sub_vars["index"] = SimpleItoa(i);
|
||||||
|
sub_vars["input_type"] = ClassName(method->input_type(), true);
|
||||||
|
sub_vars["output_type"] = ClassName(method->output_type(), true);
|
||||||
|
|
||||||
|
printer->Print(sub_vars,
|
||||||
|
"void $classname$::$name$(::google::protobuf::RpcController* controller,\n"
|
||||||
|
" const $input_type$*,\n"
|
||||||
|
" $output_type$*,\n"
|
||||||
|
" ::google::protobuf::Closure* done) {\n"
|
||||||
|
" controller->SetFailed(\"Method $name$() not implemented.\");\n"
|
||||||
|
" done->Run();\n"
|
||||||
|
"}\n"
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
|
||||||
|
printer->Print(vars_,
|
||||||
|
"void $classname$::CallMethod(const ::google::protobuf::MethodDescriptor* method,\n"
|
||||||
|
" ::google::protobuf::RpcController* controller,\n"
|
||||||
|
" const ::google::protobuf::Message* request,\n"
|
||||||
|
" ::google::protobuf::Message* response,\n"
|
||||||
|
" ::google::protobuf::Closure* done) {\n"
|
||||||
|
" GOOGLE_DCHECK_EQ(method->service(), $classname$_descriptor_);\n"
|
||||||
|
" switch(method->index()) {\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||||
|
const MethodDescriptor* method = descriptor_->method(i);
|
||||||
|
map<string, string> sub_vars;
|
||||||
|
sub_vars["name"] = method->name();
|
||||||
|
sub_vars["index"] = SimpleItoa(i);
|
||||||
|
sub_vars["input_type"] = ClassName(method->input_type(), true);
|
||||||
|
sub_vars["output_type"] = ClassName(method->output_type(), true);
|
||||||
|
|
||||||
|
// Note: down_cast does not work here because it only works on pointers,
|
||||||
|
// not references.
|
||||||
|
printer->Print(sub_vars,
|
||||||
|
" case $index$:\n"
|
||||||
|
" $name$(controller,\n"
|
||||||
|
" ::google::protobuf::down_cast<const $input_type$*>(request),\n"
|
||||||
|
" ::google::protobuf::down_cast< $output_type$*>(response),\n"
|
||||||
|
" done);\n"
|
||||||
|
" break;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(vars_,
|
||||||
|
" default:\n"
|
||||||
|
" GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
|
||||||
|
" break;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
|
||||||
|
io::Printer* printer) {
|
||||||
|
if (which == REQUEST) {
|
||||||
|
printer->Print(vars_,
|
||||||
|
"const ::google::protobuf::Message& $classname$::GetRequestPrototype(\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(vars_,
|
||||||
|
"const ::google::protobuf::Message& $classname$::GetResponsePrototype(\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(vars_,
|
||||||
|
" const ::google::protobuf::MethodDescriptor* method) const {\n"
|
||||||
|
" GOOGLE_DCHECK_EQ(method->service(), descriptor());\n"
|
||||||
|
" switch(method->index()) {\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||||
|
const MethodDescriptor* method = descriptor_->method(i);
|
||||||
|
const Descriptor* type =
|
||||||
|
(which == REQUEST) ? method->input_type() : method->output_type();
|
||||||
|
|
||||||
|
map<string, string> sub_vars;
|
||||||
|
sub_vars["index"] = SimpleItoa(i);
|
||||||
|
sub_vars["type"] = ClassName(type, true);
|
||||||
|
|
||||||
|
printer->Print(sub_vars,
|
||||||
|
" case $index$:\n"
|
||||||
|
" return $type$::default_instance();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(vars_,
|
||||||
|
" default:\n"
|
||||||
|
" GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
|
||||||
|
" return *reinterpret_cast< ::google::protobuf::Message*>(NULL);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceGenerator::GenerateStubMethods(io::Printer* printer) {
|
||||||
|
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||||
|
const MethodDescriptor* method = descriptor_->method(i);
|
||||||
|
map<string, string> sub_vars;
|
||||||
|
sub_vars["classname"] = descriptor_->name();
|
||||||
|
sub_vars["name"] = method->name();
|
||||||
|
sub_vars["index"] = SimpleItoa(i);
|
||||||
|
sub_vars["input_type"] = ClassName(method->input_type(), true);
|
||||||
|
sub_vars["output_type"] = ClassName(method->output_type(), true);
|
||||||
|
|
||||||
|
printer->Print(sub_vars,
|
||||||
|
"void $classname$_Stub::$name$(::google::protobuf::RpcController* controller,\n"
|
||||||
|
" const $input_type$* request,\n"
|
||||||
|
" $output_type$* response,\n"
|
||||||
|
" ::google::protobuf::Closure* done) {\n"
|
||||||
|
" channel_->CallMethod(descriptor()->method($index$),\n"
|
||||||
|
" controller, request, response, done);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,453 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void SetStringVariables(const FieldDescriptor* descriptor,
|
||||||
|
map<string, string>* variables) {
|
||||||
|
SetCommonFieldVariables(descriptor, variables);
|
||||||
|
(*variables)["default"] = DefaultValue(descriptor);
|
||||||
|
(*variables)["default_variable"] = descriptor->default_value_string().empty()
|
||||||
|
? "::google::protobuf::internal::kEmptyString"
|
||||||
|
: "_default_" + FieldName(descriptor) + "_";
|
||||||
|
(*variables)["pointer_type"] =
|
||||||
|
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
StringFieldGenerator::
|
||||||
|
StringFieldGenerator(const FieldDescriptor* descriptor)
|
||||||
|
: descriptor_(descriptor) {
|
||||||
|
SetStringVariables(descriptor, &variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringFieldGenerator::~StringFieldGenerator() {}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GeneratePrivateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "::std::string* $name$_;\n");
|
||||||
|
if (!descriptor_->default_value_string().empty()) {
|
||||||
|
printer->Print(variables_, "static const ::std::string $default_variable$;\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||||
|
// If we're using StringFieldGenerator for a field with a ctype, it's
|
||||||
|
// because that ctype isn't actually implemented. In particular, this is
|
||||||
|
// true of ctype=CORD and ctype=STRING_PIECE in the open source release.
|
||||||
|
// We aren't releasing Cord because it has too many Google-specific
|
||||||
|
// dependencies and we aren't releasing StringPiece because it's hardly
|
||||||
|
// useful outside of Google and because it would get confusing to have
|
||||||
|
// multiple instances of the StringPiece class in different libraries (PCRE
|
||||||
|
// already includes it for their C++ bindings, which came from Google).
|
||||||
|
//
|
||||||
|
// In any case, we make all the accessors private while still actually
|
||||||
|
// using a string to represent the field internally. This way, we can
|
||||||
|
// guarantee that if we do ever implement the ctype, it won't break any
|
||||||
|
// existing users who might be -- for whatever reason -- already using .proto
|
||||||
|
// files that applied the ctype. The field can still be accessed via the
|
||||||
|
// reflection interface since the reflection interface is independent of
|
||||||
|
// the string's underlying representation.
|
||||||
|
if (descriptor_->options().ctype() != FieldOptions::STRING) {
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print(
|
||||||
|
" private:\n"
|
||||||
|
" // Hidden due to unknown ctype option.\n");
|
||||||
|
printer->Indent();
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const ::std::string& $name$() const$deprecation$;\n"
|
||||||
|
"inline void set_$name$(const ::std::string& value)$deprecation$;\n"
|
||||||
|
"inline void set_$name$(const char* value)$deprecation$;\n"
|
||||||
|
"inline void set_$name$(const $pointer_type$* value, size_t size)"
|
||||||
|
"$deprecation$;\n"
|
||||||
|
"inline ::std::string* mutable_$name$()$deprecation$;\n"
|
||||||
|
"inline ::std::string* release_$name$()$deprecation$;\n");
|
||||||
|
|
||||||
|
if (descriptor_->options().ctype() != FieldOptions::STRING) {
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print(" public:\n");
|
||||||
|
printer->Indent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const ::std::string& $classname$::$name$() const {\n"
|
||||||
|
" return *$name$_;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::set_$name$(const ::std::string& value) {\n"
|
||||||
|
" set_has_$name$();\n"
|
||||||
|
" if ($name$_ == &$default_variable$) {\n"
|
||||||
|
" $name$_ = new ::std::string;\n"
|
||||||
|
" }\n"
|
||||||
|
" $name$_->assign(value);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::set_$name$(const char* value) {\n"
|
||||||
|
" set_has_$name$();\n"
|
||||||
|
" if ($name$_ == &$default_variable$) {\n"
|
||||||
|
" $name$_ = new ::std::string;\n"
|
||||||
|
" }\n"
|
||||||
|
" $name$_->assign(value);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline "
|
||||||
|
"void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
|
||||||
|
" set_has_$name$();\n"
|
||||||
|
" if ($name$_ == &$default_variable$) {\n"
|
||||||
|
" $name$_ = new ::std::string;\n"
|
||||||
|
" }\n"
|
||||||
|
" $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline ::std::string* $classname$::mutable_$name$() {\n"
|
||||||
|
" set_has_$name$();\n"
|
||||||
|
" if ($name$_ == &$default_variable$) {\n");
|
||||||
|
if (descriptor_->default_value_string().empty()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
" $name$_ = new ::std::string;\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
" $name$_ = new ::std::string($default_variable$);\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
" }\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline ::std::string* $classname$::release_$name$() {\n"
|
||||||
|
" clear_has_$name$();\n"
|
||||||
|
" if ($name$_ == &$default_variable$) {\n"
|
||||||
|
" return NULL;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" ::std::string* temp = $name$_;\n"
|
||||||
|
" $name$_ = const_cast< ::std::string*>(&$default_variable$);\n"
|
||||||
|
" return temp;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
|
if (!descriptor_->default_value_string().empty()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"const ::std::string $classname$::$default_variable$($default$);\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateClearingCode(io::Printer* printer) const {
|
||||||
|
if (descriptor_->default_value_string().empty()) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($name$_ != &$default_variable$) {\n"
|
||||||
|
" $name$_->clear();\n"
|
||||||
|
"}\n");
|
||||||
|
} else {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($name$_ != &$default_variable$) {\n"
|
||||||
|
" $name$_->assign($default_variable$);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "set_$name$(from.$name$());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateSwappingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateConstructorCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"$name$_ = const_cast< ::std::string*>(&$default_variable$);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateDestructorCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"if ($name$_ != &$default_variable$) {\n"
|
||||||
|
" delete $name$_;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
|
||||||
|
" input, this->mutable_$name$()));\n");
|
||||||
|
if (HasUtf8Verification(descriptor_->file()) &&
|
||||||
|
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||||
|
" this->$name$().data(), this->$name$().length(),\n"
|
||||||
|
" ::google::protobuf::internal::WireFormat::PARSE);\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||||
|
if (HasUtf8Verification(descriptor_->file()) &&
|
||||||
|
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||||
|
" this->$name$().data(), this->$name$().length(),\n"
|
||||||
|
" ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
|
||||||
|
" $number$, this->$name$(), output);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||||
|
if (HasUtf8Verification(descriptor_->file()) &&
|
||||||
|
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||||
|
" this->$name$().data(), this->$name$().length(),\n"
|
||||||
|
" ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
"target =\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n"
|
||||||
|
" $number$, this->$name$(), target);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringFieldGenerator::
|
||||||
|
GenerateByteSize(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"total_size += $tag_size$ +\n"
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||||
|
" this->$name$());\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
RepeatedStringFieldGenerator::
|
||||||
|
RepeatedStringFieldGenerator(const FieldDescriptor* descriptor)
|
||||||
|
: descriptor_(descriptor) {
|
||||||
|
SetStringVariables(descriptor, &variables_);
|
||||||
|
}
|
||||||
|
|
||||||
|
RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GeneratePrivateMembers(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||||
|
// See comment above about unknown ctypes.
|
||||||
|
if (descriptor_->options().ctype() != FieldOptions::STRING) {
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print(
|
||||||
|
" private:\n"
|
||||||
|
" // Hidden due to unknown ctype option.\n");
|
||||||
|
printer->Indent();
|
||||||
|
}
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const ::std::string& $name$(int index) const$deprecation$;\n"
|
||||||
|
"inline ::std::string* mutable_$name$(int index)$deprecation$;\n"
|
||||||
|
"inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
|
||||||
|
"inline void set_$name$(int index, const char* value)$deprecation$;\n"
|
||||||
|
"inline "
|
||||||
|
"void set_$name$(int index, const $pointer_type$* value, size_t size)"
|
||||||
|
"$deprecation$;\n"
|
||||||
|
"inline ::std::string* add_$name$()$deprecation$;\n"
|
||||||
|
"inline void add_$name$(const ::std::string& value)$deprecation$;\n"
|
||||||
|
"inline void add_$name$(const char* value)$deprecation$;\n"
|
||||||
|
"inline void add_$name$(const $pointer_type$* value, size_t size)"
|
||||||
|
"$deprecation$;\n");
|
||||||
|
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
|
||||||
|
"$deprecation$;\n"
|
||||||
|
"inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
|
||||||
|
"$deprecation$;\n");
|
||||||
|
|
||||||
|
if (descriptor_->options().ctype() != FieldOptions::STRING) {
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print(" public:\n");
|
||||||
|
printer->Indent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const ::std::string& $classname$::$name$(int index) const {\n"
|
||||||
|
" return $name$_.Get(index);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline ::std::string* $classname$::mutable_$name$(int index) {\n"
|
||||||
|
" return $name$_.Mutable(index);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::set_$name$(int index, const ::std::string& value) {\n"
|
||||||
|
" $name$_.Mutable(index)->assign(value);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::set_$name$(int index, const char* value) {\n"
|
||||||
|
" $name$_.Mutable(index)->assign(value);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void "
|
||||||
|
"$classname$::set_$name$"
|
||||||
|
"(int index, const $pointer_type$* value, size_t size) {\n"
|
||||||
|
" $name$_.Mutable(index)->assign(\n"
|
||||||
|
" reinterpret_cast<const char*>(value), size);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline ::std::string* $classname$::add_$name$() {\n"
|
||||||
|
" return $name$_.Add();\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::add_$name$(const ::std::string& value) {\n"
|
||||||
|
" $name$_.Add()->assign(value);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void $classname$::add_$name$(const char* value) {\n"
|
||||||
|
" $name$_.Add()->assign(value);\n"
|
||||||
|
"}\n"
|
||||||
|
"inline void "
|
||||||
|
"$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
|
||||||
|
" $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
|
||||||
|
"}\n");
|
||||||
|
printer->Print(variables_,
|
||||||
|
"inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
|
||||||
|
"$classname$::$name$() const {\n"
|
||||||
|
" return $name$_;\n"
|
||||||
|
"}\n"
|
||||||
|
"inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
|
||||||
|
"$classname$::mutable_$name$() {\n"
|
||||||
|
" return &$name$_;\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateClearingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_.Clear();\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateMergingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateSwappingCode(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateConstructorCode(io::Printer* printer) const {
|
||||||
|
// Not needed for repeated fields.
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
|
||||||
|
" input, this->add_$name$()));\n");
|
||||||
|
if (HasUtf8Verification(descriptor_->file()) &&
|
||||||
|
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||||
|
" this->$name$(0).data(), this->$name$(0).length(),\n"
|
||||||
|
" ::google::protobuf::internal::WireFormat::PARSE);\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||||
|
if (HasUtf8Verification(descriptor_->file()) &&
|
||||||
|
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||||
|
" this->$name$(i).data(), this->$name$(i).length(),\n"
|
||||||
|
" ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
|
||||||
|
" $number$, this->$name$(i), output);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||||
|
if (HasUtf8Verification(descriptor_->file()) &&
|
||||||
|
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||||
|
printer->Print(variables_,
|
||||||
|
" ::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||||
|
" this->$name$(i).data(), this->$name$(i).length(),\n"
|
||||||
|
" ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
|
||||||
|
}
|
||||||
|
printer->Print(variables_,
|
||||||
|
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||||
|
" Write$declared_type$ToArray($number$, this->$name$(i), target);\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatedStringFieldGenerator::
|
||||||
|
GenerateByteSize(io::Printer* printer) const {
|
||||||
|
printer->Print(variables_,
|
||||||
|
"total_size += $tag_size$ * this->$name$_size();\n"
|
||||||
|
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||||
|
" total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||||
|
" this->$name$(i));\n"
|
||||||
|
"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,104 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
|
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace cpp {
|
||||||
|
|
||||||
|
class StringFieldGenerator : public FieldGenerator {
|
||||||
|
public:
|
||||||
|
explicit StringFieldGenerator(const FieldDescriptor* descriptor);
|
||||||
|
~StringFieldGenerator();
|
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||||
|
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||||
|
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||||
|
void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
|
||||||
|
void GenerateClearingCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
|
void GenerateSwappingCode(io::Printer* printer) const;
|
||||||
|
void GenerateConstructorCode(io::Printer* printer) const;
|
||||||
|
void GenerateDestructorCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||||
|
void GenerateByteSize(io::Printer* printer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const FieldDescriptor* descriptor_;
|
||||||
|
map<string, string> variables_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
class RepeatedStringFieldGenerator : public FieldGenerator {
|
||||||
|
public:
|
||||||
|
explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor);
|
||||||
|
~RepeatedStringFieldGenerator();
|
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||||
|
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||||
|
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||||
|
void GenerateClearingCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergingCode(io::Printer* printer) const;
|
||||||
|
void GenerateSwappingCode(io::Printer* printer) const;
|
||||||
|
void GenerateConstructorCode(io::Printer* printer) const;
|
||||||
|
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||||
|
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||||
|
void GenerateByteSize(io::Printer* printer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const FieldDescriptor* descriptor_;
|
||||||
|
map<string, string> variables_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cpp
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,231 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/mock_code_generator.h>
|
||||||
|
|
||||||
|
#include <google/protobuf/testing/file.h>
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
#include <google/protobuf/stubs/substitute.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <google/protobuf/stubs/stl_util-inl.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
// Returns the list of the names of files in all_files in the form of a
|
||||||
|
// comma-separated string.
|
||||||
|
string CommaSeparatedList(const vector<const FileDescriptor*> all_files) {
|
||||||
|
vector<string> names;
|
||||||
|
for (int i = 0; i < all_files.size(); i++) {
|
||||||
|
names.push_back(all_files[i]->name());
|
||||||
|
}
|
||||||
|
return JoinStrings(names, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* kFirstInsertionPointName = "first_mock_insertion_point";
|
||||||
|
static const char* kSecondInsertionPointName = "second_mock_insertion_point";
|
||||||
|
static const char* kFirstInsertionPoint =
|
||||||
|
"# @@protoc_insertion_point(first_mock_insertion_point) is here\n";
|
||||||
|
static const char* kSecondInsertionPoint =
|
||||||
|
" # @@protoc_insertion_point(second_mock_insertion_point) is here\n";
|
||||||
|
|
||||||
|
MockCodeGenerator::MockCodeGenerator(const string& name)
|
||||||
|
: name_(name) {}
|
||||||
|
|
||||||
|
MockCodeGenerator::~MockCodeGenerator() {}
|
||||||
|
|
||||||
|
void MockCodeGenerator::ExpectGenerated(
|
||||||
|
const string& name,
|
||||||
|
const string& parameter,
|
||||||
|
const string& insertions,
|
||||||
|
const string& file,
|
||||||
|
const string& first_message_name,
|
||||||
|
const string& first_parsed_file_name,
|
||||||
|
const string& output_directory) {
|
||||||
|
string content;
|
||||||
|
ASSERT_TRUE(File::ReadFileToString(
|
||||||
|
output_directory + "/" + GetOutputFileName(name, file), &content));
|
||||||
|
|
||||||
|
vector<string> lines;
|
||||||
|
SplitStringUsing(content, "\n", &lines);
|
||||||
|
|
||||||
|
while (!lines.empty() && lines.back().empty()) {
|
||||||
|
lines.pop_back();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < lines.size(); i++) {
|
||||||
|
lines[i] += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string> insertion_list;
|
||||||
|
if (!insertions.empty()) {
|
||||||
|
SplitStringUsing(insertions, ",", &insertion_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2);
|
||||||
|
EXPECT_EQ(GetOutputFileContent(name, parameter, file,
|
||||||
|
first_parsed_file_name, first_message_name),
|
||||||
|
lines[0]);
|
||||||
|
|
||||||
|
EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]);
|
||||||
|
EXPECT_EQ(kSecondInsertionPoint, lines[2 + insertion_list.size() * 2]);
|
||||||
|
|
||||||
|
for (int i = 0; i < insertion_list.size(); i++) {
|
||||||
|
EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert",
|
||||||
|
file, file, first_message_name),
|
||||||
|
lines[1 + i]);
|
||||||
|
// Second insertion point is indented, so the inserted text should
|
||||||
|
// automatically be indented too.
|
||||||
|
EXPECT_EQ(" " + GetOutputFileContent(insertion_list[i], "second_insert",
|
||||||
|
file, file, first_message_name),
|
||||||
|
lines[2 + insertion_list.size() + i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockCodeGenerator::Generate(
|
||||||
|
const FileDescriptor* file,
|
||||||
|
const string& parameter,
|
||||||
|
GeneratorContext* context,
|
||||||
|
string* error) const {
|
||||||
|
for (int i = 0; i < file->message_type_count(); i++) {
|
||||||
|
if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
|
||||||
|
string command = StripPrefixString(file->message_type(i)->name(),
|
||||||
|
"MockCodeGenerator_");
|
||||||
|
if (command == "Error") {
|
||||||
|
*error = "Saw message type MockCodeGenerator_Error.";
|
||||||
|
return false;
|
||||||
|
} else if (command == "Exit") {
|
||||||
|
cerr << "Saw message type MockCodeGenerator_Exit." << endl;
|
||||||
|
exit(123);
|
||||||
|
} else if (command == "Abort") {
|
||||||
|
cerr << "Saw message type MockCodeGenerator_Abort." << endl;
|
||||||
|
abort();
|
||||||
|
} else {
|
||||||
|
GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasPrefixString(parameter, "insert=")) {
|
||||||
|
vector<string> insert_into;
|
||||||
|
SplitStringUsing(StripPrefixString(parameter, "insert="),
|
||||||
|
",", &insert_into);
|
||||||
|
|
||||||
|
for (int i = 0; i < insert_into.size(); i++) {
|
||||||
|
{
|
||||||
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
|
context->OpenForInsert(
|
||||||
|
GetOutputFileName(insert_into[i], file),
|
||||||
|
kFirstInsertionPointName));
|
||||||
|
io::Printer printer(output.get(), '$');
|
||||||
|
printer.PrintRaw(GetOutputFileContent(name_, "first_insert",
|
||||||
|
file, context));
|
||||||
|
if (printer.failed()) {
|
||||||
|
*error = "MockCodeGenerator detected write error.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
|
context->OpenForInsert(
|
||||||
|
GetOutputFileName(insert_into[i], file),
|
||||||
|
kSecondInsertionPointName));
|
||||||
|
io::Printer printer(output.get(), '$');
|
||||||
|
printer.PrintRaw(GetOutputFileContent(name_, "second_insert",
|
||||||
|
file, context));
|
||||||
|
if (printer.failed()) {
|
||||||
|
*error = "MockCodeGenerator detected write error.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||||
|
context->Open(GetOutputFileName(name_, file)));
|
||||||
|
|
||||||
|
io::Printer printer(output.get(), '$');
|
||||||
|
printer.PrintRaw(GetOutputFileContent(name_, parameter,
|
||||||
|
file, context));
|
||||||
|
printer.PrintRaw(kFirstInsertionPoint);
|
||||||
|
printer.PrintRaw(kSecondInsertionPoint);
|
||||||
|
|
||||||
|
if (printer.failed()) {
|
||||||
|
*error = "MockCodeGenerator detected write error.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string MockCodeGenerator::GetOutputFileName(const string& generator_name,
|
||||||
|
const FileDescriptor* file) {
|
||||||
|
return GetOutputFileName(generator_name, file->name());
|
||||||
|
}
|
||||||
|
|
||||||
|
string MockCodeGenerator::GetOutputFileName(const string& generator_name,
|
||||||
|
const string& file) {
|
||||||
|
return file + ".MockCodeGenerator." + generator_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
string MockCodeGenerator::GetOutputFileContent(
|
||||||
|
const string& generator_name,
|
||||||
|
const string& parameter,
|
||||||
|
const FileDescriptor* file,
|
||||||
|
GeneratorContext *context) {
|
||||||
|
vector<const FileDescriptor*> all_files;
|
||||||
|
context->ListParsedFiles(&all_files);
|
||||||
|
return GetOutputFileContent(
|
||||||
|
generator_name, parameter, file->name(),
|
||||||
|
CommaSeparatedList(all_files),
|
||||||
|
file->message_type_count() > 0 ?
|
||||||
|
file->message_type(0)->name() : "(none)");
|
||||||
|
}
|
||||||
|
|
||||||
|
string MockCodeGenerator::GetOutputFileContent(
|
||||||
|
const string& generator_name,
|
||||||
|
const string& parameter,
|
||||||
|
const string& file,
|
||||||
|
const string& parsed_file_list,
|
||||||
|
const string& first_message_name) {
|
||||||
|
return strings::Substitute("$0: $1, $2, $3, $4\n",
|
||||||
|
generator_name, parameter, file,
|
||||||
|
first_message_name, parsed_file_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,790 @@
|
|||||||
|
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
// source: google/protobuf/compiler/plugin.proto
|
||||||
|
|
||||||
|
#ifndef PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
|
||||||
|
#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
|
||||||
|
#if GOOGLE_PROTOBUF_VERSION < 2004000
|
||||||
|
#error This file was generated by a newer version of protoc which is
|
||||||
|
#error incompatible with your Protocol Buffer headers. Please update
|
||||||
|
#error your headers.
|
||||||
|
#endif
|
||||||
|
#if 2004001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
|
||||||
|
#error This file was generated by an older version of protoc which is
|
||||||
|
#error incompatible with your Protocol Buffer headers. Please
|
||||||
|
#error regenerate this file with a newer version of protoc.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <google/protobuf/generated_message_util.h>
|
||||||
|
#include <google/protobuf/repeated_field.h>
|
||||||
|
#include <google/protobuf/extension_set.h>
|
||||||
|
#include <google/protobuf/generated_message_reflection.h>
|
||||||
|
#include "google/protobuf/descriptor.pb.h"
|
||||||
|
// @@protoc_insertion_point(includes)
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
// Internal implementation detail -- do not call these.
|
||||||
|
void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
|
||||||
|
class CodeGeneratorRequest;
|
||||||
|
class CodeGeneratorResponse;
|
||||||
|
class CodeGeneratorResponse_File;
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message {
|
||||||
|
public:
|
||||||
|
CodeGeneratorRequest();
|
||||||
|
virtual ~CodeGeneratorRequest();
|
||||||
|
|
||||||
|
CodeGeneratorRequest(const CodeGeneratorRequest& from);
|
||||||
|
|
||||||
|
inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) {
|
||||||
|
CopyFrom(from);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
|
||||||
|
return _unknown_fields_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
|
||||||
|
return &_unknown_fields_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const ::google::protobuf::Descriptor* descriptor();
|
||||||
|
static const CodeGeneratorRequest& default_instance();
|
||||||
|
|
||||||
|
void Swap(CodeGeneratorRequest* other);
|
||||||
|
|
||||||
|
// implements Message ----------------------------------------------
|
||||||
|
|
||||||
|
CodeGeneratorRequest* New() const;
|
||||||
|
void CopyFrom(const ::google::protobuf::Message& from);
|
||||||
|
void MergeFrom(const ::google::protobuf::Message& from);
|
||||||
|
void CopyFrom(const CodeGeneratorRequest& from);
|
||||||
|
void MergeFrom(const CodeGeneratorRequest& from);
|
||||||
|
void Clear();
|
||||||
|
bool IsInitialized() const;
|
||||||
|
|
||||||
|
int ByteSize() const;
|
||||||
|
bool MergePartialFromCodedStream(
|
||||||
|
::google::protobuf::io::CodedInputStream* input);
|
||||||
|
void SerializeWithCachedSizes(
|
||||||
|
::google::protobuf::io::CodedOutputStream* output) const;
|
||||||
|
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
|
||||||
|
int GetCachedSize() const { return _cached_size_; }
|
||||||
|
private:
|
||||||
|
void SharedCtor();
|
||||||
|
void SharedDtor();
|
||||||
|
void SetCachedSize(int size) const;
|
||||||
|
public:
|
||||||
|
|
||||||
|
::google::protobuf::Metadata GetMetadata() const;
|
||||||
|
|
||||||
|
// nested types ----------------------------------------------------
|
||||||
|
|
||||||
|
// accessors -------------------------------------------------------
|
||||||
|
|
||||||
|
// repeated string file_to_generate = 1;
|
||||||
|
inline int file_to_generate_size() const;
|
||||||
|
inline void clear_file_to_generate();
|
||||||
|
static const int kFileToGenerateFieldNumber = 1;
|
||||||
|
inline const ::std::string& file_to_generate(int index) const;
|
||||||
|
inline ::std::string* mutable_file_to_generate(int index);
|
||||||
|
inline void set_file_to_generate(int index, const ::std::string& value);
|
||||||
|
inline void set_file_to_generate(int index, const char* value);
|
||||||
|
inline void set_file_to_generate(int index, const char* value, size_t size);
|
||||||
|
inline ::std::string* add_file_to_generate();
|
||||||
|
inline void add_file_to_generate(const ::std::string& value);
|
||||||
|
inline void add_file_to_generate(const char* value);
|
||||||
|
inline void add_file_to_generate(const char* value, size_t size);
|
||||||
|
inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
|
||||||
|
inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
|
||||||
|
|
||||||
|
// optional string parameter = 2;
|
||||||
|
inline bool has_parameter() const;
|
||||||
|
inline void clear_parameter();
|
||||||
|
static const int kParameterFieldNumber = 2;
|
||||||
|
inline const ::std::string& parameter() const;
|
||||||
|
inline void set_parameter(const ::std::string& value);
|
||||||
|
inline void set_parameter(const char* value);
|
||||||
|
inline void set_parameter(const char* value, size_t size);
|
||||||
|
inline ::std::string* mutable_parameter();
|
||||||
|
inline ::std::string* release_parameter();
|
||||||
|
|
||||||
|
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||||
|
inline int proto_file_size() const;
|
||||||
|
inline void clear_proto_file();
|
||||||
|
static const int kProtoFileFieldNumber = 15;
|
||||||
|
inline const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
|
||||||
|
inline ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
|
||||||
|
inline ::google::protobuf::FileDescriptorProto* add_proto_file();
|
||||||
|
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
|
||||||
|
proto_file() const;
|
||||||
|
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
|
||||||
|
mutable_proto_file();
|
||||||
|
|
||||||
|
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
|
||||||
|
private:
|
||||||
|
inline void set_has_parameter();
|
||||||
|
inline void clear_has_parameter();
|
||||||
|
|
||||||
|
::google::protobuf::UnknownFieldSet _unknown_fields_;
|
||||||
|
|
||||||
|
::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
|
||||||
|
::std::string* parameter_;
|
||||||
|
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
|
||||||
|
|
||||||
|
mutable int _cached_size_;
|
||||||
|
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
|
||||||
|
|
||||||
|
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
|
||||||
|
void InitAsDefaultInstance();
|
||||||
|
static CodeGeneratorRequest* default_instance_;
|
||||||
|
};
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::Message {
|
||||||
|
public:
|
||||||
|
CodeGeneratorResponse_File();
|
||||||
|
virtual ~CodeGeneratorResponse_File();
|
||||||
|
|
||||||
|
CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
|
||||||
|
|
||||||
|
inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) {
|
||||||
|
CopyFrom(from);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
|
||||||
|
return _unknown_fields_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
|
||||||
|
return &_unknown_fields_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const ::google::protobuf::Descriptor* descriptor();
|
||||||
|
static const CodeGeneratorResponse_File& default_instance();
|
||||||
|
|
||||||
|
void Swap(CodeGeneratorResponse_File* other);
|
||||||
|
|
||||||
|
// implements Message ----------------------------------------------
|
||||||
|
|
||||||
|
CodeGeneratorResponse_File* New() const;
|
||||||
|
void CopyFrom(const ::google::protobuf::Message& from);
|
||||||
|
void MergeFrom(const ::google::protobuf::Message& from);
|
||||||
|
void CopyFrom(const CodeGeneratorResponse_File& from);
|
||||||
|
void MergeFrom(const CodeGeneratorResponse_File& from);
|
||||||
|
void Clear();
|
||||||
|
bool IsInitialized() const;
|
||||||
|
|
||||||
|
int ByteSize() const;
|
||||||
|
bool MergePartialFromCodedStream(
|
||||||
|
::google::protobuf::io::CodedInputStream* input);
|
||||||
|
void SerializeWithCachedSizes(
|
||||||
|
::google::protobuf::io::CodedOutputStream* output) const;
|
||||||
|
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
|
||||||
|
int GetCachedSize() const { return _cached_size_; }
|
||||||
|
private:
|
||||||
|
void SharedCtor();
|
||||||
|
void SharedDtor();
|
||||||
|
void SetCachedSize(int size) const;
|
||||||
|
public:
|
||||||
|
|
||||||
|
::google::protobuf::Metadata GetMetadata() const;
|
||||||
|
|
||||||
|
// nested types ----------------------------------------------------
|
||||||
|
|
||||||
|
// accessors -------------------------------------------------------
|
||||||
|
|
||||||
|
// optional string name = 1;
|
||||||
|
inline bool has_name() const;
|
||||||
|
inline void clear_name();
|
||||||
|
static const int kNameFieldNumber = 1;
|
||||||
|
inline const ::std::string& name() const;
|
||||||
|
inline void set_name(const ::std::string& value);
|
||||||
|
inline void set_name(const char* value);
|
||||||
|
inline void set_name(const char* value, size_t size);
|
||||||
|
inline ::std::string* mutable_name();
|
||||||
|
inline ::std::string* release_name();
|
||||||
|
|
||||||
|
// optional string insertion_point = 2;
|
||||||
|
inline bool has_insertion_point() const;
|
||||||
|
inline void clear_insertion_point();
|
||||||
|
static const int kInsertionPointFieldNumber = 2;
|
||||||
|
inline const ::std::string& insertion_point() const;
|
||||||
|
inline void set_insertion_point(const ::std::string& value);
|
||||||
|
inline void set_insertion_point(const char* value);
|
||||||
|
inline void set_insertion_point(const char* value, size_t size);
|
||||||
|
inline ::std::string* mutable_insertion_point();
|
||||||
|
inline ::std::string* release_insertion_point();
|
||||||
|
|
||||||
|
// optional string content = 15;
|
||||||
|
inline bool has_content() const;
|
||||||
|
inline void clear_content();
|
||||||
|
static const int kContentFieldNumber = 15;
|
||||||
|
inline const ::std::string& content() const;
|
||||||
|
inline void set_content(const ::std::string& value);
|
||||||
|
inline void set_content(const char* value);
|
||||||
|
inline void set_content(const char* value, size_t size);
|
||||||
|
inline ::std::string* mutable_content();
|
||||||
|
inline ::std::string* release_content();
|
||||||
|
|
||||||
|
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
|
||||||
|
private:
|
||||||
|
inline void set_has_name();
|
||||||
|
inline void clear_has_name();
|
||||||
|
inline void set_has_insertion_point();
|
||||||
|
inline void clear_has_insertion_point();
|
||||||
|
inline void set_has_content();
|
||||||
|
inline void clear_has_content();
|
||||||
|
|
||||||
|
::google::protobuf::UnknownFieldSet _unknown_fields_;
|
||||||
|
|
||||||
|
::std::string* name_;
|
||||||
|
::std::string* insertion_point_;
|
||||||
|
::std::string* content_;
|
||||||
|
|
||||||
|
mutable int _cached_size_;
|
||||||
|
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
|
||||||
|
|
||||||
|
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
|
||||||
|
void InitAsDefaultInstance();
|
||||||
|
static CodeGeneratorResponse_File* default_instance_;
|
||||||
|
};
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Message {
|
||||||
|
public:
|
||||||
|
CodeGeneratorResponse();
|
||||||
|
virtual ~CodeGeneratorResponse();
|
||||||
|
|
||||||
|
CodeGeneratorResponse(const CodeGeneratorResponse& from);
|
||||||
|
|
||||||
|
inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) {
|
||||||
|
CopyFrom(from);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
|
||||||
|
return _unknown_fields_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
|
||||||
|
return &_unknown_fields_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const ::google::protobuf::Descriptor* descriptor();
|
||||||
|
static const CodeGeneratorResponse& default_instance();
|
||||||
|
|
||||||
|
void Swap(CodeGeneratorResponse* other);
|
||||||
|
|
||||||
|
// implements Message ----------------------------------------------
|
||||||
|
|
||||||
|
CodeGeneratorResponse* New() const;
|
||||||
|
void CopyFrom(const ::google::protobuf::Message& from);
|
||||||
|
void MergeFrom(const ::google::protobuf::Message& from);
|
||||||
|
void CopyFrom(const CodeGeneratorResponse& from);
|
||||||
|
void MergeFrom(const CodeGeneratorResponse& from);
|
||||||
|
void Clear();
|
||||||
|
bool IsInitialized() const;
|
||||||
|
|
||||||
|
int ByteSize() const;
|
||||||
|
bool MergePartialFromCodedStream(
|
||||||
|
::google::protobuf::io::CodedInputStream* input);
|
||||||
|
void SerializeWithCachedSizes(
|
||||||
|
::google::protobuf::io::CodedOutputStream* output) const;
|
||||||
|
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
|
||||||
|
int GetCachedSize() const { return _cached_size_; }
|
||||||
|
private:
|
||||||
|
void SharedCtor();
|
||||||
|
void SharedDtor();
|
||||||
|
void SetCachedSize(int size) const;
|
||||||
|
public:
|
||||||
|
|
||||||
|
::google::protobuf::Metadata GetMetadata() const;
|
||||||
|
|
||||||
|
// nested types ----------------------------------------------------
|
||||||
|
|
||||||
|
typedef CodeGeneratorResponse_File File;
|
||||||
|
|
||||||
|
// accessors -------------------------------------------------------
|
||||||
|
|
||||||
|
// optional string error = 1;
|
||||||
|
inline bool has_error() const;
|
||||||
|
inline void clear_error();
|
||||||
|
static const int kErrorFieldNumber = 1;
|
||||||
|
inline const ::std::string& error() const;
|
||||||
|
inline void set_error(const ::std::string& value);
|
||||||
|
inline void set_error(const char* value);
|
||||||
|
inline void set_error(const char* value, size_t size);
|
||||||
|
inline ::std::string* mutable_error();
|
||||||
|
inline ::std::string* release_error();
|
||||||
|
|
||||||
|
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||||
|
inline int file_size() const;
|
||||||
|
inline void clear_file();
|
||||||
|
static const int kFileFieldNumber = 15;
|
||||||
|
inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
|
||||||
|
inline ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
|
||||||
|
inline ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
|
||||||
|
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
|
||||||
|
file() const;
|
||||||
|
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
|
||||||
|
mutable_file();
|
||||||
|
|
||||||
|
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
|
||||||
|
private:
|
||||||
|
inline void set_has_error();
|
||||||
|
inline void clear_has_error();
|
||||||
|
|
||||||
|
::google::protobuf::UnknownFieldSet _unknown_fields_;
|
||||||
|
|
||||||
|
::std::string* error_;
|
||||||
|
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
|
||||||
|
|
||||||
|
mutable int _cached_size_;
|
||||||
|
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
|
||||||
|
|
||||||
|
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||||
|
|
||||||
|
void InitAsDefaultInstance();
|
||||||
|
static CodeGeneratorResponse* default_instance_;
|
||||||
|
};
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
// CodeGeneratorRequest
|
||||||
|
|
||||||
|
// repeated string file_to_generate = 1;
|
||||||
|
inline int CodeGeneratorRequest::file_to_generate_size() const {
|
||||||
|
return file_to_generate_.size();
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::clear_file_to_generate() {
|
||||||
|
file_to_generate_.Clear();
|
||||||
|
}
|
||||||
|
inline const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
|
||||||
|
return file_to_generate_.Get(index);
|
||||||
|
}
|
||||||
|
inline ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
|
||||||
|
return file_to_generate_.Mutable(index);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
|
||||||
|
file_to_generate_.Mutable(index)->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
|
||||||
|
file_to_generate_.Mutable(index)->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
|
||||||
|
file_to_generate_.Mutable(index)->assign(
|
||||||
|
reinterpret_cast<const char*>(value), size);
|
||||||
|
}
|
||||||
|
inline ::std::string* CodeGeneratorRequest::add_file_to_generate() {
|
||||||
|
return file_to_generate_.Add();
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
|
||||||
|
file_to_generate_.Add()->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::add_file_to_generate(const char* value) {
|
||||||
|
file_to_generate_.Add()->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
|
||||||
|
file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
|
||||||
|
}
|
||||||
|
inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
|
||||||
|
CodeGeneratorRequest::file_to_generate() const {
|
||||||
|
return file_to_generate_;
|
||||||
|
}
|
||||||
|
inline ::google::protobuf::RepeatedPtrField< ::std::string>*
|
||||||
|
CodeGeneratorRequest::mutable_file_to_generate() {
|
||||||
|
return &file_to_generate_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// optional string parameter = 2;
|
||||||
|
inline bool CodeGeneratorRequest::has_parameter() const {
|
||||||
|
return (_has_bits_[0] & 0x00000002u) != 0;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::set_has_parameter() {
|
||||||
|
_has_bits_[0] |= 0x00000002u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::clear_has_parameter() {
|
||||||
|
_has_bits_[0] &= ~0x00000002u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::clear_parameter() {
|
||||||
|
if (parameter_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
|
parameter_->clear();
|
||||||
|
}
|
||||||
|
clear_has_parameter();
|
||||||
|
}
|
||||||
|
inline const ::std::string& CodeGeneratorRequest::parameter() const {
|
||||||
|
return *parameter_;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
|
||||||
|
set_has_parameter();
|
||||||
|
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
parameter_ = new ::std::string;
|
||||||
|
}
|
||||||
|
parameter_->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::set_parameter(const char* value) {
|
||||||
|
set_has_parameter();
|
||||||
|
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
parameter_ = new ::std::string;
|
||||||
|
}
|
||||||
|
parameter_->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
|
||||||
|
set_has_parameter();
|
||||||
|
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
parameter_ = new ::std::string;
|
||||||
|
}
|
||||||
|
parameter_->assign(reinterpret_cast<const char*>(value), size);
|
||||||
|
}
|
||||||
|
inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
|
||||||
|
set_has_parameter();
|
||||||
|
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
parameter_ = new ::std::string;
|
||||||
|
}
|
||||||
|
return parameter_;
|
||||||
|
}
|
||||||
|
inline ::std::string* CodeGeneratorRequest::release_parameter() {
|
||||||
|
clear_has_parameter();
|
||||||
|
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
::std::string* temp = parameter_;
|
||||||
|
parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||||
|
inline int CodeGeneratorRequest::proto_file_size() const {
|
||||||
|
return proto_file_.size();
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorRequest::clear_proto_file() {
|
||||||
|
proto_file_.Clear();
|
||||||
|
}
|
||||||
|
inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
|
||||||
|
return proto_file_.Get(index);
|
||||||
|
}
|
||||||
|
inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
|
||||||
|
return proto_file_.Mutable(index);
|
||||||
|
}
|
||||||
|
inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
|
||||||
|
return proto_file_.Add();
|
||||||
|
}
|
||||||
|
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
|
||||||
|
CodeGeneratorRequest::proto_file() const {
|
||||||
|
return proto_file_;
|
||||||
|
}
|
||||||
|
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
|
||||||
|
CodeGeneratorRequest::mutable_proto_file() {
|
||||||
|
return &proto_file_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
// CodeGeneratorResponse_File
|
||||||
|
|
||||||
|
// optional string name = 1;
|
||||||
|
inline bool CodeGeneratorResponse_File::has_name() const {
|
||||||
|
return (_has_bits_[0] & 0x00000001u) != 0;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_has_name() {
|
||||||
|
_has_bits_[0] |= 0x00000001u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::clear_has_name() {
|
||||||
|
_has_bits_[0] &= ~0x00000001u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::clear_name() {
|
||||||
|
if (name_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
|
name_->clear();
|
||||||
|
}
|
||||||
|
clear_has_name();
|
||||||
|
}
|
||||||
|
inline const ::std::string& CodeGeneratorResponse_File::name() const {
|
||||||
|
return *name_;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
|
||||||
|
set_has_name();
|
||||||
|
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
name_ = new ::std::string;
|
||||||
|
}
|
||||||
|
name_->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_name(const char* value) {
|
||||||
|
set_has_name();
|
||||||
|
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
name_ = new ::std::string;
|
||||||
|
}
|
||||||
|
name_->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
|
||||||
|
set_has_name();
|
||||||
|
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
name_ = new ::std::string;
|
||||||
|
}
|
||||||
|
name_->assign(reinterpret_cast<const char*>(value), size);
|
||||||
|
}
|
||||||
|
inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
|
||||||
|
set_has_name();
|
||||||
|
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
name_ = new ::std::string;
|
||||||
|
}
|
||||||
|
return name_;
|
||||||
|
}
|
||||||
|
inline ::std::string* CodeGeneratorResponse_File::release_name() {
|
||||||
|
clear_has_name();
|
||||||
|
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
::std::string* temp = name_;
|
||||||
|
name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// optional string insertion_point = 2;
|
||||||
|
inline bool CodeGeneratorResponse_File::has_insertion_point() const {
|
||||||
|
return (_has_bits_[0] & 0x00000002u) != 0;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_has_insertion_point() {
|
||||||
|
_has_bits_[0] |= 0x00000002u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::clear_has_insertion_point() {
|
||||||
|
_has_bits_[0] &= ~0x00000002u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::clear_insertion_point() {
|
||||||
|
if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
|
insertion_point_->clear();
|
||||||
|
}
|
||||||
|
clear_has_insertion_point();
|
||||||
|
}
|
||||||
|
inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
|
||||||
|
return *insertion_point_;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
|
||||||
|
set_has_insertion_point();
|
||||||
|
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
insertion_point_ = new ::std::string;
|
||||||
|
}
|
||||||
|
insertion_point_->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
|
||||||
|
set_has_insertion_point();
|
||||||
|
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
insertion_point_ = new ::std::string;
|
||||||
|
}
|
||||||
|
insertion_point_->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
|
||||||
|
set_has_insertion_point();
|
||||||
|
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
insertion_point_ = new ::std::string;
|
||||||
|
}
|
||||||
|
insertion_point_->assign(reinterpret_cast<const char*>(value), size);
|
||||||
|
}
|
||||||
|
inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
|
||||||
|
set_has_insertion_point();
|
||||||
|
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
insertion_point_ = new ::std::string;
|
||||||
|
}
|
||||||
|
return insertion_point_;
|
||||||
|
}
|
||||||
|
inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
|
||||||
|
clear_has_insertion_point();
|
||||||
|
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
::std::string* temp = insertion_point_;
|
||||||
|
insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// optional string content = 15;
|
||||||
|
inline bool CodeGeneratorResponse_File::has_content() const {
|
||||||
|
return (_has_bits_[0] & 0x00000004u) != 0;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_has_content() {
|
||||||
|
_has_bits_[0] |= 0x00000004u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::clear_has_content() {
|
||||||
|
_has_bits_[0] &= ~0x00000004u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::clear_content() {
|
||||||
|
if (content_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
|
content_->clear();
|
||||||
|
}
|
||||||
|
clear_has_content();
|
||||||
|
}
|
||||||
|
inline const ::std::string& CodeGeneratorResponse_File::content() const {
|
||||||
|
return *content_;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
|
||||||
|
set_has_content();
|
||||||
|
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
content_ = new ::std::string;
|
||||||
|
}
|
||||||
|
content_->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_content(const char* value) {
|
||||||
|
set_has_content();
|
||||||
|
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
content_ = new ::std::string;
|
||||||
|
}
|
||||||
|
content_->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
|
||||||
|
set_has_content();
|
||||||
|
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
content_ = new ::std::string;
|
||||||
|
}
|
||||||
|
content_->assign(reinterpret_cast<const char*>(value), size);
|
||||||
|
}
|
||||||
|
inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
|
||||||
|
set_has_content();
|
||||||
|
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
content_ = new ::std::string;
|
||||||
|
}
|
||||||
|
return content_;
|
||||||
|
}
|
||||||
|
inline ::std::string* CodeGeneratorResponse_File::release_content() {
|
||||||
|
clear_has_content();
|
||||||
|
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
::std::string* temp = content_;
|
||||||
|
content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
// CodeGeneratorResponse
|
||||||
|
|
||||||
|
// optional string error = 1;
|
||||||
|
inline bool CodeGeneratorResponse::has_error() const {
|
||||||
|
return (_has_bits_[0] & 0x00000001u) != 0;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse::set_has_error() {
|
||||||
|
_has_bits_[0] |= 0x00000001u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse::clear_has_error() {
|
||||||
|
_has_bits_[0] &= ~0x00000001u;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse::clear_error() {
|
||||||
|
if (error_ != &::google::protobuf::internal::kEmptyString) {
|
||||||
|
error_->clear();
|
||||||
|
}
|
||||||
|
clear_has_error();
|
||||||
|
}
|
||||||
|
inline const ::std::string& CodeGeneratorResponse::error() const {
|
||||||
|
return *error_;
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
|
||||||
|
set_has_error();
|
||||||
|
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
error_ = new ::std::string;
|
||||||
|
}
|
||||||
|
error_->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse::set_error(const char* value) {
|
||||||
|
set_has_error();
|
||||||
|
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
error_ = new ::std::string;
|
||||||
|
}
|
||||||
|
error_->assign(value);
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
|
||||||
|
set_has_error();
|
||||||
|
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
error_ = new ::std::string;
|
||||||
|
}
|
||||||
|
error_->assign(reinterpret_cast<const char*>(value), size);
|
||||||
|
}
|
||||||
|
inline ::std::string* CodeGeneratorResponse::mutable_error() {
|
||||||
|
set_has_error();
|
||||||
|
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
error_ = new ::std::string;
|
||||||
|
}
|
||||||
|
return error_;
|
||||||
|
}
|
||||||
|
inline ::std::string* CodeGeneratorResponse::release_error() {
|
||||||
|
clear_has_error();
|
||||||
|
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
::std::string* temp = error_;
|
||||||
|
error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||||
|
inline int CodeGeneratorResponse::file_size() const {
|
||||||
|
return file_.size();
|
||||||
|
}
|
||||||
|
inline void CodeGeneratorResponse::clear_file() {
|
||||||
|
file_.Clear();
|
||||||
|
}
|
||||||
|
inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
|
||||||
|
return file_.Get(index);
|
||||||
|
}
|
||||||
|
inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
|
||||||
|
return file_.Mutable(index);
|
||||||
|
}
|
||||||
|
inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
|
||||||
|
return file_.Add();
|
||||||
|
}
|
||||||
|
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
|
||||||
|
CodeGeneratorResponse::file() const {
|
||||||
|
return file_;
|
||||||
|
}
|
||||||
|
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
|
||||||
|
CodeGeneratorResponse::mutable_file() {
|
||||||
|
return &file_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @@protoc_insertion_point(namespace_scope)
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
|
|
||||||
|
#ifndef SWIG
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
} // namespace protobuf
|
||||||
|
#endif // SWIG
|
||||||
|
|
||||||
|
// @@protoc_insertion_point(global_scope)
|
||||||
|
|
||||||
|
#endif // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
|
@ -0,0 +1,218 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: ambrose@google.com (Ambrose Feinstein),
|
||||||
|
// kenton@google.com (Kenton Varda)
|
||||||
|
//
|
||||||
|
// Based on http://www.pkware.com/documents/casestudies/APPNOTE.TXT
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/zip_writer.h>
|
||||||
|
#include <google/protobuf/io/coded_stream.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
static const uint32 kCRC32Table[256] = {
|
||||||
|
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||||
|
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||||
|
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||||
|
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||||
|
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||||
|
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||||
|
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||||
|
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||||
|
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||||
|
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||||
|
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||||
|
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||||
|
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||||
|
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||||
|
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||||
|
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||||
|
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||||
|
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||||
|
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||||
|
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||||
|
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||||
|
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||||
|
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||||
|
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||||
|
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||||
|
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||||
|
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||||
|
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||||
|
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||||
|
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||||
|
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||||
|
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||||
|
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||||
|
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||||
|
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||||
|
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||||
|
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||||
|
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||||
|
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||||
|
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||||
|
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||||
|
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||||
|
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32 ComputeCRC32(const string &buf) {
|
||||||
|
uint32 x = ~0U;
|
||||||
|
for (int i = 0; i < buf.size(); ++i) {
|
||||||
|
unsigned char c = buf[i];
|
||||||
|
x = kCRC32Table[(x ^ c) & 0xff] ^ (x >> 8);
|
||||||
|
}
|
||||||
|
return ~x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteShort(io::CodedOutputStream *out, uint16 val) {
|
||||||
|
uint8 p[2];
|
||||||
|
p[0] = static_cast<uint8>(val);
|
||||||
|
p[1] = static_cast<uint8>(val >> 8);
|
||||||
|
out->WriteRaw(p, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipWriter::ZipWriter(io::ZeroCopyOutputStream* raw_output)
|
||||||
|
: raw_output_(raw_output) {}
|
||||||
|
ZipWriter::~ZipWriter() {}
|
||||||
|
|
||||||
|
bool ZipWriter::Write(const string& filename, const string& contents) {
|
||||||
|
FileInfo info;
|
||||||
|
|
||||||
|
info.name = filename;
|
||||||
|
uint16 filename_size = filename.size();
|
||||||
|
info.offset = raw_output_->ByteCount();
|
||||||
|
info.size = contents.size();
|
||||||
|
info.crc32 = ComputeCRC32(contents);
|
||||||
|
|
||||||
|
files_.push_back(info);
|
||||||
|
|
||||||
|
// write file header
|
||||||
|
io::CodedOutputStream output(raw_output_);
|
||||||
|
output.WriteLittleEndian32(0x04034b50); // magic
|
||||||
|
WriteShort(&output, 10); // version needed to extract
|
||||||
|
WriteShort(&output, 0); // flags
|
||||||
|
WriteShort(&output, 0); // compression method: stored
|
||||||
|
WriteShort(&output, 0); // last modified time
|
||||||
|
WriteShort(&output, 0); // last modified date
|
||||||
|
output.WriteLittleEndian32(info.crc32); // crc-32
|
||||||
|
output.WriteLittleEndian32(info.size); // compressed size
|
||||||
|
output.WriteLittleEndian32(info.size); // uncompressed size
|
||||||
|
WriteShort(&output, filename_size); // file name length
|
||||||
|
WriteShort(&output, 0); // extra field length
|
||||||
|
output.WriteString(filename); // file name
|
||||||
|
output.WriteString(contents); // file data
|
||||||
|
|
||||||
|
return !output.HadError();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZipWriter::WriteDirectory() {
|
||||||
|
uint16 num_entries = files_.size();
|
||||||
|
uint32 dir_ofs = raw_output_->ByteCount();
|
||||||
|
|
||||||
|
// write central directory
|
||||||
|
io::CodedOutputStream output(raw_output_);
|
||||||
|
for (int i = 0; i < num_entries; ++i) {
|
||||||
|
const string &filename = files_[i].name;
|
||||||
|
uint16 filename_size = filename.size();
|
||||||
|
uint32 crc32 = files_[i].crc32;
|
||||||
|
uint32 size = files_[i].size;
|
||||||
|
uint32 offset = files_[i].offset;
|
||||||
|
|
||||||
|
output.WriteLittleEndian32(0x02014b50); // magic
|
||||||
|
WriteShort(&output, 10); // version made by
|
||||||
|
WriteShort(&output, 10); // version needed to extract
|
||||||
|
WriteShort(&output, 0); // flags
|
||||||
|
WriteShort(&output, 0); // compression method: stored
|
||||||
|
WriteShort(&output, 0); // last modified time
|
||||||
|
WriteShort(&output, 0); // last modified date
|
||||||
|
output.WriteLittleEndian32(crc32); // crc-32
|
||||||
|
output.WriteLittleEndian32(size); // compressed size
|
||||||
|
output.WriteLittleEndian32(size); // uncompressed size
|
||||||
|
WriteShort(&output, filename_size); // file name length
|
||||||
|
WriteShort(&output, 0); // extra field length
|
||||||
|
WriteShort(&output, 0); // file comment length
|
||||||
|
WriteShort(&output, 0); // starting disk number
|
||||||
|
WriteShort(&output, 0); // internal file attributes
|
||||||
|
output.WriteLittleEndian32(0); // external file attributes
|
||||||
|
output.WriteLittleEndian32(offset); // local header offset
|
||||||
|
output.WriteString(filename); // file name
|
||||||
|
}
|
||||||
|
uint32 dir_len = output.ByteCount();
|
||||||
|
|
||||||
|
// write end of central directory marker
|
||||||
|
output.WriteLittleEndian32(0x06054b50); // magic
|
||||||
|
WriteShort(&output, 0); // disk number
|
||||||
|
WriteShort(&output, 0); // disk with start of central directory
|
||||||
|
WriteShort(&output, num_entries); // central directory entries (this disk)
|
||||||
|
WriteShort(&output, num_entries); // central directory entries (total)
|
||||||
|
output.WriteLittleEndian32(dir_len); // central directory byte size
|
||||||
|
output.WriteLittleEndian32(dir_ofs); // central directory offset
|
||||||
|
WriteShort(&output, 0); // comment length
|
||||||
|
|
||||||
|
return output.HadError();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,93 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
class ZipWriter {
|
||||||
|
public:
|
||||||
|
ZipWriter(io::ZeroCopyOutputStream* raw_output);
|
||||||
|
~ZipWriter();
|
||||||
|
|
||||||
|
bool Write(const string& filename, const string& contents);
|
||||||
|
bool WriteDirectory();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct FileInfo {
|
||||||
|
string name;
|
||||||
|
uint32 offset;
|
||||||
|
uint32 size;
|
||||||
|
uint32 crc32;
|
||||||
|
};
|
||||||
|
|
||||||
|
io::ZeroCopyOutputStream* raw_output_;
|
||||||
|
vector<FileInfo> files_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,541 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/descriptor_database.h>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
#include <google/protobuf/wire_format_lite_inl.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
#include <google/protobuf/stubs/stl_util-inl.h>
|
||||||
|
#include <google/protobuf/stubs/map-util.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
|
||||||
|
DescriptorDatabase::~DescriptorDatabase() {}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddFile(
|
||||||
|
const FileDescriptorProto& file,
|
||||||
|
Value value) {
|
||||||
|
if (!InsertIfNotPresent(&by_name_, file.name(), value)) {
|
||||||
|
GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must be careful here -- calling file.package() if file.has_package() is
|
||||||
|
// false could access an uninitialized static-storage variable if we are being
|
||||||
|
// run at startup time.
|
||||||
|
string path = file.has_package() ? file.package() : string();
|
||||||
|
if (!path.empty()) path += '.';
|
||||||
|
|
||||||
|
for (int i = 0; i < file.message_type_size(); i++) {
|
||||||
|
if (!AddSymbol(path + file.message_type(i).name(), value)) return false;
|
||||||
|
if (!AddNestedExtensions(file.message_type(i), value)) return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < file.enum_type_size(); i++) {
|
||||||
|
if (!AddSymbol(path + file.enum_type(i).name(), value)) return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < file.extension_size(); i++) {
|
||||||
|
if (!AddSymbol(path + file.extension(i).name(), value)) return false;
|
||||||
|
if (!AddExtension(file.extension(i), value)) return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < file.service_size(); i++) {
|
||||||
|
if (!AddSymbol(path + file.service(i).name(), value)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol(
|
||||||
|
const string& name, Value value) {
|
||||||
|
// We need to make sure not to violate our map invariant.
|
||||||
|
|
||||||
|
// If the symbol name is invalid it could break our lookup algorithm (which
|
||||||
|
// relies on the fact that '.' sorts before all other characters that are
|
||||||
|
// valid in symbol names).
|
||||||
|
if (!ValidateSymbolName(name)) {
|
||||||
|
GOOGLE_LOG(ERROR) << "Invalid symbol name: " << name;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to look up the symbol to make sure a super-symbol doesn't already
|
||||||
|
// exist.
|
||||||
|
typename map<string, Value>::iterator iter = FindLastLessOrEqual(name);
|
||||||
|
|
||||||
|
if (iter == by_symbol_.end()) {
|
||||||
|
// Apparently the map is currently empty. Just insert and be done with it.
|
||||||
|
by_symbol_.insert(typename map<string, Value>::value_type(name, value));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsSubSymbol(iter->first, name)) {
|
||||||
|
GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing "
|
||||||
|
"symbol \"" << iter->first << "\".";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OK, that worked. Now we have to make sure that no symbol in the map is
|
||||||
|
// a sub-symbol of the one we are inserting. The only symbol which could
|
||||||
|
// be so is the first symbol that is greater than the new symbol. Since
|
||||||
|
// |iter| points at the last symbol that is less than or equal, we just have
|
||||||
|
// to increment it.
|
||||||
|
++iter;
|
||||||
|
|
||||||
|
if (iter != by_symbol_.end() && IsSubSymbol(name, iter->first)) {
|
||||||
|
GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing "
|
||||||
|
"symbol \"" << iter->first << "\".";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OK, no conflicts.
|
||||||
|
|
||||||
|
// Insert the new symbol using the iterator as a hint, the new entry will
|
||||||
|
// appear immediately before the one the iterator is pointing at.
|
||||||
|
by_symbol_.insert(iter, typename map<string, Value>::value_type(name, value));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddNestedExtensions(
|
||||||
|
const DescriptorProto& message_type,
|
||||||
|
Value value) {
|
||||||
|
for (int i = 0; i < message_type.nested_type_size(); i++) {
|
||||||
|
if (!AddNestedExtensions(message_type.nested_type(i), value)) return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < message_type.extension_size(); i++) {
|
||||||
|
if (!AddExtension(message_type.extension(i), value)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddExtension(
|
||||||
|
const FieldDescriptorProto& field,
|
||||||
|
Value value) {
|
||||||
|
if (!field.extendee().empty() && field.extendee()[0] == '.') {
|
||||||
|
// The extension is fully-qualified. We can use it as a lookup key in
|
||||||
|
// the by_symbol_ table.
|
||||||
|
if (!InsertIfNotPresent(&by_extension_,
|
||||||
|
make_pair(field.extendee().substr(1),
|
||||||
|
field.number()),
|
||||||
|
value)) {
|
||||||
|
GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: "
|
||||||
|
"extend " << field.extendee() << " { "
|
||||||
|
<< field.name() << " = " << field.number() << " }";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Not fully-qualified. We can't really do anything here, unfortunately.
|
||||||
|
// We don't consider this an error, though, because the descriptor is
|
||||||
|
// valid.
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindFile(
|
||||||
|
const string& filename) {
|
||||||
|
return FindWithDefault(by_name_, filename, Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindSymbol(
|
||||||
|
const string& name) {
|
||||||
|
typename map<string, Value>::iterator iter = FindLastLessOrEqual(name);
|
||||||
|
|
||||||
|
return (iter != by_symbol_.end() && IsSubSymbol(iter->first, name)) ?
|
||||||
|
iter->second : Value();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension(
|
||||||
|
const string& containing_type,
|
||||||
|
int field_number) {
|
||||||
|
return FindWithDefault(by_extension_,
|
||||||
|
make_pair(containing_type, field_number),
|
||||||
|
Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers(
|
||||||
|
const string& containing_type,
|
||||||
|
vector<int>* output) {
|
||||||
|
typename map<pair<string, int>, Value >::const_iterator it =
|
||||||
|
by_extension_.lower_bound(make_pair(containing_type, 0));
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
for (; it != by_extension_.end() && it->first.first == containing_type;
|
||||||
|
++it) {
|
||||||
|
output->push_back(it->first.second);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
typename map<string, Value>::iterator
|
||||||
|
SimpleDescriptorDatabase::DescriptorIndex<Value>::FindLastLessOrEqual(
|
||||||
|
const string& name) {
|
||||||
|
// Find the last key in the map which sorts less than or equal to the
|
||||||
|
// symbol name. Since upper_bound() returns the *first* key that sorts
|
||||||
|
// *greater* than the input, we want the element immediately before that.
|
||||||
|
typename map<string, Value>::iterator iter = by_symbol_.upper_bound(name);
|
||||||
|
if (iter != by_symbol_.begin()) --iter;
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::IsSubSymbol(
|
||||||
|
const string& sub_symbol, const string& super_symbol) {
|
||||||
|
return sub_symbol == super_symbol ||
|
||||||
|
(HasPrefixString(super_symbol, sub_symbol) &&
|
||||||
|
super_symbol[sub_symbol.size()] == '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::ValidateSymbolName(
|
||||||
|
const string& name) {
|
||||||
|
for (int i = 0; i < name.size(); i++) {
|
||||||
|
// I don't trust ctype.h due to locales. :(
|
||||||
|
if (name[i] != '.' && name[i] != '_' &&
|
||||||
|
(name[i] < '0' || name[i] > '9') &&
|
||||||
|
(name[i] < 'A' || name[i] > 'Z') &&
|
||||||
|
(name[i] < 'a' || name[i] > 'z')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
SimpleDescriptorDatabase::SimpleDescriptorDatabase() {}
|
||||||
|
SimpleDescriptorDatabase::~SimpleDescriptorDatabase() {
|
||||||
|
STLDeleteElements(&files_to_delete_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) {
|
||||||
|
FileDescriptorProto* new_file = new FileDescriptorProto;
|
||||||
|
new_file->CopyFrom(file);
|
||||||
|
return AddAndOwn(new_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SimpleDescriptorDatabase::AddAndOwn(const FileDescriptorProto* file) {
|
||||||
|
files_to_delete_.push_back(file);
|
||||||
|
return index_.AddFile(*file, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SimpleDescriptorDatabase::FindFileByName(
|
||||||
|
const string& filename,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
return MaybeCopy(index_.FindFile(filename), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SimpleDescriptorDatabase::FindFileContainingSymbol(
|
||||||
|
const string& symbol_name,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
return MaybeCopy(index_.FindSymbol(symbol_name), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SimpleDescriptorDatabase::FindFileContainingExtension(
|
||||||
|
const string& containing_type,
|
||||||
|
int field_number,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
return MaybeCopy(index_.FindExtension(containing_type, field_number), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SimpleDescriptorDatabase::FindAllExtensionNumbers(
|
||||||
|
const string& extendee_type,
|
||||||
|
vector<int>* output) {
|
||||||
|
return index_.FindAllExtensionNumbers(extendee_type, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
if (file == NULL) return false;
|
||||||
|
output->CopyFrom(*file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
EncodedDescriptorDatabase::EncodedDescriptorDatabase() {}
|
||||||
|
EncodedDescriptorDatabase::~EncodedDescriptorDatabase() {
|
||||||
|
for (int i = 0; i < files_to_delete_.size(); i++) {
|
||||||
|
operator delete(files_to_delete_[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EncodedDescriptorDatabase::Add(
|
||||||
|
const void* encoded_file_descriptor, int size) {
|
||||||
|
FileDescriptorProto file;
|
||||||
|
if (file.ParseFromArray(encoded_file_descriptor, size)) {
|
||||||
|
return index_.AddFile(file, make_pair(encoded_file_descriptor, size));
|
||||||
|
} else {
|
||||||
|
GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to "
|
||||||
|
"EncodedDescriptorDatabase::Add().";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EncodedDescriptorDatabase::AddCopy(
|
||||||
|
const void* encoded_file_descriptor, int size) {
|
||||||
|
void* copy = operator new(size);
|
||||||
|
memcpy(copy, encoded_file_descriptor, size);
|
||||||
|
files_to_delete_.push_back(copy);
|
||||||
|
return Add(copy, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EncodedDescriptorDatabase::FindFileByName(
|
||||||
|
const string& filename,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
return MaybeParse(index_.FindFile(filename), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EncodedDescriptorDatabase::FindFileContainingSymbol(
|
||||||
|
const string& symbol_name,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
return MaybeParse(index_.FindSymbol(symbol_name), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EncodedDescriptorDatabase::FindNameOfFileContainingSymbol(
|
||||||
|
const string& symbol_name,
|
||||||
|
string* output) {
|
||||||
|
pair<const void*, int> encoded_file = index_.FindSymbol(symbol_name);
|
||||||
|
if (encoded_file.first == NULL) return false;
|
||||||
|
|
||||||
|
// Optimization: The name should be the first field in the encoded message.
|
||||||
|
// Try to just read it directly.
|
||||||
|
io::CodedInputStream input(reinterpret_cast<const uint8*>(encoded_file.first),
|
||||||
|
encoded_file.second);
|
||||||
|
|
||||||
|
const uint32 kNameTag = internal::WireFormatLite::MakeTag(
|
||||||
|
FileDescriptorProto::kNameFieldNumber,
|
||||||
|
internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
|
||||||
|
|
||||||
|
if (input.ReadTag() == kNameTag) {
|
||||||
|
// Success!
|
||||||
|
return internal::WireFormatLite::ReadString(&input, output);
|
||||||
|
} else {
|
||||||
|
// Slow path. Parse whole message.
|
||||||
|
FileDescriptorProto file_proto;
|
||||||
|
if (!file_proto.ParseFromArray(encoded_file.first, encoded_file.second)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*output = file_proto.name();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EncodedDescriptorDatabase::FindFileContainingExtension(
|
||||||
|
const string& containing_type,
|
||||||
|
int field_number,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
return MaybeParse(index_.FindExtension(containing_type, field_number),
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EncodedDescriptorDatabase::FindAllExtensionNumbers(
|
||||||
|
const string& extendee_type,
|
||||||
|
vector<int>* output) {
|
||||||
|
return index_.FindAllExtensionNumbers(extendee_type, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EncodedDescriptorDatabase::MaybeParse(
|
||||||
|
pair<const void*, int> encoded_file,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
if (encoded_file.first == NULL) return false;
|
||||||
|
return output->ParseFromArray(encoded_file.first, encoded_file.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
DescriptorPoolDatabase::DescriptorPoolDatabase(const DescriptorPool& pool)
|
||||||
|
: pool_(pool) {}
|
||||||
|
DescriptorPoolDatabase::~DescriptorPoolDatabase() {}
|
||||||
|
|
||||||
|
bool DescriptorPoolDatabase::FindFileByName(
|
||||||
|
const string& filename,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
const FileDescriptor* file = pool_.FindFileByName(filename);
|
||||||
|
if (file == NULL) return false;
|
||||||
|
output->Clear();
|
||||||
|
file->CopyTo(output);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DescriptorPoolDatabase::FindFileContainingSymbol(
|
||||||
|
const string& symbol_name,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
const FileDescriptor* file = pool_.FindFileContainingSymbol(symbol_name);
|
||||||
|
if (file == NULL) return false;
|
||||||
|
output->Clear();
|
||||||
|
file->CopyTo(output);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DescriptorPoolDatabase::FindFileContainingExtension(
|
||||||
|
const string& containing_type,
|
||||||
|
int field_number,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
const Descriptor* extendee = pool_.FindMessageTypeByName(containing_type);
|
||||||
|
if (extendee == NULL) return false;
|
||||||
|
|
||||||
|
const FieldDescriptor* extension =
|
||||||
|
pool_.FindExtensionByNumber(extendee, field_number);
|
||||||
|
if (extension == NULL) return false;
|
||||||
|
|
||||||
|
output->Clear();
|
||||||
|
extension->file()->CopyTo(output);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DescriptorPoolDatabase::FindAllExtensionNumbers(
|
||||||
|
const string& extendee_type,
|
||||||
|
vector<int>* output) {
|
||||||
|
const Descriptor* extendee = pool_.FindMessageTypeByName(extendee_type);
|
||||||
|
if (extendee == NULL) return false;
|
||||||
|
|
||||||
|
vector<const FieldDescriptor*> extensions;
|
||||||
|
pool_.FindAllExtensions(extendee, &extensions);
|
||||||
|
|
||||||
|
for (int i = 0; i < extensions.size(); ++i) {
|
||||||
|
output->push_back(extensions[i]->number());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
MergedDescriptorDatabase::MergedDescriptorDatabase(
|
||||||
|
DescriptorDatabase* source1,
|
||||||
|
DescriptorDatabase* source2) {
|
||||||
|
sources_.push_back(source1);
|
||||||
|
sources_.push_back(source2);
|
||||||
|
}
|
||||||
|
MergedDescriptorDatabase::MergedDescriptorDatabase(
|
||||||
|
const vector<DescriptorDatabase*>& sources)
|
||||||
|
: sources_(sources) {}
|
||||||
|
MergedDescriptorDatabase::~MergedDescriptorDatabase() {}
|
||||||
|
|
||||||
|
bool MergedDescriptorDatabase::FindFileByName(
|
||||||
|
const string& filename,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
for (int i = 0; i < sources_.size(); i++) {
|
||||||
|
if (sources_[i]->FindFileByName(filename, output)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MergedDescriptorDatabase::FindFileContainingSymbol(
|
||||||
|
const string& symbol_name,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
for (int i = 0; i < sources_.size(); i++) {
|
||||||
|
if (sources_[i]->FindFileContainingSymbol(symbol_name, output)) {
|
||||||
|
// The symbol was found in source i. However, if one of the previous
|
||||||
|
// sources defines a file with the same name (which presumably doesn't
|
||||||
|
// contain the symbol, since it wasn't found in that source), then we
|
||||||
|
// must hide it from the caller.
|
||||||
|
FileDescriptorProto temp;
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
if (sources_[j]->FindFileByName(output->name(), &temp)) {
|
||||||
|
// Found conflicting file in a previous source.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MergedDescriptorDatabase::FindFileContainingExtension(
|
||||||
|
const string& containing_type,
|
||||||
|
int field_number,
|
||||||
|
FileDescriptorProto* output) {
|
||||||
|
for (int i = 0; i < sources_.size(); i++) {
|
||||||
|
if (sources_[i]->FindFileContainingExtension(
|
||||||
|
containing_type, field_number, output)) {
|
||||||
|
// The symbol was found in source i. However, if one of the previous
|
||||||
|
// sources defines a file with the same name (which presumably doesn't
|
||||||
|
// contain the symbol, since it wasn't found in that source), then we
|
||||||
|
// must hide it from the caller.
|
||||||
|
FileDescriptorProto temp;
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
if (sources_[j]->FindFileByName(output->name(), &temp)) {
|
||||||
|
// Found conflicting file in a previous source.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MergedDescriptorDatabase::FindAllExtensionNumbers(
|
||||||
|
const string& extendee_type,
|
||||||
|
vector<int>* output) {
|
||||||
|
set<int> merged_results;
|
||||||
|
vector<int> results;
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < sources_.size(); i++) {
|
||||||
|
if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) {
|
||||||
|
copy(results.begin(), results.end(),
|
||||||
|
insert_iterator<set<int> >(merged_results, merged_results.begin()));
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
results.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(merged_results.begin(), merged_results.end(),
|
||||||
|
insert_iterator<vector<int> >(*output, output->end()));
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,558 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
//
|
||||||
|
// DynamicMessage is implemented by constructing a data structure which
|
||||||
|
// has roughly the same memory layout as a generated message would have.
|
||||||
|
// Then, we use GeneratedMessageReflection to implement our reflection
|
||||||
|
// interface. All the other operations we need to implement (e.g.
|
||||||
|
// parsing, copying, etc.) are already implemented in terms of
|
||||||
|
// Reflection, so the rest is easy.
|
||||||
|
//
|
||||||
|
// The up side of this strategy is that it's very efficient. We don't
|
||||||
|
// need to use hash_maps or generic representations of fields. The
|
||||||
|
// down side is that this is a low-level memory management hack which
|
||||||
|
// can be tricky to get right.
|
||||||
|
//
|
||||||
|
// As mentioned in the header, we only expose a DynamicMessageFactory
|
||||||
|
// publicly, not the DynamicMessage class itself. This is because
|
||||||
|
// GenericMessageReflection wants to have a pointer to a "default"
|
||||||
|
// copy of the class, with all fields initialized to their default
|
||||||
|
// values. We only want to construct one of these per message type,
|
||||||
|
// so DynamicMessageFactory stores a cache of default messages for
|
||||||
|
// each type it sees (each unique Descriptor pointer). The code
|
||||||
|
// refers to the "default" copy of the class as the "prototype".
|
||||||
|
//
|
||||||
|
// Note on memory allocation: This module often calls "operator new()"
|
||||||
|
// to allocate untyped memory, rather than calling something like
|
||||||
|
// "new uint8[]". This is because "operator new()" means "Give me some
|
||||||
|
// space which I can use as I please." while "new uint8[]" means "Give
|
||||||
|
// me an array of 8-bit integers.". In practice, the later may return
|
||||||
|
// a pointer that is not aligned correctly for general use. I believe
|
||||||
|
// Item 8 of "More Effective C++" discusses this in more detail, though
|
||||||
|
// I don't have the book on me right now so I'm not sure.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <google/protobuf/stubs/hash.h>
|
||||||
|
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
|
||||||
|
#include <google/protobuf/dynamic_message.h>
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
#include <google/protobuf/generated_message_util.h>
|
||||||
|
#include <google/protobuf/generated_message_reflection.h>
|
||||||
|
#include <google/protobuf/reflection_ops.h>
|
||||||
|
#include <google/protobuf/repeated_field.h>
|
||||||
|
#include <google/protobuf/extension_set.h>
|
||||||
|
#include <google/protobuf/wire_format.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
|
||||||
|
using internal::WireFormat;
|
||||||
|
using internal::ExtensionSet;
|
||||||
|
using internal::GeneratedMessageReflection;
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Some helper tables and functions...
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Compute the byte size of the in-memory representation of the field.
|
||||||
|
int FieldSpaceUsed(const FieldDescriptor* field) {
|
||||||
|
typedef FieldDescriptor FD; // avoid line wrapping
|
||||||
|
if (field->label() == FD::LABEL_REPEATED) {
|
||||||
|
switch (field->cpp_type()) {
|
||||||
|
case FD::CPPTYPE_INT32 : return sizeof(RepeatedField<int32 >);
|
||||||
|
case FD::CPPTYPE_INT64 : return sizeof(RepeatedField<int64 >);
|
||||||
|
case FD::CPPTYPE_UINT32 : return sizeof(RepeatedField<uint32 >);
|
||||||
|
case FD::CPPTYPE_UINT64 : return sizeof(RepeatedField<uint64 >);
|
||||||
|
case FD::CPPTYPE_DOUBLE : return sizeof(RepeatedField<double >);
|
||||||
|
case FD::CPPTYPE_FLOAT : return sizeof(RepeatedField<float >);
|
||||||
|
case FD::CPPTYPE_BOOL : return sizeof(RepeatedField<bool >);
|
||||||
|
case FD::CPPTYPE_ENUM : return sizeof(RepeatedField<int >);
|
||||||
|
case FD::CPPTYPE_MESSAGE: return sizeof(RepeatedPtrField<Message>);
|
||||||
|
|
||||||
|
case FD::CPPTYPE_STRING:
|
||||||
|
switch (field->options().ctype()) {
|
||||||
|
default: // TODO(kenton): Support other string reps.
|
||||||
|
case FieldOptions::STRING:
|
||||||
|
return sizeof(RepeatedPtrField<string>);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (field->cpp_type()) {
|
||||||
|
case FD::CPPTYPE_INT32 : return sizeof(int32 );
|
||||||
|
case FD::CPPTYPE_INT64 : return sizeof(int64 );
|
||||||
|
case FD::CPPTYPE_UINT32 : return sizeof(uint32 );
|
||||||
|
case FD::CPPTYPE_UINT64 : return sizeof(uint64 );
|
||||||
|
case FD::CPPTYPE_DOUBLE : return sizeof(double );
|
||||||
|
case FD::CPPTYPE_FLOAT : return sizeof(float );
|
||||||
|
case FD::CPPTYPE_BOOL : return sizeof(bool );
|
||||||
|
case FD::CPPTYPE_ENUM : return sizeof(int );
|
||||||
|
case FD::CPPTYPE_MESSAGE: return sizeof(Message*);
|
||||||
|
|
||||||
|
case FD::CPPTYPE_STRING:
|
||||||
|
switch (field->options().ctype()) {
|
||||||
|
default: // TODO(kenton): Support other string reps.
|
||||||
|
case FieldOptions::STRING:
|
||||||
|
return sizeof(string*);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GOOGLE_LOG(DFATAL) << "Can't get here.";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int DivideRoundingUp(int i, int j) {
|
||||||
|
return (i + (j - 1)) / j;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int kSafeAlignment = sizeof(uint64);
|
||||||
|
|
||||||
|
inline int AlignTo(int offset, int alignment) {
|
||||||
|
return DivideRoundingUp(offset, alignment) * alignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rounds the given byte offset up to the next offset aligned such that any
|
||||||
|
// type may be stored at it.
|
||||||
|
inline int AlignOffset(int offset) {
|
||||||
|
return AlignTo(offset, kSafeAlignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define bitsizeof(T) (sizeof(T) * 8)
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
class DynamicMessage : public Message {
|
||||||
|
public:
|
||||||
|
struct TypeInfo {
|
||||||
|
int size;
|
||||||
|
int has_bits_offset;
|
||||||
|
int unknown_fields_offset;
|
||||||
|
int extensions_offset;
|
||||||
|
|
||||||
|
// Not owned by the TypeInfo.
|
||||||
|
DynamicMessageFactory* factory; // The factory that created this object.
|
||||||
|
const DescriptorPool* pool; // The factory's DescriptorPool.
|
||||||
|
const Descriptor* type; // Type of this DynamicMessage.
|
||||||
|
|
||||||
|
// Warning: The order in which the following pointers are defined is
|
||||||
|
// important (the prototype must be deleted *before* the offsets).
|
||||||
|
scoped_array<int> offsets;
|
||||||
|
scoped_ptr<const GeneratedMessageReflection> reflection;
|
||||||
|
scoped_ptr<const DynamicMessage> prototype;
|
||||||
|
};
|
||||||
|
|
||||||
|
DynamicMessage(const TypeInfo* type_info);
|
||||||
|
~DynamicMessage();
|
||||||
|
|
||||||
|
// Called on the prototype after construction to initialize message fields.
|
||||||
|
void CrossLinkPrototypes();
|
||||||
|
|
||||||
|
// implements Message ----------------------------------------------
|
||||||
|
|
||||||
|
Message* New() const;
|
||||||
|
|
||||||
|
int GetCachedSize() const;
|
||||||
|
void SetCachedSize(int size) const;
|
||||||
|
|
||||||
|
Metadata GetMetadata() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
|
||||||
|
|
||||||
|
inline bool is_prototype() const {
|
||||||
|
return type_info_->prototype == this ||
|
||||||
|
// If type_info_->prototype is NULL, then we must be constructing
|
||||||
|
// the prototype now, which means we must be the prototype.
|
||||||
|
type_info_->prototype == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* OffsetToPointer(int offset) {
|
||||||
|
return reinterpret_cast<uint8*>(this) + offset;
|
||||||
|
}
|
||||||
|
inline const void* OffsetToPointer(int offset) const {
|
||||||
|
return reinterpret_cast<const uint8*>(this) + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TypeInfo* type_info_;
|
||||||
|
|
||||||
|
// TODO(kenton): Make this an atomic<int> when C++ supports it.
|
||||||
|
mutable int cached_byte_size_;
|
||||||
|
};
|
||||||
|
|
||||||
|
DynamicMessage::DynamicMessage(const TypeInfo* type_info)
|
||||||
|
: type_info_(type_info),
|
||||||
|
cached_byte_size_(0) {
|
||||||
|
// We need to call constructors for various fields manually and set
|
||||||
|
// default values where appropriate. We use placement new to call
|
||||||
|
// constructors. If you haven't heard of placement new, I suggest Googling
|
||||||
|
// it now. We use placement new even for primitive types that don't have
|
||||||
|
// constructors for consistency. (In theory, placement new should be used
|
||||||
|
// any time you are trying to convert untyped memory to typed memory, though
|
||||||
|
// in practice that's not strictly necessary for types that don't have a
|
||||||
|
// constructor.)
|
||||||
|
|
||||||
|
const Descriptor* descriptor = type_info_->type;
|
||||||
|
|
||||||
|
new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet;
|
||||||
|
|
||||||
|
if (type_info_->extensions_offset != -1) {
|
||||||
|
new(OffsetToPointer(type_info_->extensions_offset)) ExtensionSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||||
|
const FieldDescriptor* field = descriptor->field(i);
|
||||||
|
void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
|
||||||
|
switch (field->cpp_type()) {
|
||||||
|
#define HANDLE_TYPE(CPPTYPE, TYPE) \
|
||||||
|
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
||||||
|
if (!field->is_repeated()) { \
|
||||||
|
new(field_ptr) TYPE(field->default_value_##TYPE()); \
|
||||||
|
} else { \
|
||||||
|
new(field_ptr) RepeatedField<TYPE>(); \
|
||||||
|
} \
|
||||||
|
break;
|
||||||
|
|
||||||
|
HANDLE_TYPE(INT32 , int32 );
|
||||||
|
HANDLE_TYPE(INT64 , int64 );
|
||||||
|
HANDLE_TYPE(UINT32, uint32);
|
||||||
|
HANDLE_TYPE(UINT64, uint64);
|
||||||
|
HANDLE_TYPE(DOUBLE, double);
|
||||||
|
HANDLE_TYPE(FLOAT , float );
|
||||||
|
HANDLE_TYPE(BOOL , bool );
|
||||||
|
#undef HANDLE_TYPE
|
||||||
|
|
||||||
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
|
if (!field->is_repeated()) {
|
||||||
|
new(field_ptr) int(field->default_value_enum()->number());
|
||||||
|
} else {
|
||||||
|
new(field_ptr) RepeatedField<int>();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
|
switch (field->options().ctype()) {
|
||||||
|
default: // TODO(kenton): Support other string reps.
|
||||||
|
case FieldOptions::STRING:
|
||||||
|
if (!field->is_repeated()) {
|
||||||
|
if (is_prototype()) {
|
||||||
|
new(field_ptr) const string*(&field->default_value_string());
|
||||||
|
} else {
|
||||||
|
string* default_value =
|
||||||
|
*reinterpret_cast<string* const*>(
|
||||||
|
type_info_->prototype->OffsetToPointer(
|
||||||
|
type_info_->offsets[i]));
|
||||||
|
new(field_ptr) string*(default_value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new(field_ptr) RepeatedPtrField<string>();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE: {
|
||||||
|
if (!field->is_repeated()) {
|
||||||
|
new(field_ptr) Message*(NULL);
|
||||||
|
} else {
|
||||||
|
new(field_ptr) RepeatedPtrField<Message>();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicMessage::~DynamicMessage() {
|
||||||
|
const Descriptor* descriptor = type_info_->type;
|
||||||
|
|
||||||
|
reinterpret_cast<UnknownFieldSet*>(
|
||||||
|
OffsetToPointer(type_info_->unknown_fields_offset))->~UnknownFieldSet();
|
||||||
|
|
||||||
|
if (type_info_->extensions_offset != -1) {
|
||||||
|
reinterpret_cast<ExtensionSet*>(
|
||||||
|
OffsetToPointer(type_info_->extensions_offset))->~ExtensionSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to manually run the destructors for repeated fields and strings,
|
||||||
|
// just as we ran their constructors in the the DynamicMessage constructor.
|
||||||
|
// Additionally, if any singular embedded messages have been allocated, we
|
||||||
|
// need to delete them, UNLESS we are the prototype message of this type,
|
||||||
|
// in which case any embedded messages are other prototypes and shouldn't
|
||||||
|
// be touched.
|
||||||
|
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||||
|
const FieldDescriptor* field = descriptor->field(i);
|
||||||
|
void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
|
||||||
|
|
||||||
|
if (field->is_repeated()) {
|
||||||
|
switch (field->cpp_type()) {
|
||||||
|
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
|
||||||
|
case FieldDescriptor::CPPTYPE_##UPPERCASE : \
|
||||||
|
reinterpret_cast<RepeatedField<LOWERCASE>*>(field_ptr) \
|
||||||
|
->~RepeatedField<LOWERCASE>(); \
|
||||||
|
break
|
||||||
|
|
||||||
|
HANDLE_TYPE( INT32, int32);
|
||||||
|
HANDLE_TYPE( INT64, int64);
|
||||||
|
HANDLE_TYPE(UINT32, uint32);
|
||||||
|
HANDLE_TYPE(UINT64, uint64);
|
||||||
|
HANDLE_TYPE(DOUBLE, double);
|
||||||
|
HANDLE_TYPE( FLOAT, float);
|
||||||
|
HANDLE_TYPE( BOOL, bool);
|
||||||
|
HANDLE_TYPE( ENUM, int);
|
||||||
|
#undef HANDLE_TYPE
|
||||||
|
|
||||||
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
|
switch (field->options().ctype()) {
|
||||||
|
default: // TODO(kenton): Support other string reps.
|
||||||
|
case FieldOptions::STRING:
|
||||||
|
reinterpret_cast<RepeatedPtrField<string>*>(field_ptr)
|
||||||
|
->~RepeatedPtrField<string>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
|
reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
|
||||||
|
->~RepeatedPtrField<Message>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
||||||
|
switch (field->options().ctype()) {
|
||||||
|
default: // TODO(kenton): Support other string reps.
|
||||||
|
case FieldOptions::STRING: {
|
||||||
|
string* ptr = *reinterpret_cast<string**>(field_ptr);
|
||||||
|
if (ptr != &field->default_value_string()) {
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) &&
|
||||||
|
!is_prototype()) {
|
||||||
|
Message* message = *reinterpret_cast<Message**>(field_ptr);
|
||||||
|
if (message != NULL) {
|
||||||
|
delete message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicMessage::CrossLinkPrototypes() {
|
||||||
|
// This should only be called on the prototype message.
|
||||||
|
GOOGLE_CHECK(is_prototype());
|
||||||
|
|
||||||
|
DynamicMessageFactory* factory = type_info_->factory;
|
||||||
|
const Descriptor* descriptor = type_info_->type;
|
||||||
|
|
||||||
|
// Cross-link default messages.
|
||||||
|
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||||
|
const FieldDescriptor* field = descriptor->field(i);
|
||||||
|
void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
|
||||||
|
|
||||||
|
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
|
||||||
|
!field->is_repeated()) {
|
||||||
|
// For fields with message types, we need to cross-link with the
|
||||||
|
// prototype for the field's type.
|
||||||
|
// For singular fields, the field is just a pointer which should
|
||||||
|
// point to the prototype.
|
||||||
|
*reinterpret_cast<const Message**>(field_ptr) =
|
||||||
|
factory->GetPrototypeNoLock(field->message_type());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Message* DynamicMessage::New() const {
|
||||||
|
void* new_base = reinterpret_cast<uint8*>(operator new(type_info_->size));
|
||||||
|
memset(new_base, 0, type_info_->size);
|
||||||
|
return new(new_base) DynamicMessage(type_info_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DynamicMessage::GetCachedSize() const {
|
||||||
|
return cached_byte_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicMessage::SetCachedSize(int size) const {
|
||||||
|
// This is theoretically not thread-compatible, but in practice it works
|
||||||
|
// because if multiple threads write this simultaneously, they will be
|
||||||
|
// writing the exact same value.
|
||||||
|
cached_byte_size_ = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
Metadata DynamicMessage::GetMetadata() const {
|
||||||
|
Metadata metadata;
|
||||||
|
metadata.descriptor = type_info_->type;
|
||||||
|
metadata.reflection = type_info_->reflection.get();
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
struct DynamicMessageFactory::PrototypeMap {
|
||||||
|
typedef hash_map<const Descriptor*, const DynamicMessage::TypeInfo*> Map;
|
||||||
|
Map map_;
|
||||||
|
};
|
||||||
|
|
||||||
|
DynamicMessageFactory::DynamicMessageFactory()
|
||||||
|
: pool_(NULL), delegate_to_generated_factory_(false),
|
||||||
|
prototypes_(new PrototypeMap) {
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
|
||||||
|
: pool_(pool), delegate_to_generated_factory_(false),
|
||||||
|
prototypes_(new PrototypeMap) {
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicMessageFactory::~DynamicMessageFactory() {
|
||||||
|
for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin();
|
||||||
|
iter != prototypes_->map_.end(); ++iter) {
|
||||||
|
delete iter->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
|
||||||
|
MutexLock lock(&prototypes_mutex_);
|
||||||
|
return GetPrototypeNoLock(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Message* DynamicMessageFactory::GetPrototypeNoLock(
|
||||||
|
const Descriptor* type) {
|
||||||
|
if (delegate_to_generated_factory_ &&
|
||||||
|
type->file()->pool() == DescriptorPool::generated_pool()) {
|
||||||
|
return MessageFactory::generated_factory()->GetPrototype(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
|
||||||
|
if (*target != NULL) {
|
||||||
|
// Already exists.
|
||||||
|
return (*target)->prototype.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
|
||||||
|
*target = type_info;
|
||||||
|
|
||||||
|
type_info->type = type;
|
||||||
|
type_info->pool = (pool_ == NULL) ? type->file()->pool() : pool_;
|
||||||
|
type_info->factory = this;
|
||||||
|
|
||||||
|
// We need to construct all the structures passed to
|
||||||
|
// GeneratedMessageReflection's constructor. This includes:
|
||||||
|
// - A block of memory that contains space for all the message's fields.
|
||||||
|
// - An array of integers indicating the byte offset of each field within
|
||||||
|
// this block.
|
||||||
|
// - A big bitfield containing a bit for each field indicating whether
|
||||||
|
// or not that field is set.
|
||||||
|
|
||||||
|
// Compute size and offsets.
|
||||||
|
int* offsets = new int[type->field_count()];
|
||||||
|
type_info->offsets.reset(offsets);
|
||||||
|
|
||||||
|
// Decide all field offsets by packing in order.
|
||||||
|
// We place the DynamicMessage object itself at the beginning of the allocated
|
||||||
|
// space.
|
||||||
|
int size = sizeof(DynamicMessage);
|
||||||
|
size = AlignOffset(size);
|
||||||
|
|
||||||
|
// Next the has_bits, which is an array of uint32s.
|
||||||
|
type_info->has_bits_offset = size;
|
||||||
|
int has_bits_array_size =
|
||||||
|
DivideRoundingUp(type->field_count(), bitsizeof(uint32));
|
||||||
|
size += has_bits_array_size * sizeof(uint32);
|
||||||
|
size = AlignOffset(size);
|
||||||
|
|
||||||
|
// The ExtensionSet, if any.
|
||||||
|
if (type->extension_range_count() > 0) {
|
||||||
|
type_info->extensions_offset = size;
|
||||||
|
size += sizeof(ExtensionSet);
|
||||||
|
size = AlignOffset(size);
|
||||||
|
} else {
|
||||||
|
// No extensions.
|
||||||
|
type_info->extensions_offset = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All the fields.
|
||||||
|
for (int i = 0; i < type->field_count(); i++) {
|
||||||
|
// Make sure field is aligned to avoid bus errors.
|
||||||
|
int field_size = FieldSpaceUsed(type->field(i));
|
||||||
|
size = AlignTo(size, min(kSafeAlignment, field_size));
|
||||||
|
offsets[i] = size;
|
||||||
|
size += field_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the UnknownFieldSet to the end.
|
||||||
|
size = AlignOffset(size);
|
||||||
|
type_info->unknown_fields_offset = size;
|
||||||
|
size += sizeof(UnknownFieldSet);
|
||||||
|
|
||||||
|
// Align the final size to make sure no clever allocators think that
|
||||||
|
// alignment is not necessary.
|
||||||
|
size = AlignOffset(size);
|
||||||
|
type_info->size = size;
|
||||||
|
|
||||||
|
// Allocate the prototype.
|
||||||
|
void* base = operator new(size);
|
||||||
|
memset(base, 0, size);
|
||||||
|
DynamicMessage* prototype = new(base) DynamicMessage(type_info);
|
||||||
|
type_info->prototype.reset(prototype);
|
||||||
|
|
||||||
|
// Construct the reflection object.
|
||||||
|
type_info->reflection.reset(
|
||||||
|
new GeneratedMessageReflection(
|
||||||
|
type_info->type,
|
||||||
|
type_info->prototype.get(),
|
||||||
|
type_info->offsets.get(),
|
||||||
|
type_info->has_bits_offset,
|
||||||
|
type_info->unknown_fields_offset,
|
||||||
|
type_info->extensions_offset,
|
||||||
|
type_info->pool,
|
||||||
|
this,
|
||||||
|
type_info->size));
|
||||||
|
|
||||||
|
// Cross link prototypes.
|
||||||
|
prototype->CrossLinkPrototypes();
|
||||||
|
|
||||||
|
return prototype;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,904 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
//
|
||||||
|
// 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_EXTENSION_SET_H__
|
||||||
|
#define GOOGLE_PROTOBUF_EXTENSION_SET_H__
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
|
||||||
|
namespace protobuf {
|
||||||
|
class Descriptor; // descriptor.h
|
||||||
|
class FieldDescriptor; // descriptor.h
|
||||||
|
class DescriptorPool; // descriptor.h
|
||||||
|
class MessageLite; // message_lite.h
|
||||||
|
class Message; // message.h
|
||||||
|
class MessageFactory; // message.h
|
||||||
|
class UnknownFieldSet; // unknown_field_set.h
|
||||||
|
namespace io {
|
||||||
|
class CodedInputStream; // coded_stream.h
|
||||||
|
class CodedOutputStream; // coded_stream.h
|
||||||
|
}
|
||||||
|
namespace internal {
|
||||||
|
class FieldSkipper; // wire_format_lite.h
|
||||||
|
class RepeatedPtrFieldBase; // repeated_field.h
|
||||||
|
}
|
||||||
|
template <typename Element> class RepeatedField; // repeated_field.h
|
||||||
|
template <typename Element> class RepeatedPtrField; // repeated_field.h
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace protobuf {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Used to store values of type WireFormatLite::FieldType without having to
|
||||||
|
// #include wire_format_lite.h. Also, ensures that we use only one byte to
|
||||||
|
// store these values, which is important to keep the layout of
|
||||||
|
// ExtensionSet::Extension small.
|
||||||
|
typedef uint8 FieldType;
|
||||||
|
|
||||||
|
// A function which, given an integer value, returns true if the number
|
||||||
|
// matches one of the defined values for the corresponding enum type. This
|
||||||
|
// is used with RegisterEnumExtension, below.
|
||||||
|
typedef bool EnumValidityFunc(int number);
|
||||||
|
|
||||||
|
// Version of the above which takes an argument. This is needed to deal with
|
||||||
|
// extensions that are not compiled in.
|
||||||
|
typedef bool EnumValidityFuncWithArg(const void* arg, int number);
|
||||||
|
|
||||||
|
// Information about a registered extension.
|
||||||
|
struct ExtensionInfo {
|
||||||
|
inline ExtensionInfo() {}
|
||||||
|
inline ExtensionInfo(FieldType type, bool is_repeated, bool is_packed)
|
||||||
|
: type(type), is_repeated(is_repeated), is_packed(is_packed),
|
||||||
|
descriptor(NULL) {}
|
||||||
|
|
||||||
|
FieldType type;
|
||||||
|
bool is_repeated;
|
||||||
|
bool is_packed;
|
||||||
|
|
||||||
|
struct EnumValidityCheck {
|
||||||
|
EnumValidityFuncWithArg* func;
|
||||||
|
const void* arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
EnumValidityCheck enum_validity_check;
|
||||||
|
const MessageLite* message_prototype;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The descriptor for this extension, if one exists and is known. May be
|
||||||
|
// NULL. Must not be NULL if the descriptor for the extension does not
|
||||||
|
// live in the same pool as the descriptor for the containing type.
|
||||||
|
const FieldDescriptor* descriptor;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Abstract interface for an object which looks up extension definitions. Used
|
||||||
|
// when parsing.
|
||||||
|
class LIBPROTOBUF_EXPORT ExtensionFinder {
|
||||||
|
public:
|
||||||
|
virtual ~ExtensionFinder();
|
||||||
|
|
||||||
|
// Find the extension with the given containing type and number.
|
||||||
|
virtual bool Find(int number, ExtensionInfo* output) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation of ExtensionFinder which finds extensions defined in .proto
|
||||||
|
// files which have been compiled into the binary.
|
||||||
|
class LIBPROTOBUF_EXPORT GeneratedExtensionFinder : public ExtensionFinder {
|
||||||
|
public:
|
||||||
|
GeneratedExtensionFinder(const MessageLite* containing_type)
|
||||||
|
: containing_type_(containing_type) {}
|
||||||
|
virtual ~GeneratedExtensionFinder() {}
|
||||||
|
|
||||||
|
// Returns true and fills in *output if found, otherwise returns false.
|
||||||
|
virtual bool Find(int number, ExtensionInfo* output);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const MessageLite* containing_type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Note: extension_set_heavy.cc defines DescriptorPoolExtensionFinder for
|
||||||
|
// finding extensions from a DescriptorPool.
|
||||||
|
|
||||||
|
// This is an internal helper class intended for use within the protocol buffer
|
||||||
|
// library and generated classes. Clients should not use it directly. Instead,
|
||||||
|
// use the generated accessors such as GetExtension() of the class being
|
||||||
|
// extended.
|
||||||
|
//
|
||||||
|
// This class manages extensions for a protocol message object. The
|
||||||
|
// message's HasExtension(), GetExtension(), MutableExtension(), and
|
||||||
|
// ClearExtension() methods are just thin wrappers around the embedded
|
||||||
|
// ExtensionSet. When parsing, if a tag number is encountered which is
|
||||||
|
// inside one of the message type's extension ranges, the tag is passed
|
||||||
|
// off to the ExtensionSet for parsing. Etc.
|
||||||
|
class LIBPROTOBUF_EXPORT ExtensionSet {
|
||||||
|
public:
|
||||||
|
ExtensionSet();
|
||||||
|
~ExtensionSet();
|
||||||
|
|
||||||
|
// These are called at startup by protocol-compiler-generated code to
|
||||||
|
// register known extensions. The registrations are used by ParseField()
|
||||||
|
// to look up extensions for parsed field numbers. Note that dynamic parsing
|
||||||
|
// does not use ParseField(); only protocol-compiler-generated parsing
|
||||||
|
// methods do.
|
||||||
|
static void RegisterExtension(const MessageLite* containing_type,
|
||||||
|
int number, FieldType type,
|
||||||
|
bool is_repeated, bool is_packed);
|
||||||
|
static void RegisterEnumExtension(const MessageLite* containing_type,
|
||||||
|
int number, FieldType type,
|
||||||
|
bool is_repeated, bool is_packed,
|
||||||
|
EnumValidityFunc* is_valid);
|
||||||
|
static void RegisterMessageExtension(const MessageLite* containing_type,
|
||||||
|
int number, FieldType type,
|
||||||
|
bool is_repeated, bool is_packed,
|
||||||
|
const MessageLite* prototype);
|
||||||
|
|
||||||
|
// =================================================================
|
||||||
|
|
||||||
|
// Add all fields which are currently present to the given vector. This
|
||||||
|
// is useful to implement Reflection::ListFields().
|
||||||
|
void AppendToList(const Descriptor* containing_type,
|
||||||
|
const DescriptorPool* pool,
|
||||||
|
vector<const FieldDescriptor*>* output) const;
|
||||||
|
|
||||||
|
// =================================================================
|
||||||
|
// Accessors
|
||||||
|
//
|
||||||
|
// Generated message classes include type-safe templated wrappers around
|
||||||
|
// these methods. Generally you should use those rather than call these
|
||||||
|
// directly, unless you are doing low-level memory management.
|
||||||
|
//
|
||||||
|
// When calling any of these accessors, the extension number requested
|
||||||
|
// MUST exist in the DescriptorPool provided to the constructor. Otheriwse,
|
||||||
|
// the method will fail an assert. Normally, though, you would not call
|
||||||
|
// these directly; you would either call the generated accessors of your
|
||||||
|
// message class (e.g. GetExtension()) or you would call the accessors
|
||||||
|
// of the reflection interface. In both cases, it is impossible to
|
||||||
|
// trigger this assert failure: the generated accessors only accept
|
||||||
|
// linked-in extension types as parameters, while the Reflection interface
|
||||||
|
// requires you to provide the FieldDescriptor describing the extension.
|
||||||
|
//
|
||||||
|
// When calling any of these accessors, a protocol-compiler-generated
|
||||||
|
// implementation of the extension corresponding to the number MUST
|
||||||
|
// be linked in, and the FieldDescriptor used to refer to it MUST be
|
||||||
|
// the one generated by that linked-in code. Otherwise, the method will
|
||||||
|
// die on an assert failure. The message objects returned by the message
|
||||||
|
// accessors are guaranteed to be of the correct linked-in type.
|
||||||
|
//
|
||||||
|
// These methods pretty much match Reflection except that:
|
||||||
|
// - They're not virtual.
|
||||||
|
// - They identify fields by number rather than FieldDescriptors.
|
||||||
|
// - They identify enum values using integers rather than descriptors.
|
||||||
|
// - Strings provide Mutable() in addition to Set() accessors.
|
||||||
|
|
||||||
|
bool Has(int number) const;
|
||||||
|
int ExtensionSize(int number) const; // Size of a repeated extension.
|
||||||
|
FieldType ExtensionType(int number) const;
|
||||||
|
void ClearExtension(int number);
|
||||||
|
|
||||||
|
// singular fields -------------------------------------------------
|
||||||
|
|
||||||
|
int32 GetInt32 (int number, int32 default_value) const;
|
||||||
|
int64 GetInt64 (int number, int64 default_value) const;
|
||||||
|
uint32 GetUInt32(int number, uint32 default_value) const;
|
||||||
|
uint64 GetUInt64(int number, uint64 default_value) const;
|
||||||
|
float GetFloat (int number, float default_value) const;
|
||||||
|
double GetDouble(int number, double default_value) const;
|
||||||
|
bool GetBool (int number, bool default_value) const;
|
||||||
|
int GetEnum (int number, int default_value) const;
|
||||||
|
const string & GetString (int number, const string& default_value) const;
|
||||||
|
const MessageLite& GetMessage(int number,
|
||||||
|
const MessageLite& default_value) const;
|
||||||
|
const MessageLite& GetMessage(int number, const Descriptor* message_type,
|
||||||
|
MessageFactory* factory) const;
|
||||||
|
|
||||||
|
// |descriptor| may be NULL so long as it is known that the descriptor for
|
||||||
|
// the extension lives in the same pool as the descriptor for the containing
|
||||||
|
// type.
|
||||||
|
#define desc const FieldDescriptor* descriptor // avoid line wrapping
|
||||||
|
void SetInt32 (int number, FieldType type, int32 value, desc);
|
||||||
|
void SetInt64 (int number, FieldType type, int64 value, desc);
|
||||||
|
void SetUInt32(int number, FieldType type, uint32 value, desc);
|
||||||
|
void SetUInt64(int number, FieldType type, uint64 value, desc);
|
||||||
|
void SetFloat (int number, FieldType type, float value, desc);
|
||||||
|
void SetDouble(int number, FieldType type, double value, desc);
|
||||||
|
void SetBool (int number, FieldType type, bool value, desc);
|
||||||
|
void SetEnum (int number, FieldType type, int value, desc);
|
||||||
|
void SetString(int number, FieldType type, const string& value, desc);
|
||||||
|
string * MutableString (int number, FieldType type, desc);
|
||||||
|
MessageLite* MutableMessage(int number, FieldType type,
|
||||||
|
const MessageLite& prototype, desc);
|
||||||
|
MessageLite* MutableMessage(const FieldDescriptor* decsriptor,
|
||||||
|
MessageFactory* factory);
|
||||||
|
#undef desc
|
||||||
|
|
||||||
|
// repeated fields -------------------------------------------------
|
||||||
|
|
||||||
|
int32 GetRepeatedInt32 (int number, int index) const;
|
||||||
|
int64 GetRepeatedInt64 (int number, int index) const;
|
||||||
|
uint32 GetRepeatedUInt32(int number, int index) const;
|
||||||
|
uint64 GetRepeatedUInt64(int number, int index) const;
|
||||||
|
float GetRepeatedFloat (int number, int index) const;
|
||||||
|
double GetRepeatedDouble(int number, int index) const;
|
||||||
|
bool GetRepeatedBool (int number, int index) const;
|
||||||
|
int GetRepeatedEnum (int number, int index) const;
|
||||||
|
const string & GetRepeatedString (int number, int index) const;
|
||||||
|
const MessageLite& GetRepeatedMessage(int number, int index) const;
|
||||||
|
|
||||||
|
void SetRepeatedInt32 (int number, int index, int32 value);
|
||||||
|
void SetRepeatedInt64 (int number, int index, int64 value);
|
||||||
|
void SetRepeatedUInt32(int number, int index, uint32 value);
|
||||||
|
void SetRepeatedUInt64(int number, int index, uint64 value);
|
||||||
|
void SetRepeatedFloat (int number, int index, float value);
|
||||||
|
void SetRepeatedDouble(int number, int index, double value);
|
||||||
|
void SetRepeatedBool (int number, int index, bool value);
|
||||||
|
void SetRepeatedEnum (int number, int index, int value);
|
||||||
|
void SetRepeatedString(int number, int index, const string& value);
|
||||||
|
string * MutableRepeatedString (int number, int index);
|
||||||
|
MessageLite* MutableRepeatedMessage(int number, int index);
|
||||||
|
|
||||||
|
#define desc const FieldDescriptor* descriptor // avoid line wrapping
|
||||||
|
void AddInt32 (int number, FieldType type, bool packed, int32 value, desc);
|
||||||
|
void AddInt64 (int number, FieldType type, bool packed, int64 value, desc);
|
||||||
|
void AddUInt32(int number, FieldType type, bool packed, uint32 value, desc);
|
||||||
|
void AddUInt64(int number, FieldType type, bool packed, uint64 value, desc);
|
||||||
|
void AddFloat (int number, FieldType type, bool packed, float value, desc);
|
||||||
|
void AddDouble(int number, FieldType type, bool packed, double value, desc);
|
||||||
|
void AddBool (int number, FieldType type, bool packed, bool value, desc);
|
||||||
|
void AddEnum (int number, FieldType type, bool packed, int value, desc);
|
||||||
|
void AddString(int number, FieldType type, const string& value, desc);
|
||||||
|
string * AddString (int number, FieldType type, desc);
|
||||||
|
MessageLite* AddMessage(int number, FieldType type,
|
||||||
|
const MessageLite& prototype, desc);
|
||||||
|
MessageLite* AddMessage(const FieldDescriptor* descriptor,
|
||||||
|
MessageFactory* factory);
|
||||||
|
#undef desc
|
||||||
|
|
||||||
|
void RemoveLast(int number);
|
||||||
|
void SwapElements(int number, int index1, int index2);
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// TODO(kenton): Hardcore memory management accessors
|
||||||
|
|
||||||
|
// =================================================================
|
||||||
|
// convenience methods for implementing methods of Message
|
||||||
|
//
|
||||||
|
// These could all be implemented in terms of the other methods of this
|
||||||
|
// class, but providing them here helps keep the generated code size down.
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
void MergeFrom(const ExtensionSet& other);
|
||||||
|
void Swap(ExtensionSet* other);
|
||||||
|
bool IsInitialized() const;
|
||||||
|
|
||||||
|
// Parses a single extension from the input. The input should start out
|
||||||
|
// positioned immediately after the tag. |containing_type| is the default
|
||||||
|
// instance for the containing message; it is used only to look up the
|
||||||
|
// extension by number. See RegisterExtension(), above. Unlike the other
|
||||||
|
// methods of ExtensionSet, this only works for generated message types --
|
||||||
|
// it looks up extensions registered using RegisterExtension().
|
||||||
|
bool ParseField(uint32 tag, io::CodedInputStream* input,
|
||||||
|
ExtensionFinder* extension_finder,
|
||||||
|
FieldSkipper* field_skipper);
|
||||||
|
|
||||||
|
// Specific versions for lite or full messages (constructs the appropriate
|
||||||
|
// FieldSkipper automatically).
|
||||||
|
bool ParseField(uint32 tag, io::CodedInputStream* input,
|
||||||
|
const MessageLite* containing_type);
|
||||||
|
bool ParseField(uint32 tag, io::CodedInputStream* input,
|
||||||
|
const Message* containing_type,
|
||||||
|
UnknownFieldSet* unknown_fields);
|
||||||
|
|
||||||
|
// Parse an entire message in MessageSet format. Such messages have no
|
||||||
|
// fields, only extensions.
|
||||||
|
bool ParseMessageSet(io::CodedInputStream* input,
|
||||||
|
ExtensionFinder* extension_finder,
|
||||||
|
FieldSkipper* field_skipper);
|
||||||
|
|
||||||
|
// Specific versions for lite or full messages (constructs the appropriate
|
||||||
|
// FieldSkipper automatically).
|
||||||
|
bool ParseMessageSet(io::CodedInputStream* input,
|
||||||
|
const MessageLite* containing_type);
|
||||||
|
bool ParseMessageSet(io::CodedInputStream* input,
|
||||||
|
const Message* containing_type,
|
||||||
|
UnknownFieldSet* unknown_fields);
|
||||||
|
|
||||||
|
// Write all extension fields with field numbers in the range
|
||||||
|
// [start_field_number, end_field_number)
|
||||||
|
// to the output stream, using the cached sizes computed when ByteSize() was
|
||||||
|
// last called. Note that the range bounds are inclusive-exclusive.
|
||||||
|
void SerializeWithCachedSizes(int start_field_number,
|
||||||
|
int end_field_number,
|
||||||
|
io::CodedOutputStream* output) const;
|
||||||
|
|
||||||
|
// Same as SerializeWithCachedSizes, but without any bounds checking.
|
||||||
|
// The caller must ensure that target has sufficient capacity for the
|
||||||
|
// serialized extensions.
|
||||||
|
//
|
||||||
|
// Returns a pointer past the last written byte.
|
||||||
|
uint8* SerializeWithCachedSizesToArray(int start_field_number,
|
||||||
|
int end_field_number,
|
||||||
|
uint8* target) const;
|
||||||
|
|
||||||
|
// Like above but serializes in MessageSet format.
|
||||||
|
void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const;
|
||||||
|
uint8* SerializeMessageSetWithCachedSizesToArray(uint8* target) const;
|
||||||
|
|
||||||
|
// Returns the total serialized size of all the extensions.
|
||||||
|
int ByteSize() const;
|
||||||
|
|
||||||
|
// Like ByteSize() but uses MessageSet format.
|
||||||
|
int MessageSetByteSize() const;
|
||||||
|
|
||||||
|
// Returns (an estimate of) the total number of bytes used for storing the
|
||||||
|
// extensions in memory, excluding sizeof(*this). If the ExtensionSet is
|
||||||
|
// for a lite message (and thus possibly contains lite messages), the results
|
||||||
|
// are undefined (might work, might crash, might corrupt data, might not even
|
||||||
|
// be linked in). It's up to the protocol compiler to avoid calling this on
|
||||||
|
// such ExtensionSets (easy enough since lite messages don't implement
|
||||||
|
// SpaceUsed()).
|
||||||
|
int SpaceUsedExcludingSelf() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct Extension {
|
||||||
|
union {
|
||||||
|
int32 int32_value;
|
||||||
|
int64 int64_value;
|
||||||
|
uint32 uint32_value;
|
||||||
|
uint64 uint64_value;
|
||||||
|
float float_value;
|
||||||
|
double double_value;
|
||||||
|
bool bool_value;
|
||||||
|
int enum_value;
|
||||||
|
string* string_value;
|
||||||
|
MessageLite* message_value;
|
||||||
|
|
||||||
|
RepeatedField <int32 >* repeated_int32_value;
|
||||||
|
RepeatedField <int64 >* repeated_int64_value;
|
||||||
|
RepeatedField <uint32 >* repeated_uint32_value;
|
||||||
|
RepeatedField <uint64 >* repeated_uint64_value;
|
||||||
|
RepeatedField <float >* repeated_float_value;
|
||||||
|
RepeatedField <double >* repeated_double_value;
|
||||||
|
RepeatedField <bool >* repeated_bool_value;
|
||||||
|
RepeatedField <int >* repeated_enum_value;
|
||||||
|
RepeatedPtrField<string >* repeated_string_value;
|
||||||
|
RepeatedPtrField<MessageLite>* repeated_message_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
FieldType type;
|
||||||
|
bool is_repeated;
|
||||||
|
|
||||||
|
// For singular types, indicates if the extension is "cleared". This
|
||||||
|
// happens when an extension is set and then later cleared by the caller.
|
||||||
|
// We want to keep the Extension object around for reuse, so instead of
|
||||||
|
// removing it from the map, we just set is_cleared = true. This has no
|
||||||
|
// meaning for repeated types; for those, the size of the RepeatedField
|
||||||
|
// simply becomes zero when cleared.
|
||||||
|
bool is_cleared;
|
||||||
|
|
||||||
|
// For repeated types, this indicates if the [packed=true] option is set.
|
||||||
|
bool is_packed;
|
||||||
|
|
||||||
|
// The descriptor for this extension, if one exists and is known. May be
|
||||||
|
// NULL. Must not be NULL if the descriptor for the extension does not
|
||||||
|
// live in the same pool as the descriptor for the containing type.
|
||||||
|
const FieldDescriptor* descriptor;
|
||||||
|
|
||||||
|
// For packed fields, the size of the packed data is recorded here when
|
||||||
|
// ByteSize() is called then used during serialization.
|
||||||
|
// TODO(kenton): Use atomic<int> when C++ supports it.
|
||||||
|
mutable int cached_size;
|
||||||
|
|
||||||
|
// Some helper methods for operations on a single Extension.
|
||||||
|
void SerializeFieldWithCachedSizes(
|
||||||
|
int number,
|
||||||
|
io::CodedOutputStream* output) const;
|
||||||
|
uint8* SerializeFieldWithCachedSizesToArray(
|
||||||
|
int number,
|
||||||
|
uint8* target) const;
|
||||||
|
void SerializeMessageSetItemWithCachedSizes(
|
||||||
|
int number,
|
||||||
|
io::CodedOutputStream* output) const;
|
||||||
|
uint8* SerializeMessageSetItemWithCachedSizesToArray(
|
||||||
|
int number,
|
||||||
|
uint8* target) const;
|
||||||
|
int ByteSize(int number) const;
|
||||||
|
int MessageSetItemByteSize(int number) const;
|
||||||
|
void Clear();
|
||||||
|
int GetSize() const;
|
||||||
|
void Free();
|
||||||
|
int SpaceUsedExcludingSelf() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Gets the extension with the given number, creating it if it does not
|
||||||
|
// already exist. Returns true if the extension did not already exist.
|
||||||
|
bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
|
||||||
|
Extension** result);
|
||||||
|
|
||||||
|
// Parse a single MessageSet item -- called just after the item group start
|
||||||
|
// tag has been read.
|
||||||
|
bool ParseMessageSetItem(io::CodedInputStream* input,
|
||||||
|
ExtensionFinder* extension_finder,
|
||||||
|
FieldSkipper* field_skipper);
|
||||||
|
|
||||||
|
|
||||||
|
// Hack: RepeatedPtrFieldBase declares ExtensionSet as a friend. This
|
||||||
|
// friendship should automatically extend to ExtensionSet::Extension, but
|
||||||
|
// unfortunately some older compilers (e.g. GCC 3.4.4) do not implement this
|
||||||
|
// correctly. So, we must provide helpers for calling methods of that
|
||||||
|
// class.
|
||||||
|
|
||||||
|
// Defined in extension_set_heavy.cc.
|
||||||
|
static inline int RepeatedMessage_SpaceUsedExcludingSelf(
|
||||||
|
RepeatedPtrFieldBase* field);
|
||||||
|
|
||||||
|
// The Extension struct is small enough to be passed by value, so we use it
|
||||||
|
// directly as the value type in the map rather than use pointers. We use
|
||||||
|
// a map rather than hash_map here because we expect most ExtensionSets will
|
||||||
|
// only contain a small number of extensions whereas hash_map is optimized
|
||||||
|
// for 100 elements or more. Also, we want AppendToList() to order fields
|
||||||
|
// by field number.
|
||||||
|
map<int, Extension> extensions_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet);
|
||||||
|
};
|
||||||
|
|
||||||
|
// These are just for convenience...
|
||||||
|
inline void ExtensionSet::SetString(int number, FieldType type,
|
||||||
|
const string& value,
|
||||||
|
const FieldDescriptor* descriptor) {
|
||||||
|
MutableString(number, type, descriptor)->assign(value);
|
||||||
|
}
|
||||||
|
inline void ExtensionSet::SetRepeatedString(int number, int index,
|
||||||
|
const string& value) {
|
||||||
|
MutableRepeatedString(number, index)->assign(value);
|
||||||
|
}
|
||||||
|
inline void ExtensionSet::AddString(int number, FieldType type,
|
||||||
|
const string& value,
|
||||||
|
const FieldDescriptor* descriptor) {
|
||||||
|
AddString(number, type, descriptor)->assign(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Glue for generated extension accessors
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Template magic
|
||||||
|
|
||||||
|
// First we have a set of classes representing "type traits" for different
|
||||||
|
// field types. A type traits class knows how to implement basic accessors
|
||||||
|
// for extensions of a particular type given an ExtensionSet. The signature
|
||||||
|
// for a type traits class looks like this:
|
||||||
|
//
|
||||||
|
// class TypeTraits {
|
||||||
|
// public:
|
||||||
|
// typedef ? ConstType;
|
||||||
|
// typedef ? MutableType;
|
||||||
|
//
|
||||||
|
// static inline ConstType Get(int number, const ExtensionSet& set);
|
||||||
|
// static inline void Set(int number, ConstType value, ExtensionSet* set);
|
||||||
|
// static inline MutableType Mutable(int number, ExtensionSet* set);
|
||||||
|
//
|
||||||
|
// // Variants for repeated fields.
|
||||||
|
// static inline ConstType Get(int number, const ExtensionSet& set,
|
||||||
|
// int index);
|
||||||
|
// static inline void Set(int number, int index,
|
||||||
|
// ConstType value, ExtensionSet* set);
|
||||||
|
// static inline MutableType Mutable(int number, int index,
|
||||||
|
// ExtensionSet* set);
|
||||||
|
// static inline void Add(int number, ConstType value, ExtensionSet* set);
|
||||||
|
// static inline MutableType Add(int number, ExtensionSet* set);
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// Not all of these methods make sense for all field types. For example, the
|
||||||
|
// "Mutable" methods only make sense for strings and messages, and the
|
||||||
|
// repeated methods only make sense for repeated types. So, each type
|
||||||
|
// traits class implements only the set of methods from this signature that it
|
||||||
|
// actually supports. This will cause a compiler error if the user tries to
|
||||||
|
// access an extension using a method that doesn't make sense for its type.
|
||||||
|
// For example, if "foo" is an extension of type "optional int32", then if you
|
||||||
|
// try to write code like:
|
||||||
|
// my_message.MutableExtension(foo)
|
||||||
|
// you will get a compile error because PrimitiveTypeTraits<int32> does not
|
||||||
|
// have a "Mutable()" method.
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// PrimitiveTypeTraits
|
||||||
|
|
||||||
|
// Since the ExtensionSet has different methods for each primitive type,
|
||||||
|
// we must explicitly define the methods of the type traits class for each
|
||||||
|
// known type.
|
||||||
|
template <typename Type>
|
||||||
|
class PrimitiveTypeTraits {
|
||||||
|
public:
|
||||||
|
typedef Type ConstType;
|
||||||
|
|
||||||
|
static inline ConstType Get(int number, const ExtensionSet& set,
|
||||||
|
ConstType default_value);
|
||||||
|
static inline void Set(int number, FieldType field_type,
|
||||||
|
ConstType value, ExtensionSet* set);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
class RepeatedPrimitiveTypeTraits {
|
||||||
|
public:
|
||||||
|
typedef Type ConstType;
|
||||||
|
|
||||||
|
static inline Type Get(int number, const ExtensionSet& set, int index);
|
||||||
|
static inline void Set(int number, int index, Type value, ExtensionSet* set);
|
||||||
|
static inline void Add(int number, FieldType field_type,
|
||||||
|
bool is_packed, Type value, ExtensionSet* set);
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \
|
||||||
|
template<> inline TYPE PrimitiveTypeTraits<TYPE>::Get( \
|
||||||
|
int number, const ExtensionSet& set, TYPE default_value) { \
|
||||||
|
return set.Get##METHOD(number, default_value); \
|
||||||
|
} \
|
||||||
|
template<> inline void PrimitiveTypeTraits<TYPE>::Set( \
|
||||||
|
int number, FieldType field_type, TYPE value, ExtensionSet* set) { \
|
||||||
|
set->Set##METHOD(number, field_type, value, NULL); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template<> inline TYPE RepeatedPrimitiveTypeTraits<TYPE>::Get( \
|
||||||
|
int number, const ExtensionSet& set, int index) { \
|
||||||
|
return set.GetRepeated##METHOD(number, index); \
|
||||||
|
} \
|
||||||
|
template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Set( \
|
||||||
|
int number, int index, TYPE value, ExtensionSet* set) { \
|
||||||
|
set->SetRepeated##METHOD(number, index, value); \
|
||||||
|
} \
|
||||||
|
template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \
|
||||||
|
int number, FieldType field_type, bool is_packed, \
|
||||||
|
TYPE value, ExtensionSet* set) { \
|
||||||
|
set->Add##METHOD(number, field_type, is_packed, value, NULL); \
|
||||||
|
}
|
||||||
|
|
||||||
|
PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32, Int32)
|
||||||
|
PROTOBUF_DEFINE_PRIMITIVE_TYPE( int64, Int64)
|
||||||
|
PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint32, UInt32)
|
||||||
|
PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint64, UInt64)
|
||||||
|
PROTOBUF_DEFINE_PRIMITIVE_TYPE( float, Float)
|
||||||
|
PROTOBUF_DEFINE_PRIMITIVE_TYPE(double, Double)
|
||||||
|
PROTOBUF_DEFINE_PRIMITIVE_TYPE( bool, Bool)
|
||||||
|
|
||||||
|
#undef PROTOBUF_DEFINE_PRIMITIVE_TYPE
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// StringTypeTraits
|
||||||
|
|
||||||
|
// Strings support both Set() and Mutable().
|
||||||
|
class LIBPROTOBUF_EXPORT StringTypeTraits {
|
||||||
|
public:
|
||||||
|
typedef const string& ConstType;
|
||||||
|
typedef string* MutableType;
|
||||||
|
|
||||||
|
static inline const string& Get(int number, const ExtensionSet& set,
|
||||||
|
ConstType default_value) {
|
||||||
|
return set.GetString(number, default_value);
|
||||||
|
}
|
||||||
|
static inline void Set(int number, FieldType field_type,
|
||||||
|
const string& value, ExtensionSet* set) {
|
||||||
|
set->SetString(number, field_type, value, NULL);
|
||||||
|
}
|
||||||
|
static inline string* Mutable(int number, FieldType field_type,
|
||||||
|
ExtensionSet* set) {
|
||||||
|
return set->MutableString(number, field_type, NULL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
|
||||||
|
public:
|
||||||
|
typedef const string& ConstType;
|
||||||
|
typedef string* MutableType;
|
||||||
|
|
||||||
|
static inline const string& Get(int number, const ExtensionSet& set,
|
||||||
|
int index) {
|
||||||
|
return set.GetRepeatedString(number, index);
|
||||||
|
}
|
||||||
|
static inline void Set(int number, int index,
|
||||||
|
const string& value, ExtensionSet* set) {
|
||||||
|
set->SetRepeatedString(number, index, value);
|
||||||
|
}
|
||||||
|
static inline string* Mutable(int number, int index, ExtensionSet* set) {
|
||||||
|
return set->MutableRepeatedString(number, index);
|
||||||
|
}
|
||||||
|
static inline void Add(int number, FieldType field_type,
|
||||||
|
bool /*is_packed*/, const string& value,
|
||||||
|
ExtensionSet* set) {
|
||||||
|
set->AddString(number, field_type, value, NULL);
|
||||||
|
}
|
||||||
|
static inline string* Add(int number, FieldType field_type,
|
||||||
|
ExtensionSet* set) {
|
||||||
|
return set->AddString(number, field_type, NULL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// EnumTypeTraits
|
||||||
|
|
||||||
|
// ExtensionSet represents enums using integers internally, so we have to
|
||||||
|
// static_cast around.
|
||||||
|
template <typename Type, bool IsValid(int)>
|
||||||
|
class EnumTypeTraits {
|
||||||
|
public:
|
||||||
|
typedef Type ConstType;
|
||||||
|
|
||||||
|
static inline ConstType Get(int number, const ExtensionSet& set,
|
||||||
|
ConstType default_value) {
|
||||||
|
return static_cast<Type>(set.GetEnum(number, default_value));
|
||||||
|
}
|
||||||
|
static inline void Set(int number, FieldType field_type,
|
||||||
|
ConstType value, ExtensionSet* set) {
|
||||||
|
GOOGLE_DCHECK(IsValid(value));
|
||||||
|
set->SetEnum(number, field_type, value, NULL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type, bool IsValid(int)>
|
||||||
|
class RepeatedEnumTypeTraits {
|
||||||
|
public:
|
||||||
|
typedef Type ConstType;
|
||||||
|
|
||||||
|
static inline ConstType Get(int number, const ExtensionSet& set, int index) {
|
||||||
|
return static_cast<Type>(set.GetRepeatedEnum(number, index));
|
||||||
|
}
|
||||||
|
static inline void Set(int number, int index,
|
||||||
|
ConstType value, ExtensionSet* set) {
|
||||||
|
GOOGLE_DCHECK(IsValid(value));
|
||||||
|
set->SetRepeatedEnum(number, index, value);
|
||||||
|
}
|
||||||
|
static inline void Add(int number, FieldType field_type,
|
||||||
|
bool is_packed, ConstType value, ExtensionSet* set) {
|
||||||
|
GOOGLE_DCHECK(IsValid(value));
|
||||||
|
set->AddEnum(number, field_type, is_packed, value, NULL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// MessageTypeTraits
|
||||||
|
|
||||||
|
// ExtensionSet guarantees that when manipulating extensions with message
|
||||||
|
// types, the implementation used will be the compiled-in class representing
|
||||||
|
// that type. So, we can static_cast down to the exact type we expect.
|
||||||
|
template <typename Type>
|
||||||
|
class MessageTypeTraits {
|
||||||
|
public:
|
||||||
|
typedef const Type& ConstType;
|
||||||
|
typedef Type* MutableType;
|
||||||
|
|
||||||
|
static inline ConstType Get(int number, const ExtensionSet& set,
|
||||||
|
ConstType default_value) {
|
||||||
|
return static_cast<const Type&>(
|
||||||
|
set.GetMessage(number, default_value));
|
||||||
|
}
|
||||||
|
static inline MutableType Mutable(int number, FieldType field_type,
|
||||||
|
ExtensionSet* set) {
|
||||||
|
return static_cast<Type*>(
|
||||||
|
set->MutableMessage(number, field_type, Type::default_instance(), NULL));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
class RepeatedMessageTypeTraits {
|
||||||
|
public:
|
||||||
|
typedef const Type& ConstType;
|
||||||
|
typedef Type* MutableType;
|
||||||
|
|
||||||
|
static inline ConstType Get(int number, const ExtensionSet& set, int index) {
|
||||||
|
return static_cast<const Type&>(set.GetRepeatedMessage(number, index));
|
||||||
|
}
|
||||||
|
static inline MutableType Mutable(int number, int index, ExtensionSet* set) {
|
||||||
|
return static_cast<Type*>(set->MutableRepeatedMessage(number, index));
|
||||||
|
}
|
||||||
|
static inline MutableType Add(int number, FieldType field_type,
|
||||||
|
ExtensionSet* set) {
|
||||||
|
return static_cast<Type*>(
|
||||||
|
set->AddMessage(number, field_type, Type::default_instance(), NULL));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// ExtensionIdentifier
|
||||||
|
|
||||||
|
// This is the type of actual extension objects. E.g. if you have:
|
||||||
|
// extends Foo with optional int32 bar = 1234;
|
||||||
|
// then "bar" will be defined in C++ as:
|
||||||
|
// ExtensionIdentifier<Foo, PrimitiveTypeTraits<int32>, 1, false> bar(1234);
|
||||||
|
//
|
||||||
|
// Note that we could, in theory, supply the field number as a template
|
||||||
|
// parameter, and thus make an instance of ExtensionIdentifier have no
|
||||||
|
// actual contents. However, if we did that, then using at extension
|
||||||
|
// identifier would not necessarily cause the compiler to output any sort
|
||||||
|
// of reference to any simple defined in the extension's .pb.o file. Some
|
||||||
|
// linkers will actually drop object files that are not explicitly referenced,
|
||||||
|
// but that would be bad because it would cause this extension to not be
|
||||||
|
// registered at static initialization, and therefore using it would crash.
|
||||||
|
|
||||||
|
template <typename ExtendeeType, typename TypeTraitsType,
|
||||||
|
FieldType field_type, bool is_packed>
|
||||||
|
class ExtensionIdentifier {
|
||||||
|
public:
|
||||||
|
typedef TypeTraitsType TypeTraits;
|
||||||
|
typedef ExtendeeType Extendee;
|
||||||
|
|
||||||
|
ExtensionIdentifier(int number, typename TypeTraits::ConstType default_value)
|
||||||
|
: number_(number), default_value_(default_value) {}
|
||||||
|
inline int number() const { return number_; }
|
||||||
|
typename TypeTraits::ConstType default_value() const {
|
||||||
|
return default_value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int number_;
|
||||||
|
typename TypeTraits::ConstType default_value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Generated accessors
|
||||||
|
|
||||||
|
// This macro should be expanded in the context of a generated type which
|
||||||
|
// has extensions.
|
||||||
|
//
|
||||||
|
// We use "_proto_TypeTraits" as a type name below because "TypeTraits"
|
||||||
|
// causes problems if the class has a nested message or enum type with that
|
||||||
|
// name and "_TypeTraits" is technically reserved for the C++ library since
|
||||||
|
// it starts with an underscore followed by a capital letter.
|
||||||
|
#define GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(CLASSNAME) \
|
||||||
|
/* Has, Size, Clear */ \
|
||||||
|
template <typename _proto_TypeTraits, \
|
||||||
|
::google::protobuf::internal::FieldType field_type, \
|
||||||
|
bool is_packed> \
|
||||||
|
inline bool HasExtension( \
|
||||||
|
const ::google::protobuf::internal::ExtensionIdentifier< \
|
||||||
|
CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
|
||||||
|
return _extensions_.Has(id.number()); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename _proto_TypeTraits, \
|
||||||
|
::google::protobuf::internal::FieldType field_type, \
|
||||||
|
bool is_packed> \
|
||||||
|
inline void ClearExtension( \
|
||||||
|
const ::google::protobuf::internal::ExtensionIdentifier< \
|
||||||
|
CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
|
||||||
|
_extensions_.ClearExtension(id.number()); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename _proto_TypeTraits, \
|
||||||
|
::google::protobuf::internal::FieldType field_type, \
|
||||||
|
bool is_packed> \
|
||||||
|
inline int ExtensionSize( \
|
||||||
|
const ::google::protobuf::internal::ExtensionIdentifier< \
|
||||||
|
CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
|
||||||
|
return _extensions_.ExtensionSize(id.number()); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Singular accessors */ \
|
||||||
|
template <typename _proto_TypeTraits, \
|
||||||
|
::google::protobuf::internal::FieldType field_type, \
|
||||||
|
bool is_packed> \
|
||||||
|
inline typename _proto_TypeTraits::ConstType GetExtension( \
|
||||||
|
const ::google::protobuf::internal::ExtensionIdentifier< \
|
||||||
|
CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
|
||||||
|
return _proto_TypeTraits::Get(id.number(), _extensions_, \
|
||||||
|
id.default_value()); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename _proto_TypeTraits, \
|
||||||
|
::google::protobuf::internal::FieldType field_type, \
|
||||||
|
bool is_packed> \
|
||||||
|
inline typename _proto_TypeTraits::MutableType MutableExtension( \
|
||||||
|
const ::google::protobuf::internal::ExtensionIdentifier< \
|
||||||
|
CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
|
||||||
|
return _proto_TypeTraits::Mutable(id.number(), field_type, &_extensions_);\
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename _proto_TypeTraits, \
|
||||||
|
::google::protobuf::internal::FieldType field_type, \
|
||||||
|
bool is_packed> \
|
||||||
|
inline void SetExtension( \
|
||||||
|
const ::google::protobuf::internal::ExtensionIdentifier< \
|
||||||
|
CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
|
||||||
|
typename _proto_TypeTraits::ConstType value) { \
|
||||||
|
_proto_TypeTraits::Set(id.number(), field_type, value, &_extensions_); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Repeated accessors */ \
|
||||||
|
template <typename _proto_TypeTraits, \
|
||||||
|
::google::protobuf::internal::FieldType field_type, \
|
||||||
|
bool is_packed> \
|
||||||
|
inline typename _proto_TypeTraits::ConstType GetExtension( \
|
||||||
|
const ::google::protobuf::internal::ExtensionIdentifier< \
|
||||||
|
CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
|
||||||
|
int index) const { \
|
||||||
|
return _proto_TypeTraits::Get(id.number(), _extensions_, index); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename _proto_TypeTraits, \
|
||||||
|
::google::protobuf::internal::FieldType field_type, \
|
||||||
|
bool is_packed> \
|
||||||
|
inline typename _proto_TypeTraits::MutableType MutableExtension( \
|
||||||
|
const ::google::protobuf::internal::ExtensionIdentifier< \
|
||||||
|
CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
|
||||||
|
int index) { \
|
||||||
|
return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename _proto_TypeTraits, \
|
||||||
|
::google::protobuf::internal::FieldType field_type, \
|
||||||
|
bool is_packed> \
|
||||||
|
inline void SetExtension( \
|
||||||
|
const ::google::protobuf::internal::ExtensionIdentifier< \
|
||||||
|
CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
|
||||||
|
int index, typename _proto_TypeTraits::ConstType value) { \
|
||||||
|
_proto_TypeTraits::Set(id.number(), index, value, &_extensions_); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename _proto_TypeTraits, \
|
||||||
|
::google::protobuf::internal::FieldType field_type, \
|
||||||
|
bool is_packed> \
|
||||||
|
inline typename _proto_TypeTraits::MutableType AddExtension( \
|
||||||
|
const ::google::protobuf::internal::ExtensionIdentifier< \
|
||||||
|
CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
|
||||||
|
return _proto_TypeTraits::Add(id.number(), field_type, &_extensions_); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename _proto_TypeTraits, \
|
||||||
|
::google::protobuf::internal::FieldType field_type, \
|
||||||
|
bool is_packed> \
|
||||||
|
inline void AddExtension( \
|
||||||
|
const ::google::protobuf::internal::ExtensionIdentifier< \
|
||||||
|
CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
|
||||||
|
typename _proto_TypeTraits::ConstType value) { \
|
||||||
|
_proto_TypeTraits::Add(id.number(), field_type, is_packed, \
|
||||||
|
value, &_extensions_); \
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_EXTENSION_SET_H__
|
@ -0,0 +1,457 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
//
|
||||||
|
// Contains methods defined in extension_set.h which cannot be part of the
|
||||||
|
// lite library because they use descriptors or reflection.
|
||||||
|
|
||||||
|
#include <google/protobuf/extension_set.h>
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <google/protobuf/message.h>
|
||||||
|
#include <google/protobuf/repeated_field.h>
|
||||||
|
#include <google/protobuf/wire_format.h>
|
||||||
|
#include <google/protobuf/wire_format_lite_inl.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Implementation of ExtensionFinder which finds extensions in a given
|
||||||
|
// DescriptorPool, using the given MessageFactory to construct sub-objects.
|
||||||
|
// This class is implemented in extension_set_heavy.cc.
|
||||||
|
class DescriptorPoolExtensionFinder : public ExtensionFinder {
|
||||||
|
public:
|
||||||
|
DescriptorPoolExtensionFinder(const DescriptorPool* pool,
|
||||||
|
MessageFactory* factory,
|
||||||
|
const Descriptor* containing_type)
|
||||||
|
: pool_(pool), factory_(factory), containing_type_(containing_type) {}
|
||||||
|
virtual ~DescriptorPoolExtensionFinder() {}
|
||||||
|
|
||||||
|
virtual bool Find(int number, ExtensionInfo* output);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const DescriptorPool* pool_;
|
||||||
|
MessageFactory* factory_;
|
||||||
|
const Descriptor* containing_type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ExtensionSet::AppendToList(const Descriptor* containing_type,
|
||||||
|
const DescriptorPool* pool,
|
||||||
|
vector<const FieldDescriptor*>* output) const {
|
||||||
|
for (map<int, Extension>::const_iterator iter = extensions_.begin();
|
||||||
|
iter != extensions_.end(); ++iter) {
|
||||||
|
bool has = false;
|
||||||
|
if (iter->second.is_repeated) {
|
||||||
|
has = iter->second.GetSize() > 0;
|
||||||
|
} else {
|
||||||
|
has = !iter->second.is_cleared;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has) {
|
||||||
|
// TODO(kenton): Looking up each field by number is somewhat unfortunate.
|
||||||
|
// Is there a better way? The problem is that descriptors are lazily-
|
||||||
|
// initialized, so they might not even be constructed until
|
||||||
|
// AppendToList() is called.
|
||||||
|
|
||||||
|
if (iter->second.descriptor == NULL) {
|
||||||
|
output->push_back(pool->FindExtensionByNumber(
|
||||||
|
containing_type, iter->first));
|
||||||
|
} else {
|
||||||
|
output->push_back(iter->second.descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FieldDescriptor::Type real_type(FieldType type) {
|
||||||
|
GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE);
|
||||||
|
return static_cast<FieldDescriptor::Type>(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FieldDescriptor::CppType cpp_type(FieldType type) {
|
||||||
|
return FieldDescriptor::TypeToCppType(
|
||||||
|
static_cast<FieldDescriptor::Type>(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \
|
||||||
|
GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \
|
||||||
|
: FieldDescriptor::LABEL_OPTIONAL, \
|
||||||
|
FieldDescriptor::LABEL_##LABEL); \
|
||||||
|
GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
|
||||||
|
|
||||||
|
const MessageLite& ExtensionSet::GetMessage(int number,
|
||||||
|
const Descriptor* message_type,
|
||||||
|
MessageFactory* factory) const {
|
||||||
|
map<int, Extension>::const_iterator iter = extensions_.find(number);
|
||||||
|
if (iter == extensions_.end() || iter->second.is_cleared) {
|
||||||
|
// Not present. Return the default value.
|
||||||
|
return *factory->GetPrototype(message_type);
|
||||||
|
} else {
|
||||||
|
GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
|
||||||
|
return *iter->second.message_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
|
||||||
|
MessageFactory* factory) {
|
||||||
|
Extension* extension;
|
||||||
|
if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
|
||||||
|
extension->type = descriptor->type();
|
||||||
|
GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
|
||||||
|
extension->is_repeated = false;
|
||||||
|
extension->is_packed = false;
|
||||||
|
const MessageLite* prototype =
|
||||||
|
factory->GetPrototype(descriptor->message_type());
|
||||||
|
GOOGLE_CHECK(prototype != NULL);
|
||||||
|
extension->message_value = prototype->New();
|
||||||
|
} else {
|
||||||
|
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
|
||||||
|
}
|
||||||
|
extension->is_cleared = false;
|
||||||
|
return extension->message_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
|
||||||
|
MessageFactory* factory) {
|
||||||
|
Extension* extension;
|
||||||
|
if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
|
||||||
|
extension->type = descriptor->type();
|
||||||
|
GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
|
||||||
|
extension->is_repeated = true;
|
||||||
|
extension->repeated_message_value =
|
||||||
|
new RepeatedPtrField<MessageLite>();
|
||||||
|
} else {
|
||||||
|
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepeatedPtrField<Message> does not know how to Add() since it cannot
|
||||||
|
// allocate an abstract object, so we have to be tricky.
|
||||||
|
MessageLite* result = extension->repeated_message_value
|
||||||
|
->AddFromCleared<internal::GenericTypeHandler<MessageLite> >();
|
||||||
|
if (result == NULL) {
|
||||||
|
const MessageLite* prototype;
|
||||||
|
if (extension->repeated_message_value->size() == 0) {
|
||||||
|
prototype = factory->GetPrototype(descriptor->message_type());
|
||||||
|
GOOGLE_CHECK(prototype != NULL);
|
||||||
|
} else {
|
||||||
|
prototype = &extension->repeated_message_value->Get(0);
|
||||||
|
}
|
||||||
|
result = prototype->New();
|
||||||
|
extension->repeated_message_value->AddAllocated(result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
|
||||||
|
return reinterpret_cast<const EnumDescriptor*>(arg)
|
||||||
|
->FindValueByNumber(number) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
|
||||||
|
const FieldDescriptor* extension =
|
||||||
|
pool_->FindExtensionByNumber(containing_type_, number);
|
||||||
|
if (extension == NULL) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
output->type = extension->type();
|
||||||
|
output->is_repeated = extension->is_repeated();
|
||||||
|
output->is_packed = extension->options().packed();
|
||||||
|
output->descriptor = extension;
|
||||||
|
if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
||||||
|
output->message_prototype =
|
||||||
|
factory_->GetPrototype(extension->message_type());
|
||||||
|
GOOGLE_CHECK(output->message_prototype != NULL)
|
||||||
|
<< "Extension factory's GetPrototype() returned NULL for extension: "
|
||||||
|
<< extension->full_name();
|
||||||
|
} else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
|
||||||
|
output->enum_validity_check.func = ValidateEnumUsingDescriptor;
|
||||||
|
output->enum_validity_check.arg = extension->enum_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
|
||||||
|
const Message* containing_type,
|
||||||
|
UnknownFieldSet* unknown_fields) {
|
||||||
|
UnknownFieldSetFieldSkipper skipper(unknown_fields);
|
||||||
|
if (input->GetExtensionPool() == NULL) {
|
||||||
|
GeneratedExtensionFinder finder(containing_type);
|
||||||
|
return ParseField(tag, input, &finder, &skipper);
|
||||||
|
} else {
|
||||||
|
DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
|
||||||
|
input->GetExtensionFactory(),
|
||||||
|
containing_type->GetDescriptor());
|
||||||
|
return ParseField(tag, input, &finder, &skipper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
|
||||||
|
const Message* containing_type,
|
||||||
|
UnknownFieldSet* unknown_fields) {
|
||||||
|
UnknownFieldSetFieldSkipper skipper(unknown_fields);
|
||||||
|
if (input->GetExtensionPool() == NULL) {
|
||||||
|
GeneratedExtensionFinder finder(containing_type);
|
||||||
|
return ParseMessageSet(input, &finder, &skipper);
|
||||||
|
} else {
|
||||||
|
DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
|
||||||
|
input->GetExtensionFactory(),
|
||||||
|
containing_type->GetDescriptor());
|
||||||
|
return ParseMessageSet(input, &finder, &skipper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ExtensionSet::SpaceUsedExcludingSelf() const {
|
||||||
|
int total_size =
|
||||||
|
extensions_.size() * sizeof(map<int, Extension>::value_type);
|
||||||
|
for (map<int, Extension>::const_iterator iter = extensions_.begin(),
|
||||||
|
end = extensions_.end();
|
||||||
|
iter != end;
|
||||||
|
++iter) {
|
||||||
|
total_size += iter->second.SpaceUsedExcludingSelf();
|
||||||
|
}
|
||||||
|
return total_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelf(
|
||||||
|
RepeatedPtrFieldBase* field) {
|
||||||
|
return field->SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
|
||||||
|
int total_size = 0;
|
||||||
|
if (is_repeated) {
|
||||||
|
switch (cpp_type(type)) {
|
||||||
|
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
|
||||||
|
case FieldDescriptor::CPPTYPE_##UPPERCASE: \
|
||||||
|
total_size += sizeof(*repeated_##LOWERCASE##_value) + \
|
||||||
|
repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
|
||||||
|
break
|
||||||
|
|
||||||
|
HANDLE_TYPE( INT32, int32);
|
||||||
|
HANDLE_TYPE( INT64, int64);
|
||||||
|
HANDLE_TYPE( UINT32, uint32);
|
||||||
|
HANDLE_TYPE( UINT64, uint64);
|
||||||
|
HANDLE_TYPE( FLOAT, float);
|
||||||
|
HANDLE_TYPE( DOUBLE, double);
|
||||||
|
HANDLE_TYPE( BOOL, bool);
|
||||||
|
HANDLE_TYPE( ENUM, enum);
|
||||||
|
HANDLE_TYPE( STRING, string);
|
||||||
|
#undef HANDLE_TYPE
|
||||||
|
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
|
// repeated_message_value is actually a RepeatedPtrField<MessageLite>,
|
||||||
|
// but MessageLite has no SpaceUsed(), so we must directly call
|
||||||
|
// RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type
|
||||||
|
// handler.
|
||||||
|
total_size += sizeof(*repeated_message_value) +
|
||||||
|
RepeatedMessage_SpaceUsedExcludingSelf(repeated_message_value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (cpp_type(type)) {
|
||||||
|
case FieldDescriptor::CPPTYPE_STRING:
|
||||||
|
total_size += sizeof(*string_value) +
|
||||||
|
StringSpaceUsedExcludingSelf(*string_value);
|
||||||
|
break;
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
|
total_size += down_cast<Message*>(message_value)->SpaceUsed();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// No extra storage costs for primitive types.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Serialize*ToArray methods are only needed in the heavy library, as
|
||||||
|
// the lite library only generates SerializeWithCachedSizes.
|
||||||
|
uint8* ExtensionSet::SerializeWithCachedSizesToArray(
|
||||||
|
int start_field_number, int end_field_number,
|
||||||
|
uint8* target) const {
|
||||||
|
map<int, Extension>::const_iterator iter;
|
||||||
|
for (iter = extensions_.lower_bound(start_field_number);
|
||||||
|
iter != extensions_.end() && iter->first < end_field_number;
|
||||||
|
++iter) {
|
||||||
|
target = iter->second.SerializeFieldWithCachedSizesToArray(iter->first,
|
||||||
|
target);
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
|
||||||
|
uint8* target) const {
|
||||||
|
map<int, Extension>::const_iterator iter;
|
||||||
|
for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
|
||||||
|
target = iter->second.SerializeMessageSetItemWithCachedSizesToArray(
|
||||||
|
iter->first, target);
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray(
|
||||||
|
int number, uint8* target) const {
|
||||||
|
if (is_repeated) {
|
||||||
|
if (is_packed) {
|
||||||
|
if (cached_size == 0) return target;
|
||||||
|
|
||||||
|
target = WireFormatLite::WriteTagToArray(number,
|
||||||
|
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
|
||||||
|
target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target);
|
||||||
|
|
||||||
|
switch (real_type(type)) {
|
||||||
|
#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
|
||||||
|
case FieldDescriptor::TYPE_##UPPERCASE: \
|
||||||
|
for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
|
||||||
|
target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \
|
||||||
|
repeated_##LOWERCASE##_value->Get(i), target); \
|
||||||
|
} \
|
||||||
|
break
|
||||||
|
|
||||||
|
HANDLE_TYPE( INT32, Int32, int32);
|
||||||
|
HANDLE_TYPE( INT64, Int64, int64);
|
||||||
|
HANDLE_TYPE( UINT32, UInt32, uint32);
|
||||||
|
HANDLE_TYPE( UINT64, UInt64, uint64);
|
||||||
|
HANDLE_TYPE( SINT32, SInt32, int32);
|
||||||
|
HANDLE_TYPE( SINT64, SInt64, int64);
|
||||||
|
HANDLE_TYPE( FIXED32, Fixed32, uint32);
|
||||||
|
HANDLE_TYPE( FIXED64, Fixed64, uint64);
|
||||||
|
HANDLE_TYPE(SFIXED32, SFixed32, int32);
|
||||||
|
HANDLE_TYPE(SFIXED64, SFixed64, int64);
|
||||||
|
HANDLE_TYPE( FLOAT, Float, float);
|
||||||
|
HANDLE_TYPE( DOUBLE, Double, double);
|
||||||
|
HANDLE_TYPE( BOOL, Bool, bool);
|
||||||
|
HANDLE_TYPE( ENUM, Enum, enum);
|
||||||
|
#undef HANDLE_TYPE
|
||||||
|
|
||||||
|
case WireFormatLite::TYPE_STRING:
|
||||||
|
case WireFormatLite::TYPE_BYTES:
|
||||||
|
case WireFormatLite::TYPE_GROUP:
|
||||||
|
case WireFormatLite::TYPE_MESSAGE:
|
||||||
|
GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (real_type(type)) {
|
||||||
|
#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
|
||||||
|
case FieldDescriptor::TYPE_##UPPERCASE: \
|
||||||
|
for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
|
||||||
|
target = WireFormatLite::Write##CAMELCASE##ToArray(number, \
|
||||||
|
repeated_##LOWERCASE##_value->Get(i), target); \
|
||||||
|
} \
|
||||||
|
break
|
||||||
|
|
||||||
|
HANDLE_TYPE( INT32, Int32, int32);
|
||||||
|
HANDLE_TYPE( INT64, Int64, int64);
|
||||||
|
HANDLE_TYPE( UINT32, UInt32, uint32);
|
||||||
|
HANDLE_TYPE( UINT64, UInt64, uint64);
|
||||||
|
HANDLE_TYPE( SINT32, SInt32, int32);
|
||||||
|
HANDLE_TYPE( SINT64, SInt64, int64);
|
||||||
|
HANDLE_TYPE( FIXED32, Fixed32, uint32);
|
||||||
|
HANDLE_TYPE( FIXED64, Fixed64, uint64);
|
||||||
|
HANDLE_TYPE(SFIXED32, SFixed32, int32);
|
||||||
|
HANDLE_TYPE(SFIXED64, SFixed64, int64);
|
||||||
|
HANDLE_TYPE( FLOAT, Float, float);
|
||||||
|
HANDLE_TYPE( DOUBLE, Double, double);
|
||||||
|
HANDLE_TYPE( BOOL, Bool, bool);
|
||||||
|
HANDLE_TYPE( STRING, String, string);
|
||||||
|
HANDLE_TYPE( BYTES, Bytes, string);
|
||||||
|
HANDLE_TYPE( ENUM, Enum, enum);
|
||||||
|
HANDLE_TYPE( GROUP, Group, message);
|
||||||
|
HANDLE_TYPE( MESSAGE, Message, message);
|
||||||
|
#undef HANDLE_TYPE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!is_cleared) {
|
||||||
|
switch (real_type(type)) {
|
||||||
|
#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \
|
||||||
|
case FieldDescriptor::TYPE_##UPPERCASE: \
|
||||||
|
target = WireFormatLite::Write##CAMELCASE##ToArray( \
|
||||||
|
number, VALUE, target); \
|
||||||
|
break
|
||||||
|
|
||||||
|
HANDLE_TYPE( INT32, Int32, int32_value);
|
||||||
|
HANDLE_TYPE( INT64, Int64, int64_value);
|
||||||
|
HANDLE_TYPE( UINT32, UInt32, uint32_value);
|
||||||
|
HANDLE_TYPE( UINT64, UInt64, uint64_value);
|
||||||
|
HANDLE_TYPE( SINT32, SInt32, int32_value);
|
||||||
|
HANDLE_TYPE( SINT64, SInt64, int64_value);
|
||||||
|
HANDLE_TYPE( FIXED32, Fixed32, uint32_value);
|
||||||
|
HANDLE_TYPE( FIXED64, Fixed64, uint64_value);
|
||||||
|
HANDLE_TYPE(SFIXED32, SFixed32, int32_value);
|
||||||
|
HANDLE_TYPE(SFIXED64, SFixed64, int64_value);
|
||||||
|
HANDLE_TYPE( FLOAT, Float, float_value);
|
||||||
|
HANDLE_TYPE( DOUBLE, Double, double_value);
|
||||||
|
HANDLE_TYPE( BOOL, Bool, bool_value);
|
||||||
|
HANDLE_TYPE( STRING, String, *string_value);
|
||||||
|
HANDLE_TYPE( BYTES, Bytes, *string_value);
|
||||||
|
HANDLE_TYPE( ENUM, Enum, enum_value);
|
||||||
|
HANDLE_TYPE( GROUP, Group, *message_value);
|
||||||
|
HANDLE_TYPE( MESSAGE, Message, *message_value);
|
||||||
|
#undef HANDLE_TYPE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray(
|
||||||
|
int number,
|
||||||
|
uint8* target) const {
|
||||||
|
if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
|
||||||
|
// Not a valid MessageSet extension, but serialize it the normal way.
|
||||||
|
GOOGLE_LOG(WARNING) << "Invalid message set extension.";
|
||||||
|
return SerializeFieldWithCachedSizesToArray(number, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_cleared) return target;
|
||||||
|
|
||||||
|
// Start group.
|
||||||
|
target = io::CodedOutputStream::WriteTagToArray(
|
||||||
|
WireFormatLite::kMessageSetItemStartTag, target);
|
||||||
|
// Write type ID.
|
||||||
|
target = WireFormatLite::WriteUInt32ToArray(
|
||||||
|
WireFormatLite::kMessageSetTypeIdNumber, number, target);
|
||||||
|
// Write message.
|
||||||
|
target = WireFormatLite::WriteMessageToArray(
|
||||||
|
WireFormatLite::kMessageSetMessageNumber, *message_value, target);
|
||||||
|
// End group.
|
||||||
|
target = io::CodedOutputStream::WriteTagToArray(
|
||||||
|
WireFormatLite::kMessageSetItemEndTag, target);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,642 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/extension_set.h>
|
||||||
|
#include <google/protobuf/unittest.pb.h>
|
||||||
|
#include <google/protobuf/test_util.h>
|
||||||
|
#include <google/protobuf/descriptor.pb.h>
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <google/protobuf/dynamic_message.h>
|
||||||
|
#include <google/protobuf/wire_format.h>
|
||||||
|
#include <google/protobuf/io/coded_stream.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||||
|
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
#include <google/protobuf/testing/googletest.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <google/protobuf/stubs/stl_util-inl.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace internal {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// This test closely mirrors google/protobuf/compiler/cpp/unittest.cc
|
||||||
|
// except that it uses extensions rather than regular fields.
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, Defaults) {
|
||||||
|
// Check that all default values are set correctly in the initial message.
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
|
||||||
|
TestUtil::ExpectExtensionsClear(message);
|
||||||
|
|
||||||
|
// Messages should return pointers to default instances until first use.
|
||||||
|
// (This is not checked by ExpectClear() since it is not actually true after
|
||||||
|
// the fields have been set and then cleared.)
|
||||||
|
EXPECT_EQ(&unittest::OptionalGroup_extension::default_instance(),
|
||||||
|
&message.GetExtension(unittest::optionalgroup_extension));
|
||||||
|
EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
|
||||||
|
&message.GetExtension(unittest::optional_nested_message_extension));
|
||||||
|
EXPECT_EQ(&unittest::ForeignMessage::default_instance(),
|
||||||
|
&message.GetExtension(
|
||||||
|
unittest::optional_foreign_message_extension));
|
||||||
|
EXPECT_EQ(&unittest_import::ImportMessage::default_instance(),
|
||||||
|
&message.GetExtension(unittest::optional_import_message_extension));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, Accessors) {
|
||||||
|
// Set every field to a unique value then go back and check all those
|
||||||
|
// values.
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
|
||||||
|
TestUtil::SetAllExtensions(&message);
|
||||||
|
TestUtil::ExpectAllExtensionsSet(message);
|
||||||
|
|
||||||
|
TestUtil::ModifyRepeatedExtensions(&message);
|
||||||
|
TestUtil::ExpectRepeatedExtensionsModified(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, Clear) {
|
||||||
|
// Set every field to a unique value, clear the message, then check that
|
||||||
|
// it is cleared.
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
|
||||||
|
TestUtil::SetAllExtensions(&message);
|
||||||
|
message.Clear();
|
||||||
|
TestUtil::ExpectExtensionsClear(message);
|
||||||
|
|
||||||
|
// Unlike with the defaults test, we do NOT expect that requesting embedded
|
||||||
|
// messages will return a pointer to the default instance. Instead, they
|
||||||
|
// should return the objects that were created when mutable_blah() was
|
||||||
|
// called.
|
||||||
|
EXPECT_NE(&unittest::OptionalGroup_extension::default_instance(),
|
||||||
|
&message.GetExtension(unittest::optionalgroup_extension));
|
||||||
|
EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(),
|
||||||
|
&message.GetExtension(unittest::optional_nested_message_extension));
|
||||||
|
EXPECT_NE(&unittest::ForeignMessage::default_instance(),
|
||||||
|
&message.GetExtension(
|
||||||
|
unittest::optional_foreign_message_extension));
|
||||||
|
EXPECT_NE(&unittest_import::ImportMessage::default_instance(),
|
||||||
|
&message.GetExtension(unittest::optional_import_message_extension));
|
||||||
|
|
||||||
|
// Make sure setting stuff again after clearing works. (This takes slightly
|
||||||
|
// different code paths since the objects are reused.)
|
||||||
|
TestUtil::SetAllExtensions(&message);
|
||||||
|
TestUtil::ExpectAllExtensionsSet(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, ClearOneField) {
|
||||||
|
// Set every field to a unique value, then clear one value and insure that
|
||||||
|
// only that one value is cleared.
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
|
||||||
|
TestUtil::SetAllExtensions(&message);
|
||||||
|
int64 original_value =
|
||||||
|
message.GetExtension(unittest::optional_int64_extension);
|
||||||
|
|
||||||
|
// Clear the field and make sure it shows up as cleared.
|
||||||
|
message.ClearExtension(unittest::optional_int64_extension);
|
||||||
|
EXPECT_FALSE(message.HasExtension(unittest::optional_int64_extension));
|
||||||
|
EXPECT_EQ(0, message.GetExtension(unittest::optional_int64_extension));
|
||||||
|
|
||||||
|
// Other adjacent fields should not be cleared.
|
||||||
|
EXPECT_TRUE(message.HasExtension(unittest::optional_int32_extension));
|
||||||
|
EXPECT_TRUE(message.HasExtension(unittest::optional_uint32_extension));
|
||||||
|
|
||||||
|
// Make sure if we set it again, then all fields are set.
|
||||||
|
message.SetExtension(unittest::optional_int64_extension, original_value);
|
||||||
|
TestUtil::ExpectAllExtensionsSet(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, CopyFrom) {
|
||||||
|
unittest::TestAllExtensions message1, message2;
|
||||||
|
string data;
|
||||||
|
|
||||||
|
TestUtil::SetAllExtensions(&message1);
|
||||||
|
message2.CopyFrom(message1);
|
||||||
|
TestUtil::ExpectAllExtensionsSet(message2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, CopyFromUpcasted) {
|
||||||
|
unittest::TestAllExtensions message1, message2;
|
||||||
|
string data;
|
||||||
|
const Message& upcasted_message = message1;
|
||||||
|
|
||||||
|
TestUtil::SetAllExtensions(&message1);
|
||||||
|
message2.CopyFrom(upcasted_message);
|
||||||
|
TestUtil::ExpectAllExtensionsSet(message2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, SwapWithEmpty) {
|
||||||
|
unittest::TestAllExtensions message1, message2;
|
||||||
|
TestUtil::SetAllExtensions(&message1);
|
||||||
|
|
||||||
|
TestUtil::ExpectAllExtensionsSet(message1);
|
||||||
|
TestUtil::ExpectExtensionsClear(message2);
|
||||||
|
message1.Swap(&message2);
|
||||||
|
TestUtil::ExpectAllExtensionsSet(message2);
|
||||||
|
TestUtil::ExpectExtensionsClear(message1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, SwapWithSelf) {
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
TestUtil::SetAllExtensions(&message);
|
||||||
|
|
||||||
|
TestUtil::ExpectAllExtensionsSet(message);
|
||||||
|
message.Swap(&message);
|
||||||
|
TestUtil::ExpectAllExtensionsSet(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, SerializationToArray) {
|
||||||
|
// Serialize as TestAllExtensions and parse as TestAllTypes to insure wire
|
||||||
|
// compatibility of extensions.
|
||||||
|
//
|
||||||
|
// This checks serialization to a flat array by explicitly reserving space in
|
||||||
|
// the string and calling the generated message's
|
||||||
|
// SerializeWithCachedSizesToArray.
|
||||||
|
unittest::TestAllExtensions source;
|
||||||
|
unittest::TestAllTypes destination;
|
||||||
|
TestUtil::SetAllExtensions(&source);
|
||||||
|
int size = source.ByteSize();
|
||||||
|
string data;
|
||||||
|
data.resize(size);
|
||||||
|
uint8* target = reinterpret_cast<uint8*>(string_as_array(&data));
|
||||||
|
uint8* end = source.SerializeWithCachedSizesToArray(target);
|
||||||
|
EXPECT_EQ(size, end - target);
|
||||||
|
EXPECT_TRUE(destination.ParseFromString(data));
|
||||||
|
TestUtil::ExpectAllFieldsSet(destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, SerializationToStream) {
|
||||||
|
// Serialize as TestAllExtensions and parse as TestAllTypes to insure wire
|
||||||
|
// compatibility of extensions.
|
||||||
|
//
|
||||||
|
// This checks serialization to an output stream by creating an array output
|
||||||
|
// stream that can only buffer 1 byte at a time - this prevents the message
|
||||||
|
// from ever jumping to the fast path, ensuring that serialization happens via
|
||||||
|
// the CodedOutputStream.
|
||||||
|
unittest::TestAllExtensions source;
|
||||||
|
unittest::TestAllTypes destination;
|
||||||
|
TestUtil::SetAllExtensions(&source);
|
||||||
|
int size = source.ByteSize();
|
||||||
|
string data;
|
||||||
|
data.resize(size);
|
||||||
|
{
|
||||||
|
io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
|
||||||
|
io::CodedOutputStream output_stream(&array_stream);
|
||||||
|
source.SerializeWithCachedSizes(&output_stream);
|
||||||
|
ASSERT_FALSE(output_stream.HadError());
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(destination.ParseFromString(data));
|
||||||
|
TestUtil::ExpectAllFieldsSet(destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, PackedSerializationToArray) {
|
||||||
|
// Serialize as TestPackedExtensions and parse as TestPackedTypes to insure
|
||||||
|
// wire compatibility of extensions.
|
||||||
|
//
|
||||||
|
// This checks serialization to a flat array by explicitly reserving space in
|
||||||
|
// the string and calling the generated message's
|
||||||
|
// SerializeWithCachedSizesToArray.
|
||||||
|
unittest::TestPackedExtensions source;
|
||||||
|
unittest::TestPackedTypes destination;
|
||||||
|
TestUtil::SetPackedExtensions(&source);
|
||||||
|
int size = source.ByteSize();
|
||||||
|
string data;
|
||||||
|
data.resize(size);
|
||||||
|
uint8* target = reinterpret_cast<uint8*>(string_as_array(&data));
|
||||||
|
uint8* end = source.SerializeWithCachedSizesToArray(target);
|
||||||
|
EXPECT_EQ(size, end - target);
|
||||||
|
EXPECT_TRUE(destination.ParseFromString(data));
|
||||||
|
TestUtil::ExpectPackedFieldsSet(destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, PackedSerializationToStream) {
|
||||||
|
// Serialize as TestPackedExtensions and parse as TestPackedTypes to insure
|
||||||
|
// wire compatibility of extensions.
|
||||||
|
//
|
||||||
|
// This checks serialization to an output stream by creating an array output
|
||||||
|
// stream that can only buffer 1 byte at a time - this prevents the message
|
||||||
|
// from ever jumping to the fast path, ensuring that serialization happens via
|
||||||
|
// the CodedOutputStream.
|
||||||
|
unittest::TestPackedExtensions source;
|
||||||
|
unittest::TestPackedTypes destination;
|
||||||
|
TestUtil::SetPackedExtensions(&source);
|
||||||
|
int size = source.ByteSize();
|
||||||
|
string data;
|
||||||
|
data.resize(size);
|
||||||
|
{
|
||||||
|
io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
|
||||||
|
io::CodedOutputStream output_stream(&array_stream);
|
||||||
|
source.SerializeWithCachedSizes(&output_stream);
|
||||||
|
ASSERT_FALSE(output_stream.HadError());
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(destination.ParseFromString(data));
|
||||||
|
TestUtil::ExpectPackedFieldsSet(destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, Parsing) {
|
||||||
|
// Serialize as TestAllTypes and parse as TestAllExtensions.
|
||||||
|
unittest::TestAllTypes source;
|
||||||
|
unittest::TestAllExtensions destination;
|
||||||
|
string data;
|
||||||
|
|
||||||
|
TestUtil::SetAllFields(&source);
|
||||||
|
source.SerializeToString(&data);
|
||||||
|
EXPECT_TRUE(destination.ParseFromString(data));
|
||||||
|
TestUtil::ExpectAllExtensionsSet(destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, PackedParsing) {
|
||||||
|
// Serialize as TestPackedTypes and parse as TestPackedExtensions.
|
||||||
|
unittest::TestPackedTypes source;
|
||||||
|
unittest::TestPackedExtensions destination;
|
||||||
|
string data;
|
||||||
|
|
||||||
|
TestUtil::SetPackedFields(&source);
|
||||||
|
source.SerializeToString(&data);
|
||||||
|
EXPECT_TRUE(destination.ParseFromString(data));
|
||||||
|
TestUtil::ExpectPackedExtensionsSet(destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, IsInitialized) {
|
||||||
|
// Test that IsInitialized() returns false if required fields in nested
|
||||||
|
// extensions are missing.
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
|
||||||
|
EXPECT_TRUE(message.IsInitialized());
|
||||||
|
|
||||||
|
message.MutableExtension(unittest::TestRequired::single);
|
||||||
|
EXPECT_FALSE(message.IsInitialized());
|
||||||
|
|
||||||
|
message.MutableExtension(unittest::TestRequired::single)->set_a(1);
|
||||||
|
EXPECT_FALSE(message.IsInitialized());
|
||||||
|
message.MutableExtension(unittest::TestRequired::single)->set_b(2);
|
||||||
|
EXPECT_FALSE(message.IsInitialized());
|
||||||
|
message.MutableExtension(unittest::TestRequired::single)->set_c(3);
|
||||||
|
EXPECT_TRUE(message.IsInitialized());
|
||||||
|
|
||||||
|
message.AddExtension(unittest::TestRequired::multi);
|
||||||
|
EXPECT_FALSE(message.IsInitialized());
|
||||||
|
|
||||||
|
message.MutableExtension(unittest::TestRequired::multi, 0)->set_a(1);
|
||||||
|
EXPECT_FALSE(message.IsInitialized());
|
||||||
|
message.MutableExtension(unittest::TestRequired::multi, 0)->set_b(2);
|
||||||
|
EXPECT_FALSE(message.IsInitialized());
|
||||||
|
message.MutableExtension(unittest::TestRequired::multi, 0)->set_c(3);
|
||||||
|
EXPECT_TRUE(message.IsInitialized());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, MutableString) {
|
||||||
|
// Test the mutable string accessors.
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
|
||||||
|
message.MutableExtension(unittest::optional_string_extension)->assign("foo");
|
||||||
|
EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension));
|
||||||
|
EXPECT_EQ("foo", message.GetExtension(unittest::optional_string_extension));
|
||||||
|
|
||||||
|
message.AddExtension(unittest::repeated_string_extension)->assign("bar");
|
||||||
|
ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_string_extension));
|
||||||
|
EXPECT_EQ("bar",
|
||||||
|
message.GetExtension(unittest::repeated_string_extension, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, SpaceUsedExcludingSelf) {
|
||||||
|
// Scalar primitive extensions should increase the extension set size by a
|
||||||
|
// minimum of the size of the primitive type.
|
||||||
|
#define TEST_SCALAR_EXTENSIONS_SPACE_USED(type, value) \
|
||||||
|
do { \
|
||||||
|
unittest::TestAllExtensions message; \
|
||||||
|
const int base_size = message.SpaceUsed(); \
|
||||||
|
message.SetExtension(unittest::optional_##type##_extension, value); \
|
||||||
|
int min_expected_size = base_size + \
|
||||||
|
sizeof(message.GetExtension(unittest::optional_##type##_extension)); \
|
||||||
|
EXPECT_LE(min_expected_size, message.SpaceUsed()); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(int32 , 101);
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(int64 , 102);
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(uint32 , 103);
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(uint64 , 104);
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(sint32 , 105);
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(sint64 , 106);
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(fixed32 , 107);
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(fixed64 , 108);
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(sfixed32, 109);
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(sfixed64, 110);
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(float , 111);
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(double , 112);
|
||||||
|
TEST_SCALAR_EXTENSIONS_SPACE_USED(bool , true);
|
||||||
|
#undef TEST_SCALAR_EXTENSIONS_SPACE_USED
|
||||||
|
{
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
const int base_size = message.SpaceUsed();
|
||||||
|
message.SetExtension(unittest::optional_nested_enum_extension,
|
||||||
|
unittest::TestAllTypes::FOO);
|
||||||
|
int min_expected_size = base_size +
|
||||||
|
sizeof(message.GetExtension(unittest::optional_nested_enum_extension));
|
||||||
|
EXPECT_LE(min_expected_size, message.SpaceUsed());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Strings may cause extra allocations depending on their length; ensure
|
||||||
|
// that gets included as well.
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
const int base_size = message.SpaceUsed();
|
||||||
|
const string s("this is a fairly large string that will cause some "
|
||||||
|
"allocation in order to store it in the extension");
|
||||||
|
message.SetExtension(unittest::optional_string_extension, s);
|
||||||
|
int min_expected_size = base_size + s.length();
|
||||||
|
EXPECT_LE(min_expected_size, message.SpaceUsed());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Messages also have additional allocation that need to be counted.
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
const int base_size = message.SpaceUsed();
|
||||||
|
unittest::ForeignMessage foreign;
|
||||||
|
foreign.set_c(42);
|
||||||
|
message.MutableExtension(unittest::optional_foreign_message_extension)->
|
||||||
|
CopyFrom(foreign);
|
||||||
|
int min_expected_size = base_size + foreign.SpaceUsed();
|
||||||
|
EXPECT_LE(min_expected_size, message.SpaceUsed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repeated primitive extensions will increase space used by at least a
|
||||||
|
// RepeatedField<T>, and will cause additional allocations when the array
|
||||||
|
// gets too big for the initial space.
|
||||||
|
// This macro:
|
||||||
|
// - Adds a value to the repeated extension, then clears it, establishing
|
||||||
|
// the base size.
|
||||||
|
// - Adds a small number of values, testing that it doesn't increase the
|
||||||
|
// SpaceUsed()
|
||||||
|
// - Adds a large number of values (requiring allocation in the repeated
|
||||||
|
// field), and ensures that that allocation is included in SpaceUsed()
|
||||||
|
#define TEST_REPEATED_EXTENSIONS_SPACE_USED(type, cpptype, value) \
|
||||||
|
do { \
|
||||||
|
unittest::TestAllExtensions message; \
|
||||||
|
const int base_size = message.SpaceUsed(); \
|
||||||
|
int min_expected_size = sizeof(RepeatedField<cpptype>) + base_size; \
|
||||||
|
message.AddExtension(unittest::repeated_##type##_extension, value); \
|
||||||
|
message.ClearExtension(unittest::repeated_##type##_extension); \
|
||||||
|
const int empty_repeated_field_size = message.SpaceUsed(); \
|
||||||
|
EXPECT_LE(min_expected_size, empty_repeated_field_size) << #type; \
|
||||||
|
message.AddExtension(unittest::repeated_##type##_extension, value); \
|
||||||
|
message.AddExtension(unittest::repeated_##type##_extension, value); \
|
||||||
|
EXPECT_EQ(empty_repeated_field_size, message.SpaceUsed()) << #type; \
|
||||||
|
message.ClearExtension(unittest::repeated_##type##_extension); \
|
||||||
|
for (int i = 0; i < 16; ++i) { \
|
||||||
|
message.AddExtension(unittest::repeated_##type##_extension, value); \
|
||||||
|
} \
|
||||||
|
int expected_size = sizeof(cpptype) * 16 + empty_repeated_field_size; \
|
||||||
|
EXPECT_EQ(expected_size, message.SpaceUsed()) << #type; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(int32 , int32 , 101);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(int64 , int64 , 102);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(uint32 , uint32, 103);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(uint64 , uint64, 104);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(sint32 , int32 , 105);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(sint64 , int64 , 106);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(fixed32 , uint32, 107);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(fixed64 , uint64, 108);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(sfixed32, int32 , 109);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(sfixed64, int64 , 110);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(float , float , 111);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(double , double, 112);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(bool , bool , true);
|
||||||
|
TEST_REPEATED_EXTENSIONS_SPACE_USED(nested_enum, int,
|
||||||
|
unittest::TestAllTypes::FOO);
|
||||||
|
#undef TEST_REPEATED_EXTENSIONS_SPACE_USED
|
||||||
|
// Repeated strings
|
||||||
|
{
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
const int base_size = message.SpaceUsed();
|
||||||
|
int min_expected_size = sizeof(RepeatedPtrField<string>) + base_size;
|
||||||
|
const string value(256, 'x');
|
||||||
|
// Once items are allocated, they may stick around even when cleared so
|
||||||
|
// without the hardcore memory management accessors there isn't a notion of
|
||||||
|
// the empty repeated field memory usage as there is with primitive types.
|
||||||
|
for (int i = 0; i < 16; ++i) {
|
||||||
|
message.AddExtension(unittest::repeated_string_extension, value);
|
||||||
|
}
|
||||||
|
min_expected_size += (sizeof(value) + value.size()) * 16;
|
||||||
|
EXPECT_LE(min_expected_size, message.SpaceUsed());
|
||||||
|
}
|
||||||
|
// Repeated messages
|
||||||
|
{
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
const int base_size = message.SpaceUsed();
|
||||||
|
int min_expected_size = sizeof(RepeatedPtrField<unittest::ForeignMessage>) +
|
||||||
|
base_size;
|
||||||
|
unittest::ForeignMessage prototype;
|
||||||
|
prototype.set_c(2);
|
||||||
|
for (int i = 0; i < 16; ++i) {
|
||||||
|
message.AddExtension(unittest::repeated_foreign_message_extension)->
|
||||||
|
CopyFrom(prototype);
|
||||||
|
}
|
||||||
|
min_expected_size += 16 * prototype.SpaceUsed();
|
||||||
|
EXPECT_LE(min_expected_size, message.SpaceUsed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, InvalidEnumDeath) {
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
EXPECT_DEBUG_DEATH(
|
||||||
|
message.SetExtension(unittest::optional_foreign_enum_extension,
|
||||||
|
static_cast<unittest::ForeignEnum>(53)),
|
||||||
|
"IsValid");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
TEST(ExtensionSetTest, DynamicExtensions) {
|
||||||
|
// Test adding a dynamic extension to a compiled-in message object.
|
||||||
|
|
||||||
|
FileDescriptorProto dynamic_proto;
|
||||||
|
dynamic_proto.set_name("dynamic_extensions_test.proto");
|
||||||
|
dynamic_proto.add_dependency(
|
||||||
|
unittest::TestAllExtensions::descriptor()->file()->name());
|
||||||
|
dynamic_proto.set_package("dynamic_extensions");
|
||||||
|
|
||||||
|
// Copy the fields and nested types from TestDynamicExtensions into our new
|
||||||
|
// proto, converting the fields into extensions.
|
||||||
|
const Descriptor* template_descriptor =
|
||||||
|
unittest::TestDynamicExtensions::descriptor();
|
||||||
|
DescriptorProto template_descriptor_proto;
|
||||||
|
template_descriptor->CopyTo(&template_descriptor_proto);
|
||||||
|
dynamic_proto.mutable_message_type()->MergeFrom(
|
||||||
|
template_descriptor_proto.nested_type());
|
||||||
|
dynamic_proto.mutable_enum_type()->MergeFrom(
|
||||||
|
template_descriptor_proto.enum_type());
|
||||||
|
dynamic_proto.mutable_extension()->MergeFrom(
|
||||||
|
template_descriptor_proto.field());
|
||||||
|
|
||||||
|
// For each extension that we added...
|
||||||
|
for (int i = 0; i < dynamic_proto.extension_size(); i++) {
|
||||||
|
// Set its extendee to TestAllExtensions.
|
||||||
|
FieldDescriptorProto* extension = dynamic_proto.mutable_extension(i);
|
||||||
|
extension->set_extendee(
|
||||||
|
unittest::TestAllExtensions::descriptor()->full_name());
|
||||||
|
|
||||||
|
// If the field refers to one of the types nested in TestDynamicExtensions,
|
||||||
|
// make it refer to the type in our dynamic proto instead.
|
||||||
|
string prefix = "." + template_descriptor->full_name() + ".";
|
||||||
|
if (extension->has_type_name()) {
|
||||||
|
string* type_name = extension->mutable_type_name();
|
||||||
|
if (HasPrefixString(*type_name, prefix)) {
|
||||||
|
type_name->replace(0, prefix.size(), ".dynamic_extensions.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now build the file, using the generated pool as an underlay.
|
||||||
|
DescriptorPool dynamic_pool(DescriptorPool::generated_pool());
|
||||||
|
const FileDescriptor* file = dynamic_pool.BuildFile(dynamic_proto);
|
||||||
|
ASSERT_TRUE(file != NULL);
|
||||||
|
DynamicMessageFactory dynamic_factory(&dynamic_pool);
|
||||||
|
dynamic_factory.SetDelegateToGeneratedFactory(true);
|
||||||
|
|
||||||
|
// Construct a message that we can parse with the extensions we defined.
|
||||||
|
// Since the extensions were based off of the fields of TestDynamicExtensions,
|
||||||
|
// we can use that message to create this test message.
|
||||||
|
string data;
|
||||||
|
{
|
||||||
|
unittest::TestDynamicExtensions message;
|
||||||
|
message.set_scalar_extension(123);
|
||||||
|
message.set_enum_extension(unittest::FOREIGN_BAR);
|
||||||
|
message.set_dynamic_enum_extension(
|
||||||
|
unittest::TestDynamicExtensions::DYNAMIC_BAZ);
|
||||||
|
message.mutable_message_extension()->set_c(456);
|
||||||
|
message.mutable_dynamic_message_extension()->set_dynamic_field(789);
|
||||||
|
message.add_repeated_extension("foo");
|
||||||
|
message.add_repeated_extension("bar");
|
||||||
|
message.add_packed_extension(12);
|
||||||
|
message.add_packed_extension(-34);
|
||||||
|
message.add_packed_extension(56);
|
||||||
|
message.add_packed_extension(-78);
|
||||||
|
|
||||||
|
// Also add some unknown fields.
|
||||||
|
|
||||||
|
// An unknown enum value (for a known field).
|
||||||
|
message.mutable_unknown_fields()->AddVarint(
|
||||||
|
unittest::TestDynamicExtensions::kDynamicEnumExtensionFieldNumber,
|
||||||
|
12345);
|
||||||
|
// A regular unknown field.
|
||||||
|
message.mutable_unknown_fields()->AddLengthDelimited(54321, "unknown");
|
||||||
|
|
||||||
|
message.SerializeToString(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we can parse this using our dynamic extension definitions...
|
||||||
|
unittest::TestAllExtensions message;
|
||||||
|
{
|
||||||
|
io::ArrayInputStream raw_input(data.data(), data.size());
|
||||||
|
io::CodedInputStream input(&raw_input);
|
||||||
|
input.SetExtensionRegistry(&dynamic_pool, &dynamic_factory);
|
||||||
|
ASSERT_TRUE(message.ParseFromCodedStream(&input));
|
||||||
|
ASSERT_TRUE(input.ConsumedEntireMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can we print it?
|
||||||
|
EXPECT_EQ(
|
||||||
|
"[dynamic_extensions.scalar_extension]: 123\n"
|
||||||
|
"[dynamic_extensions.enum_extension]: FOREIGN_BAR\n"
|
||||||
|
"[dynamic_extensions.dynamic_enum_extension]: DYNAMIC_BAZ\n"
|
||||||
|
"[dynamic_extensions.message_extension] {\n"
|
||||||
|
" c: 456\n"
|
||||||
|
"}\n"
|
||||||
|
"[dynamic_extensions.dynamic_message_extension] {\n"
|
||||||
|
" dynamic_field: 789\n"
|
||||||
|
"}\n"
|
||||||
|
"[dynamic_extensions.repeated_extension]: \"foo\"\n"
|
||||||
|
"[dynamic_extensions.repeated_extension]: \"bar\"\n"
|
||||||
|
"[dynamic_extensions.packed_extension]: 12\n"
|
||||||
|
"[dynamic_extensions.packed_extension]: -34\n"
|
||||||
|
"[dynamic_extensions.packed_extension]: 56\n"
|
||||||
|
"[dynamic_extensions.packed_extension]: -78\n"
|
||||||
|
"2002: 12345\n"
|
||||||
|
"54321: \"unknown\"\n",
|
||||||
|
message.DebugString());
|
||||||
|
|
||||||
|
// Can we serialize it?
|
||||||
|
// (Don't use EXPECT_EQ because we don't want to dump raw binary data to the
|
||||||
|
// terminal on failure.)
|
||||||
|
EXPECT_TRUE(message.SerializeAsString() == data);
|
||||||
|
|
||||||
|
// What if we parse using the reflection-based parser?
|
||||||
|
{
|
||||||
|
unittest::TestAllExtensions message2;
|
||||||
|
io::ArrayInputStream raw_input(data.data(), data.size());
|
||||||
|
io::CodedInputStream input(&raw_input);
|
||||||
|
input.SetExtensionRegistry(&dynamic_pool, &dynamic_factory);
|
||||||
|
ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &message2));
|
||||||
|
ASSERT_TRUE(input.ConsumedEntireMessage());
|
||||||
|
EXPECT_EQ(message.DebugString(), message2.DebugString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Are the embedded generated types actually using the generated objects?
|
||||||
|
{
|
||||||
|
const FieldDescriptor* message_extension =
|
||||||
|
file->FindExtensionByName("message_extension");
|
||||||
|
ASSERT_TRUE(message_extension != NULL);
|
||||||
|
const Message& sub_message =
|
||||||
|
message.GetReflection()->GetMessage(message, message_extension);
|
||||||
|
const unittest::ForeignMessage* typed_sub_message =
|
||||||
|
dynamic_cast<const unittest::ForeignMessage*>(&sub_message);
|
||||||
|
ASSERT_TRUE(typed_sub_message != NULL);
|
||||||
|
EXPECT_EQ(456, typed_sub_message->c());
|
||||||
|
}
|
||||||
|
|
||||||
|
// What does GetMessage() return for the embedded dynamic type if it isn't
|
||||||
|
// present?
|
||||||
|
{
|
||||||
|
const FieldDescriptor* dynamic_message_extension =
|
||||||
|
file->FindExtensionByName("dynamic_message_extension");
|
||||||
|
ASSERT_TRUE(dynamic_message_extension != NULL);
|
||||||
|
const Message& parent = unittest::TestAllExtensions::default_instance();
|
||||||
|
const Message& sub_message =
|
||||||
|
parent.GetReflection()->GetMessage(parent, dynamic_message_extension,
|
||||||
|
&dynamic_factory);
|
||||||
|
const Message* prototype =
|
||||||
|
dynamic_factory.GetPrototype(dynamic_message_extension->message_type());
|
||||||
|
EXPECT_EQ(prototype, &sub_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,424 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
//
|
||||||
|
// 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/message.h>
|
||||||
|
#include <google/protobuf/unknown_field_set.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
class DescriptorPool;
|
||||||
|
// Generated code needs these to have been forward-declared. Easier to do it
|
||||||
|
// here than to print them inside every .pb.h file.
|
||||||
|
class FileDescriptor;
|
||||||
|
class EnumDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace protobuf {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
~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;
|
||||||
|
void RemoveLast(Message* message, const FieldDescriptor* field) const;
|
||||||
|
void Swap(Message* message1, Message* message2) 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class GeneratedMessage;
|
||||||
|
|
||||||
|
const Descriptor* descriptor_;
|
||||||
|
const Message* default_instance_;
|
||||||
|
const int* offsets_;
|
||||||
|
|
||||||
|
int has_bits_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;
|
||||||
|
inline const Message* GetMessagePrototype(const FieldDescriptor* field) const;
|
||||||
|
|
||||||
|
inline const uint32* GetHasBits(const Message& message) const;
|
||||||
|
inline uint32* MutableHasBits(Message* message) 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;
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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_MESSAGE_REFLECTION_H__
|
@ -0,0 +1,839 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
//
|
||||||
|
// This implementation is heavily optimized to make reads and writes
|
||||||
|
// of small values (especially varints) as fast as possible. In
|
||||||
|
// particular, we optimize for the common case that a read or a write
|
||||||
|
// will not cross the end of the buffer, since we can avoid a lot
|
||||||
|
// of branching in this case.
|
||||||
|
|
||||||
|
#include <google/protobuf/io/coded_stream_inl.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/stubs/stl_util-inl.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace io {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
static const int kMaxVarintBytes = 10;
|
||||||
|
static const int kMaxVarint32Bytes = 5;
|
||||||
|
|
||||||
|
|
||||||
|
inline bool NextNonEmpty(ZeroCopyInputStream* input,
|
||||||
|
const void** data, int* size) {
|
||||||
|
bool success;
|
||||||
|
do {
|
||||||
|
success = input->Next(data, size);
|
||||||
|
} while (success && *size == 0);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// CodedInputStream ==================================================
|
||||||
|
|
||||||
|
|
||||||
|
void CodedInputStream::BackUpInputToCurrentPosition() {
|
||||||
|
int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
|
||||||
|
if (backup_bytes > 0) {
|
||||||
|
input_->BackUp(backup_bytes);
|
||||||
|
|
||||||
|
// total_bytes_read_ doesn't include overflow_bytes_.
|
||||||
|
total_bytes_read_ -= BufferSize() + buffer_size_after_limit_;
|
||||||
|
buffer_end_ = buffer_;
|
||||||
|
buffer_size_after_limit_ = 0;
|
||||||
|
overflow_bytes_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CodedInputStream::RecomputeBufferLimits() {
|
||||||
|
buffer_end_ += buffer_size_after_limit_;
|
||||||
|
int closest_limit = min(current_limit_, total_bytes_limit_);
|
||||||
|
if (closest_limit < total_bytes_read_) {
|
||||||
|
// The limit position is in the current buffer. We must adjust
|
||||||
|
// the buffer size accordingly.
|
||||||
|
buffer_size_after_limit_ = total_bytes_read_ - closest_limit;
|
||||||
|
buffer_end_ -= buffer_size_after_limit_;
|
||||||
|
} else {
|
||||||
|
buffer_size_after_limit_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
|
||||||
|
// Current position relative to the beginning of the stream.
|
||||||
|
int current_position = total_bytes_read_ -
|
||||||
|
(BufferSize() + buffer_size_after_limit_);
|
||||||
|
|
||||||
|
Limit old_limit = current_limit_;
|
||||||
|
|
||||||
|
// security: byte_limit is possibly evil, so check for negative values
|
||||||
|
// and overflow.
|
||||||
|
if (byte_limit >= 0 &&
|
||||||
|
byte_limit <= INT_MAX - current_position) {
|
||||||
|
current_limit_ = current_position + byte_limit;
|
||||||
|
} else {
|
||||||
|
// Negative or overflow.
|
||||||
|
current_limit_ = INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to enforce all limits, not just the new one, so if the previous
|
||||||
|
// limit was before the new requested limit, we continue to enforce the
|
||||||
|
// previous limit.
|
||||||
|
current_limit_ = min(current_limit_, old_limit);
|
||||||
|
|
||||||
|
RecomputeBufferLimits();
|
||||||
|
return old_limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodedInputStream::PopLimit(Limit limit) {
|
||||||
|
// The limit passed in is actually the *old* limit, which we returned from
|
||||||
|
// PushLimit().
|
||||||
|
current_limit_ = limit;
|
||||||
|
RecomputeBufferLimits();
|
||||||
|
|
||||||
|
// We may no longer be at a legitimate message end. ReadTag() needs to be
|
||||||
|
// called again to find out.
|
||||||
|
legitimate_message_end_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CodedInputStream::BytesUntilLimit() {
|
||||||
|
if (current_limit_ == INT_MAX) return -1;
|
||||||
|
int current_position = total_bytes_read_ -
|
||||||
|
(BufferSize() + buffer_size_after_limit_);
|
||||||
|
|
||||||
|
return current_limit_ - current_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodedInputStream::SetTotalBytesLimit(
|
||||||
|
int total_bytes_limit, int warning_threshold) {
|
||||||
|
// Make sure the limit isn't already past, since this could confuse other
|
||||||
|
// code.
|
||||||
|
int current_position = total_bytes_read_ -
|
||||||
|
(BufferSize() + buffer_size_after_limit_);
|
||||||
|
total_bytes_limit_ = max(current_position, total_bytes_limit);
|
||||||
|
total_bytes_warning_threshold_ = warning_threshold;
|
||||||
|
RecomputeBufferLimits();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodedInputStream::PrintTotalBytesLimitError() {
|
||||||
|
GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too "
|
||||||
|
"big (more than " << total_bytes_limit_
|
||||||
|
<< " bytes). To increase the limit (or to disable these "
|
||||||
|
"warnings), see CodedInputStream::SetTotalBytesLimit() "
|
||||||
|
"in google/protobuf/io/coded_stream.h.";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedInputStream::Skip(int count) {
|
||||||
|
if (count < 0) return false; // security: count is often user-supplied
|
||||||
|
|
||||||
|
const int original_buffer_size = BufferSize();
|
||||||
|
|
||||||
|
if (count <= original_buffer_size) {
|
||||||
|
// Just skipping within the current buffer. Easy.
|
||||||
|
Advance(count);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer_size_after_limit_ > 0) {
|
||||||
|
// We hit a limit inside this buffer. Advance to the limit and fail.
|
||||||
|
Advance(original_buffer_size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
count -= original_buffer_size;
|
||||||
|
buffer_ = NULL;
|
||||||
|
buffer_end_ = buffer_;
|
||||||
|
|
||||||
|
// Make sure this skip doesn't try to skip past the current limit.
|
||||||
|
int closest_limit = min(current_limit_, total_bytes_limit_);
|
||||||
|
int bytes_until_limit = closest_limit - total_bytes_read_;
|
||||||
|
if (bytes_until_limit < count) {
|
||||||
|
// We hit the limit. Skip up to it then fail.
|
||||||
|
if (bytes_until_limit > 0) {
|
||||||
|
total_bytes_read_ = closest_limit;
|
||||||
|
input_->Skip(bytes_until_limit);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_bytes_read_ += count;
|
||||||
|
return input_->Skip(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
|
||||||
|
if (BufferSize() == 0 && !Refresh()) return false;
|
||||||
|
|
||||||
|
*data = buffer_;
|
||||||
|
*size = BufferSize();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedInputStream::ReadRaw(void* buffer, int size) {
|
||||||
|
int current_buffer_size;
|
||||||
|
while ((current_buffer_size = BufferSize()) < size) {
|
||||||
|
// Reading past end of buffer. Copy what we have, then refresh.
|
||||||
|
memcpy(buffer, buffer_, current_buffer_size);
|
||||||
|
buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
|
||||||
|
size -= current_buffer_size;
|
||||||
|
Advance(current_buffer_size);
|
||||||
|
if (!Refresh()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, buffer_, size);
|
||||||
|
Advance(size);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedInputStream::ReadString(string* buffer, int size) {
|
||||||
|
if (size < 0) return false; // security: size is often user-supplied
|
||||||
|
return InternalReadStringInline(buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedInputStream::ReadStringFallback(string* buffer, int size) {
|
||||||
|
if (!buffer->empty()) {
|
||||||
|
buffer->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int current_buffer_size;
|
||||||
|
while ((current_buffer_size = BufferSize()) < size) {
|
||||||
|
// Some STL implementations "helpfully" crash on buffer->append(NULL, 0).
|
||||||
|
if (current_buffer_size != 0) {
|
||||||
|
// Note: string1.append(string2) is O(string2.size()) (as opposed to
|
||||||
|
// O(string1.size() + string2.size()), which would be bad).
|
||||||
|
buffer->append(reinterpret_cast<const char*>(buffer_),
|
||||||
|
current_buffer_size);
|
||||||
|
}
|
||||||
|
size -= current_buffer_size;
|
||||||
|
Advance(current_buffer_size);
|
||||||
|
if (!Refresh()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->append(reinterpret_cast<const char*>(buffer_), size);
|
||||||
|
Advance(size);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) {
|
||||||
|
uint8 bytes[sizeof(*value)];
|
||||||
|
|
||||||
|
const uint8* ptr;
|
||||||
|
if (BufferSize() >= sizeof(*value)) {
|
||||||
|
// Fast path: Enough bytes in the buffer to read directly.
|
||||||
|
ptr = buffer_;
|
||||||
|
Advance(sizeof(*value));
|
||||||
|
} else {
|
||||||
|
// Slow path: Had to read past the end of the buffer.
|
||||||
|
if (!ReadRaw(bytes, sizeof(*value))) return false;
|
||||||
|
ptr = bytes;
|
||||||
|
}
|
||||||
|
ReadLittleEndian32FromArray(ptr, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
|
||||||
|
uint8 bytes[sizeof(*value)];
|
||||||
|
|
||||||
|
const uint8* ptr;
|
||||||
|
if (BufferSize() >= sizeof(*value)) {
|
||||||
|
// Fast path: Enough bytes in the buffer to read directly.
|
||||||
|
ptr = buffer_;
|
||||||
|
Advance(sizeof(*value));
|
||||||
|
} else {
|
||||||
|
// Slow path: Had to read past the end of the buffer.
|
||||||
|
if (!ReadRaw(bytes, sizeof(*value))) return false;
|
||||||
|
ptr = bytes;
|
||||||
|
}
|
||||||
|
ReadLittleEndian64FromArray(ptr, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
inline const uint8* ReadVarint32FromArray(
|
||||||
|
const uint8* buffer, uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
|
||||||
|
inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) {
|
||||||
|
// Fast path: We have enough bytes left in the buffer to guarantee that
|
||||||
|
// this read won't cross the end, so we can skip the checks.
|
||||||
|
const uint8* ptr = buffer;
|
||||||
|
uint32 b;
|
||||||
|
uint32 result;
|
||||||
|
|
||||||
|
b = *(ptr++); result = (b & 0x7F) ; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); result |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); result |= b << 28; if (!(b & 0x80)) goto done;
|
||||||
|
|
||||||
|
// If the input is larger than 32 bits, we still need to read it all
|
||||||
|
// and discard the high-order bits.
|
||||||
|
for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
|
||||||
|
b = *(ptr++); if (!(b & 0x80)) goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have overrun the maximum size of a varint (10 bytes). Assume
|
||||||
|
// the data is corrupt.
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
done:
|
||||||
|
*value = result;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool CodedInputStream::ReadVarint32Slow(uint32* value) {
|
||||||
|
uint64 result;
|
||||||
|
// Directly invoke ReadVarint64Fallback, since we already tried to optimize
|
||||||
|
// for one-byte varints.
|
||||||
|
if (!ReadVarint64Fallback(&result)) return false;
|
||||||
|
*value = (uint32)result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedInputStream::ReadVarint32Fallback(uint32* value) {
|
||||||
|
if (BufferSize() >= kMaxVarintBytes ||
|
||||||
|
// Optimization: If the varint ends at exactly the end of the buffer,
|
||||||
|
// we can detect that and still use the fast path.
|
||||||
|
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
|
||||||
|
const uint8* end = ReadVarint32FromArray(buffer_, value);
|
||||||
|
if (end == NULL) return false;
|
||||||
|
buffer_ = end;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// Really slow case: we will incur the cost of an extra function call here,
|
||||||
|
// but moving this out of line reduces the size of this function, which
|
||||||
|
// improves the common case. In micro benchmarks, this is worth about 10-15%
|
||||||
|
return ReadVarint32Slow(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CodedInputStream::ReadTagSlow() {
|
||||||
|
if (buffer_ == buffer_end_) {
|
||||||
|
// Call refresh.
|
||||||
|
if (!Refresh()) {
|
||||||
|
// Refresh failed. Make sure that it failed due to EOF, not because
|
||||||
|
// we hit total_bytes_limit_, which, unlike normal limits, is not a
|
||||||
|
// valid place to end a message.
|
||||||
|
int current_position = total_bytes_read_ - buffer_size_after_limit_;
|
||||||
|
if (current_position >= total_bytes_limit_) {
|
||||||
|
// Hit total_bytes_limit_. But if we also hit the normal limit,
|
||||||
|
// we're still OK.
|
||||||
|
legitimate_message_end_ = current_limit_ == total_bytes_limit_;
|
||||||
|
} else {
|
||||||
|
legitimate_message_end_ = true;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
|
||||||
|
// again, since we have now refreshed the buffer.
|
||||||
|
uint64 result;
|
||||||
|
if (!ReadVarint64(&result)) return 0;
|
||||||
|
return static_cast<uint32>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CodedInputStream::ReadTagFallback() {
|
||||||
|
if (BufferSize() >= kMaxVarintBytes ||
|
||||||
|
// Optimization: If the varint ends at exactly the end of the buffer,
|
||||||
|
// we can detect that and still use the fast path.
|
||||||
|
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
|
||||||
|
uint32 tag;
|
||||||
|
const uint8* end = ReadVarint32FromArray(buffer_, &tag);
|
||||||
|
if (end == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
buffer_ = end;
|
||||||
|
return tag;
|
||||||
|
} else {
|
||||||
|
// We are commonly at a limit when attempting to read tags. Try to quickly
|
||||||
|
// detect this case without making another function call.
|
||||||
|
if (buffer_ == buffer_end_ && buffer_size_after_limit_ > 0 &&
|
||||||
|
// Make sure that the limit we hit is not total_bytes_limit_, since
|
||||||
|
// in that case we still need to call Refresh() so that it prints an
|
||||||
|
// error.
|
||||||
|
total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
|
||||||
|
// We hit a byte limit.
|
||||||
|
legitimate_message_end_ = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ReadTagSlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedInputStream::ReadVarint64Slow(uint64* value) {
|
||||||
|
// Slow path: This read might cross the end of the buffer, so we
|
||||||
|
// need to check and refresh the buffer if and when it does.
|
||||||
|
|
||||||
|
uint64 result = 0;
|
||||||
|
int count = 0;
|
||||||
|
uint32 b;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (count == kMaxVarintBytes) return false;
|
||||||
|
while (buffer_ == buffer_end_) {
|
||||||
|
if (!Refresh()) return false;
|
||||||
|
}
|
||||||
|
b = *buffer_;
|
||||||
|
result |= static_cast<uint64>(b & 0x7F) << (7 * count);
|
||||||
|
Advance(1);
|
||||||
|
++count;
|
||||||
|
} while (b & 0x80);
|
||||||
|
|
||||||
|
*value = result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedInputStream::ReadVarint64Fallback(uint64* value) {
|
||||||
|
if (BufferSize() >= kMaxVarintBytes ||
|
||||||
|
// Optimization: If the varint ends at exactly the end of the buffer,
|
||||||
|
// we can detect that and still use the fast path.
|
||||||
|
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
|
||||||
|
// Fast path: We have enough bytes left in the buffer to guarantee that
|
||||||
|
// this read won't cross the end, so we can skip the checks.
|
||||||
|
|
||||||
|
const uint8* ptr = buffer_;
|
||||||
|
uint32 b;
|
||||||
|
|
||||||
|
// Splitting into 32-bit pieces gives better performance on 32-bit
|
||||||
|
// processors.
|
||||||
|
uint32 part0 = 0, part1 = 0, part2 = 0;
|
||||||
|
|
||||||
|
b = *(ptr++); part0 = (b & 0x7F) ; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); part0 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); part0 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); part0 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); part1 = (b & 0x7F) ; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); part1 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); part1 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); part1 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); part2 = (b & 0x7F) ; if (!(b & 0x80)) goto done;
|
||||||
|
b = *(ptr++); part2 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
|
||||||
|
|
||||||
|
// We have overrun the maximum size of a varint (10 bytes). The data
|
||||||
|
// must be corrupt.
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
done:
|
||||||
|
Advance(ptr - buffer_);
|
||||||
|
*value = (static_cast<uint64>(part0) ) |
|
||||||
|
(static_cast<uint64>(part1) << 28) |
|
||||||
|
(static_cast<uint64>(part2) << 56);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return ReadVarint64Slow(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedInputStream::Refresh() {
|
||||||
|
GOOGLE_DCHECK_EQ(0, BufferSize());
|
||||||
|
|
||||||
|
if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 ||
|
||||||
|
total_bytes_read_ == current_limit_) {
|
||||||
|
// We've hit a limit. Stop.
|
||||||
|
int current_position = total_bytes_read_ - buffer_size_after_limit_;
|
||||||
|
|
||||||
|
if (current_position >= total_bytes_limit_ &&
|
||||||
|
total_bytes_limit_ != current_limit_) {
|
||||||
|
// Hit total_bytes_limit_.
|
||||||
|
PrintTotalBytesLimitError();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (total_bytes_warning_threshold_ >= 0 &&
|
||||||
|
total_bytes_read_ >= total_bytes_warning_threshold_) {
|
||||||
|
GOOGLE_LOG(WARNING) << "Reading dangerously large protocol message. If the "
|
||||||
|
"message turns out to be larger than "
|
||||||
|
<< total_bytes_limit_ << " bytes, parsing will be halted "
|
||||||
|
"for security reasons. To increase the limit (or to "
|
||||||
|
"disable these warnings), see "
|
||||||
|
"CodedInputStream::SetTotalBytesLimit() in "
|
||||||
|
"google/protobuf/io/coded_stream.h.";
|
||||||
|
|
||||||
|
// Don't warn again for this stream.
|
||||||
|
total_bytes_warning_threshold_ = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* void_buffer;
|
||||||
|
int buffer_size;
|
||||||
|
if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
|
||||||
|
buffer_ = reinterpret_cast<const uint8*>(void_buffer);
|
||||||
|
buffer_end_ = buffer_ + buffer_size;
|
||||||
|
GOOGLE_CHECK_GE(buffer_size, 0);
|
||||||
|
|
||||||
|
if (total_bytes_read_ <= INT_MAX - buffer_size) {
|
||||||
|
total_bytes_read_ += buffer_size;
|
||||||
|
} else {
|
||||||
|
// Overflow. Reset buffer_end_ to not include the bytes beyond INT_MAX.
|
||||||
|
// We can't get that far anyway, because total_bytes_limit_ is guaranteed
|
||||||
|
// to be less than it. We need to keep track of the number of bytes
|
||||||
|
// we discarded, though, so that we can call input_->BackUp() to back
|
||||||
|
// up over them on destruction.
|
||||||
|
|
||||||
|
// The following line is equivalent to:
|
||||||
|
// overflow_bytes_ = total_bytes_read_ + buffer_size - INT_MAX;
|
||||||
|
// except that it avoids overflows. Signed integer overflow has
|
||||||
|
// undefined results according to the C standard.
|
||||||
|
overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size);
|
||||||
|
buffer_end_ -= overflow_bytes_;
|
||||||
|
total_bytes_read_ = INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecomputeBufferLimits();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
buffer_ = NULL;
|
||||||
|
buffer_end_ = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CodedOutputStream =================================================
|
||||||
|
|
||||||
|
CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
|
||||||
|
: output_(output),
|
||||||
|
buffer_(NULL),
|
||||||
|
buffer_size_(0),
|
||||||
|
total_bytes_(0),
|
||||||
|
had_error_(false) {
|
||||||
|
// Eagerly Refresh() so buffer space is immediately available.
|
||||||
|
Refresh();
|
||||||
|
// The Refresh() may have failed. If the client doesn't write any data,
|
||||||
|
// though, don't consider this an error. If the client does write data, then
|
||||||
|
// another Refresh() will be attempted and it will set the error once again.
|
||||||
|
had_error_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodedOutputStream::~CodedOutputStream() {
|
||||||
|
if (buffer_size_ > 0) {
|
||||||
|
output_->BackUp(buffer_size_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedOutputStream::Skip(int count) {
|
||||||
|
if (count < 0) return false;
|
||||||
|
|
||||||
|
while (count > buffer_size_) {
|
||||||
|
count -= buffer_size_;
|
||||||
|
if (!Refresh()) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Advance(count);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedOutputStream::GetDirectBufferPointer(void** data, int* size) {
|
||||||
|
if (buffer_size_ == 0 && !Refresh()) return false;
|
||||||
|
|
||||||
|
*data = buffer_;
|
||||||
|
*size = buffer_size_;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodedOutputStream::WriteRaw(const void* data, int size) {
|
||||||
|
while (buffer_size_ < size) {
|
||||||
|
memcpy(buffer_, data, buffer_size_);
|
||||||
|
size -= buffer_size_;
|
||||||
|
data = reinterpret_cast<const uint8*>(data) + buffer_size_;
|
||||||
|
if (!Refresh()) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer_, data, size);
|
||||||
|
Advance(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8* CodedOutputStream::WriteRawToArray(
|
||||||
|
const void* data, int size, uint8* target) {
|
||||||
|
memcpy(target, data, size);
|
||||||
|
return target + size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CodedOutputStream::WriteLittleEndian32(uint32 value) {
|
||||||
|
uint8 bytes[sizeof(value)];
|
||||||
|
|
||||||
|
bool use_fast = buffer_size_ >= sizeof(value);
|
||||||
|
uint8* ptr = use_fast ? buffer_ : bytes;
|
||||||
|
|
||||||
|
WriteLittleEndian32ToArray(value, ptr);
|
||||||
|
|
||||||
|
if (use_fast) {
|
||||||
|
Advance(sizeof(value));
|
||||||
|
} else {
|
||||||
|
WriteRaw(bytes, sizeof(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodedOutputStream::WriteLittleEndian64(uint64 value) {
|
||||||
|
uint8 bytes[sizeof(value)];
|
||||||
|
|
||||||
|
bool use_fast = buffer_size_ >= sizeof(value);
|
||||||
|
uint8* ptr = use_fast ? buffer_ : bytes;
|
||||||
|
|
||||||
|
WriteLittleEndian64ToArray(value, ptr);
|
||||||
|
|
||||||
|
if (use_fast) {
|
||||||
|
Advance(sizeof(value));
|
||||||
|
} else {
|
||||||
|
WriteRaw(bytes, sizeof(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline(
|
||||||
|
uint32 value, uint8* target) {
|
||||||
|
target[0] = static_cast<uint8>(value | 0x80);
|
||||||
|
if (value >= (1 << 7)) {
|
||||||
|
target[1] = static_cast<uint8>((value >> 7) | 0x80);
|
||||||
|
if (value >= (1 << 14)) {
|
||||||
|
target[2] = static_cast<uint8>((value >> 14) | 0x80);
|
||||||
|
if (value >= (1 << 21)) {
|
||||||
|
target[3] = static_cast<uint8>((value >> 21) | 0x80);
|
||||||
|
if (value >= (1 << 28)) {
|
||||||
|
target[4] = static_cast<uint8>(value >> 28);
|
||||||
|
return target + 5;
|
||||||
|
} else {
|
||||||
|
target[3] &= 0x7F;
|
||||||
|
return target + 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
target[2] &= 0x7F;
|
||||||
|
return target + 3;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
target[1] &= 0x7F;
|
||||||
|
return target + 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
target[0] &= 0x7F;
|
||||||
|
return target + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodedOutputStream::WriteVarint32(uint32 value) {
|
||||||
|
if (buffer_size_ >= kMaxVarint32Bytes) {
|
||||||
|
// Fast path: We have enough bytes left in the buffer to guarantee that
|
||||||
|
// this write won't cross the end, so we can skip the checks.
|
||||||
|
uint8* target = buffer_;
|
||||||
|
uint8* end = WriteVarint32FallbackToArrayInline(value, target);
|
||||||
|
int size = end - target;
|
||||||
|
Advance(size);
|
||||||
|
} else {
|
||||||
|
// Slow path: This write might cross the end of the buffer, so we
|
||||||
|
// compose the bytes first then use WriteRaw().
|
||||||
|
uint8 bytes[kMaxVarint32Bytes];
|
||||||
|
int size = 0;
|
||||||
|
while (value > 0x7F) {
|
||||||
|
bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
|
||||||
|
value >>= 7;
|
||||||
|
}
|
||||||
|
bytes[size++] = static_cast<uint8>(value) & 0x7F;
|
||||||
|
WriteRaw(bytes, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8* CodedOutputStream::WriteVarint32FallbackToArray(
|
||||||
|
uint32 value, uint8* target) {
|
||||||
|
return WriteVarint32FallbackToArrayInline(value, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8* CodedOutputStream::WriteVarint64ToArrayInline(
|
||||||
|
uint64 value, uint8* target) {
|
||||||
|
// Splitting into 32-bit pieces gives better performance on 32-bit
|
||||||
|
// processors.
|
||||||
|
uint32 part0 = static_cast<uint32>(value );
|
||||||
|
uint32 part1 = static_cast<uint32>(value >> 28);
|
||||||
|
uint32 part2 = static_cast<uint32>(value >> 56);
|
||||||
|
|
||||||
|
int size;
|
||||||
|
|
||||||
|
// Here we can't really optimize for small numbers, since the value is
|
||||||
|
// split into three parts. Cheking for numbers < 128, for instance,
|
||||||
|
// would require three comparisons, since you'd have to make sure part1
|
||||||
|
// and part2 are zero. However, if the caller is using 64-bit integers,
|
||||||
|
// it is likely that they expect the numbers to often be very large, so
|
||||||
|
// we probably don't want to optimize for small numbers anyway. Thus,
|
||||||
|
// we end up with a hardcoded binary search tree...
|
||||||
|
if (part2 == 0) {
|
||||||
|
if (part1 == 0) {
|
||||||
|
if (part0 < (1 << 14)) {
|
||||||
|
if (part0 < (1 << 7)) {
|
||||||
|
size = 1; goto size1;
|
||||||
|
} else {
|
||||||
|
size = 2; goto size2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (part0 < (1 << 21)) {
|
||||||
|
size = 3; goto size3;
|
||||||
|
} else {
|
||||||
|
size = 4; goto size4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (part1 < (1 << 14)) {
|
||||||
|
if (part1 < (1 << 7)) {
|
||||||
|
size = 5; goto size5;
|
||||||
|
} else {
|
||||||
|
size = 6; goto size6;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (part1 < (1 << 21)) {
|
||||||
|
size = 7; goto size7;
|
||||||
|
} else {
|
||||||
|
size = 8; goto size8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (part2 < (1 << 7)) {
|
||||||
|
size = 9; goto size9;
|
||||||
|
} else {
|
||||||
|
size = 10; goto size10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||||
|
|
||||||
|
size10: target[9] = static_cast<uint8>((part2 >> 7) | 0x80);
|
||||||
|
size9 : target[8] = static_cast<uint8>((part2 ) | 0x80);
|
||||||
|
size8 : target[7] = static_cast<uint8>((part1 >> 21) | 0x80);
|
||||||
|
size7 : target[6] = static_cast<uint8>((part1 >> 14) | 0x80);
|
||||||
|
size6 : target[5] = static_cast<uint8>((part1 >> 7) | 0x80);
|
||||||
|
size5 : target[4] = static_cast<uint8>((part1 ) | 0x80);
|
||||||
|
size4 : target[3] = static_cast<uint8>((part0 >> 21) | 0x80);
|
||||||
|
size3 : target[2] = static_cast<uint8>((part0 >> 14) | 0x80);
|
||||||
|
size2 : target[1] = static_cast<uint8>((part0 >> 7) | 0x80);
|
||||||
|
size1 : target[0] = static_cast<uint8>((part0 ) | 0x80);
|
||||||
|
|
||||||
|
target[size-1] &= 0x7F;
|
||||||
|
return target + size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodedOutputStream::WriteVarint64(uint64 value) {
|
||||||
|
if (buffer_size_ >= kMaxVarintBytes) {
|
||||||
|
// Fast path: We have enough bytes left in the buffer to guarantee that
|
||||||
|
// this write won't cross the end, so we can skip the checks.
|
||||||
|
uint8* target = buffer_;
|
||||||
|
|
||||||
|
uint8* end = WriteVarint64ToArrayInline(value, target);
|
||||||
|
int size = end - target;
|
||||||
|
Advance(size);
|
||||||
|
} else {
|
||||||
|
// Slow path: This write might cross the end of the buffer, so we
|
||||||
|
// compose the bytes first then use WriteRaw().
|
||||||
|
uint8 bytes[kMaxVarintBytes];
|
||||||
|
int size = 0;
|
||||||
|
while (value > 0x7F) {
|
||||||
|
bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
|
||||||
|
value >>= 7;
|
||||||
|
}
|
||||||
|
bytes[size++] = static_cast<uint8>(value) & 0x7F;
|
||||||
|
WriteRaw(bytes, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8* CodedOutputStream::WriteVarint64ToArray(
|
||||||
|
uint64 value, uint8* target) {
|
||||||
|
return WriteVarint64ToArrayInline(value, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodedOutputStream::Refresh() {
|
||||||
|
void* void_buffer;
|
||||||
|
if (output_->Next(&void_buffer, &buffer_size_)) {
|
||||||
|
buffer_ = reinterpret_cast<uint8*>(void_buffer);
|
||||||
|
total_bytes_ += buffer_size_;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
buffer_ = NULL;
|
||||||
|
buffer_size_ = 0;
|
||||||
|
had_error_ = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CodedOutputStream::VarintSize32Fallback(uint32 value) {
|
||||||
|
if (value < (1 << 7)) {
|
||||||
|
return 1;
|
||||||
|
} else if (value < (1 << 14)) {
|
||||||
|
return 2;
|
||||||
|
} else if (value < (1 << 21)) {
|
||||||
|
return 3;
|
||||||
|
} else if (value < (1 << 28)) {
|
||||||
|
return 4;
|
||||||
|
} else {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CodedOutputStream::VarintSize64(uint64 value) {
|
||||||
|
if (value < (1ull << 35)) {
|
||||||
|
if (value < (1ull << 7)) {
|
||||||
|
return 1;
|
||||||
|
} else if (value < (1ull << 14)) {
|
||||||
|
return 2;
|
||||||
|
} else if (value < (1ull << 21)) {
|
||||||
|
return 3;
|
||||||
|
} else if (value < (1ull << 28)) {
|
||||||
|
return 4;
|
||||||
|
} else {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (value < (1ull << 42)) {
|
||||||
|
return 6;
|
||||||
|
} else if (value < (1ull << 49)) {
|
||||||
|
return 7;
|
||||||
|
} else if (value < (1ull << 56)) {
|
||||||
|
return 8;
|
||||||
|
} else if (value < (1ull << 63)) {
|
||||||
|
return 9;
|
||||||
|
} else {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace io
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,199 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace io {
|
||||||
|
|
||||||
|
Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter)
|
||||||
|
: variable_delimiter_(variable_delimiter),
|
||||||
|
output_(output),
|
||||||
|
buffer_(NULL),
|
||||||
|
buffer_size_(0),
|
||||||
|
at_start_of_line_(true),
|
||||||
|
failed_(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Printer::~Printer() {
|
||||||
|
// Only BackUp() if we're sure we've successfully called Next() at least once.
|
||||||
|
if (buffer_size_ > 0) {
|
||||||
|
output_->BackUp(buffer_size_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Printer::Print(const map<string, string>& variables, const char* text) {
|
||||||
|
int size = strlen(text);
|
||||||
|
int pos = 0; // The number of bytes we've written so far.
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
if (text[i] == '\n') {
|
||||||
|
// Saw newline. If there is more text, we may need to insert an indent
|
||||||
|
// here. So, write what we have so far, including the '\n'.
|
||||||
|
WriteRaw(text + pos, i - pos + 1);
|
||||||
|
pos = i + 1;
|
||||||
|
|
||||||
|
// Setting this true will cause the next WriteRaw() to insert an indent
|
||||||
|
// first.
|
||||||
|
at_start_of_line_ = true;
|
||||||
|
|
||||||
|
} else if (text[i] == variable_delimiter_) {
|
||||||
|
// Saw the start of a variable name.
|
||||||
|
|
||||||
|
// Write what we have so far.
|
||||||
|
WriteRaw(text + pos, i - pos);
|
||||||
|
pos = i + 1;
|
||||||
|
|
||||||
|
// Find closing delimiter.
|
||||||
|
const char* end = strchr(text + pos, variable_delimiter_);
|
||||||
|
if (end == NULL) {
|
||||||
|
GOOGLE_LOG(DFATAL) << " Unclosed variable name.";
|
||||||
|
end = text + pos;
|
||||||
|
}
|
||||||
|
int endpos = end - text;
|
||||||
|
|
||||||
|
string varname(text + pos, endpos - pos);
|
||||||
|
if (varname.empty()) {
|
||||||
|
// Two delimiters in a row reduce to a literal delimiter character.
|
||||||
|
WriteRaw(&variable_delimiter_, 1);
|
||||||
|
} else {
|
||||||
|
// Replace with the variable's value.
|
||||||
|
map<string, string>::const_iterator iter = variables.find(varname);
|
||||||
|
if (iter == variables.end()) {
|
||||||
|
GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
|
||||||
|
} else {
|
||||||
|
WriteRaw(iter->second.data(), iter->second.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advance past this variable.
|
||||||
|
i = endpos;
|
||||||
|
pos = endpos + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the rest.
|
||||||
|
WriteRaw(text + pos, size - pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Printer::Print(const char* text) {
|
||||||
|
static map<string, string> empty;
|
||||||
|
Print(empty, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Printer::Print(const char* text,
|
||||||
|
const char* variable, const string& value) {
|
||||||
|
map<string, string> vars;
|
||||||
|
vars[variable] = value;
|
||||||
|
Print(vars, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Printer::Print(const char* text,
|
||||||
|
const char* variable1, const string& value1,
|
||||||
|
const char* variable2, const string& value2) {
|
||||||
|
map<string, string> vars;
|
||||||
|
vars[variable1] = value1;
|
||||||
|
vars[variable2] = value2;
|
||||||
|
Print(vars, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Printer::Print(const char* text,
|
||||||
|
const char* variable1, const string& value1,
|
||||||
|
const char* variable2, const string& value2,
|
||||||
|
const char* variable3, const string& value3) {
|
||||||
|
map<string, string> vars;
|
||||||
|
vars[variable1] = value1;
|
||||||
|
vars[variable2] = value2;
|
||||||
|
vars[variable3] = value3;
|
||||||
|
Print(vars, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Printer::Indent() {
|
||||||
|
indent_ += " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Printer::Outdent() {
|
||||||
|
if (indent_.empty()) {
|
||||||
|
GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
indent_.resize(indent_.size() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Printer::PrintRaw(const string& data) {
|
||||||
|
WriteRaw(data.data(), data.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Printer::PrintRaw(const char* data) {
|
||||||
|
if (failed_) return;
|
||||||
|
WriteRaw(data, strlen(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Printer::WriteRaw(const char* data, int size) {
|
||||||
|
if (failed_) return;
|
||||||
|
if (size == 0) return;
|
||||||
|
|
||||||
|
if (at_start_of_line_) {
|
||||||
|
// Insert an indent.
|
||||||
|
at_start_of_line_ = false;
|
||||||
|
WriteRaw(indent_.data(), indent_.size());
|
||||||
|
if (failed_) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (size > buffer_size_) {
|
||||||
|
// Data exceeds space in the buffer. Copy what we can and request a
|
||||||
|
// new buffer.
|
||||||
|
memcpy(buffer_, data, buffer_size_);
|
||||||
|
data += buffer_size_;
|
||||||
|
size -= buffer_size_;
|
||||||
|
void* void_buffer;
|
||||||
|
failed_ = !output_->Next(&void_buffer, &buffer_size_);
|
||||||
|
if (failed_) return;
|
||||||
|
buffer_ = reinterpret_cast<char*>(void_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buffer is big enough to receive the data; copy it.
|
||||||
|
memcpy(buffer_, data, size);
|
||||||
|
buffer_ += size;
|
||||||
|
buffer_size_ -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace io
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,136 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
//
|
||||||
|
// 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,694 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
//
|
||||||
|
// Here we have a hand-written lexer. At first you might ask yourself,
|
||||||
|
// "Hand-written text processing? Is Kenton crazy?!" Well, first of all,
|
||||||
|
// yes I am crazy, but that's beside the point. There are actually reasons
|
||||||
|
// why I ended up writing this this way.
|
||||||
|
//
|
||||||
|
// The traditional approach to lexing is to use lex to generate a lexer for
|
||||||
|
// you. Unfortunately, lex's output is ridiculously ugly and difficult to
|
||||||
|
// integrate cleanly with C++ code, especially abstract code or code meant
|
||||||
|
// as a library. Better parser-generators exist but would add dependencies
|
||||||
|
// which most users won't already have, which we'd like to avoid. (GNU flex
|
||||||
|
// has a C++ output option, but it's still ridiculously ugly, non-abstract,
|
||||||
|
// and not library-friendly.)
|
||||||
|
//
|
||||||
|
// The next approach that any good software engineer should look at is to
|
||||||
|
// use regular expressions. And, indeed, I did. I have code which
|
||||||
|
// implements this same class using regular expressions. It's about 200
|
||||||
|
// lines shorter. However:
|
||||||
|
// - Rather than error messages telling you "This string has an invalid
|
||||||
|
// escape sequence at line 5, column 45", you get error messages like
|
||||||
|
// "Parse error on line 5". Giving more precise errors requires adding
|
||||||
|
// a lot of code that ends up basically as complex as the hand-coded
|
||||||
|
// version anyway.
|
||||||
|
// - The regular expression to match a string literal looks like this:
|
||||||
|
// kString = new RE("(\"([^\"\\\\]|" // non-escaped
|
||||||
|
// "\\\\[abfnrtv?\"'\\\\0-7]|" // normal escape
|
||||||
|
// "\\\\x[0-9a-fA-F])*\"|" // hex escape
|
||||||
|
// "\'([^\'\\\\]|" // Also support single-quotes.
|
||||||
|
// "\\\\[abfnrtv?\"'\\\\0-7]|"
|
||||||
|
// "\\\\x[0-9a-fA-F])*\')");
|
||||||
|
// Verifying the correctness of this line noise is actually harder than
|
||||||
|
// verifying the correctness of ConsumeString(), defined below. I'm not
|
||||||
|
// even confident that the above is correct, after staring at it for some
|
||||||
|
// time.
|
||||||
|
// - PCRE is fast, but there's still more overhead involved than the code
|
||||||
|
// below.
|
||||||
|
// - Sadly, regular expressions are not part of the C standard library, so
|
||||||
|
// using them would require depending on some other library. For the
|
||||||
|
// open source release, this could be really annoying. Nobody likes
|
||||||
|
// downloading one piece of software just to find that they need to
|
||||||
|
// download something else to make it work, and in all likelihood
|
||||||
|
// people downloading Protocol Buffers will already be doing so just
|
||||||
|
// to make something else work. We could include a copy of PCRE with
|
||||||
|
// our code, but that obligates us to keep it up-to-date and just seems
|
||||||
|
// like a big waste just to save 200 lines of code.
|
||||||
|
//
|
||||||
|
// On a similar but unrelated note, I'm even scared to use ctype.h.
|
||||||
|
// Apparently functions like isalpha() are locale-dependent. So, if we used
|
||||||
|
// that, then if this code is being called from some program that doesn't
|
||||||
|
// have its locale set to "C", it would behave strangely. We can't just set
|
||||||
|
// the locale to "C" ourselves since we might break the calling program that
|
||||||
|
// way, particularly if it is multi-threaded. WTF? Someone please let me
|
||||||
|
// (Kenton) know if I'm missing something here...
|
||||||
|
//
|
||||||
|
// I'd love to hear about other alternatives, though, as this code isn't
|
||||||
|
// exactly pretty.
|
||||||
|
|
||||||
|
#include <google/protobuf/io/tokenizer.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace io {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// As mentioned above, I don't trust ctype.h due to the presence of "locales".
|
||||||
|
// So, I have written replacement functions here. Someone please smack me if
|
||||||
|
// this is a bad idea or if there is some way around this.
|
||||||
|
//
|
||||||
|
// These "character classes" are designed to be used in template methods.
|
||||||
|
// For instance, Tokenizer::ConsumeZeroOrMore<Whitespace>() will eat
|
||||||
|
// whitespace.
|
||||||
|
|
||||||
|
// Note: No class is allowed to contain '\0', since this is used to mark end-
|
||||||
|
// of-input and is handled specially.
|
||||||
|
|
||||||
|
#define CHARACTER_CLASS(NAME, EXPRESSION) \
|
||||||
|
class NAME { \
|
||||||
|
public: \
|
||||||
|
static inline bool InClass(char c) { \
|
||||||
|
return EXPRESSION; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' ||
|
||||||
|
c == '\r' || c == '\v' || c == '\f');
|
||||||
|
|
||||||
|
CHARACTER_CLASS(Unprintable, c < ' ' && c > '\0');
|
||||||
|
|
||||||
|
CHARACTER_CLASS(Digit, '0' <= c && c <= '9');
|
||||||
|
CHARACTER_CLASS(OctalDigit, '0' <= c && c <= '7');
|
||||||
|
CHARACTER_CLASS(HexDigit, ('0' <= c && c <= '9') ||
|
||||||
|
('a' <= c && c <= 'f') ||
|
||||||
|
('A' <= c && c <= 'F'));
|
||||||
|
|
||||||
|
CHARACTER_CLASS(Letter, ('a' <= c && c <= 'z') ||
|
||||||
|
('A' <= c && c <= 'Z') ||
|
||||||
|
(c == '_'));
|
||||||
|
|
||||||
|
CHARACTER_CLASS(Alphanumeric, ('a' <= c && c <= 'z') ||
|
||||||
|
('A' <= c && c <= 'Z') ||
|
||||||
|
('0' <= c && c <= '9') ||
|
||||||
|
(c == '_'));
|
||||||
|
|
||||||
|
CHARACTER_CLASS(Escape, c == 'a' || c == 'b' || c == 'f' || c == 'n' ||
|
||||||
|
c == 'r' || c == 't' || c == 'v' || c == '\\' ||
|
||||||
|
c == '?' || c == '\'' || c == '\"');
|
||||||
|
|
||||||
|
#undef CHARACTER_CLASS
|
||||||
|
|
||||||
|
// Given a char, interpret it as a numeric digit and return its value.
|
||||||
|
// This supports any number base up to 36.
|
||||||
|
inline int DigitValue(char digit) {
|
||||||
|
if ('0' <= digit && digit <= '9') return digit - '0';
|
||||||
|
if ('a' <= digit && digit <= 'z') return digit - 'a' + 10;
|
||||||
|
if ('A' <= digit && digit <= 'Z') return digit - 'A' + 10;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inline because it's only used in one place.
|
||||||
|
inline char TranslateEscape(char c) {
|
||||||
|
switch (c) {
|
||||||
|
case 'a': return '\a';
|
||||||
|
case 'b': return '\b';
|
||||||
|
case 'f': return '\f';
|
||||||
|
case 'n': return '\n';
|
||||||
|
case 'r': return '\r';
|
||||||
|
case 't': return '\t';
|
||||||
|
case 'v': return '\v';
|
||||||
|
case '\\': return '\\';
|
||||||
|
case '?': return '\?'; // Trigraphs = :(
|
||||||
|
case '\'': return '\'';
|
||||||
|
case '"': return '\"';
|
||||||
|
|
||||||
|
// We expect escape sequences to have been validated separately.
|
||||||
|
default: return '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
ErrorCollector::~ErrorCollector() {}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
Tokenizer::Tokenizer(ZeroCopyInputStream* input,
|
||||||
|
ErrorCollector* error_collector)
|
||||||
|
: input_(input),
|
||||||
|
error_collector_(error_collector),
|
||||||
|
buffer_(NULL),
|
||||||
|
buffer_size_(0),
|
||||||
|
buffer_pos_(0),
|
||||||
|
read_error_(false),
|
||||||
|
line_(0),
|
||||||
|
column_(0),
|
||||||
|
token_start_(-1),
|
||||||
|
allow_f_after_float_(false),
|
||||||
|
comment_style_(CPP_COMMENT_STYLE) {
|
||||||
|
|
||||||
|
current_.line = 0;
|
||||||
|
current_.column = 0;
|
||||||
|
current_.end_column = 0;
|
||||||
|
current_.type = TYPE_START;
|
||||||
|
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
Tokenizer::~Tokenizer() {
|
||||||
|
// If we had any buffer left unread, return it to the underlying stream
|
||||||
|
// so that someone else can read it.
|
||||||
|
if (buffer_size_ > buffer_pos_) {
|
||||||
|
input_->BackUp(buffer_size_ - buffer_pos_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Internal helpers.
|
||||||
|
|
||||||
|
void Tokenizer::NextChar() {
|
||||||
|
// Update our line and column counters based on the character being
|
||||||
|
// consumed.
|
||||||
|
if (current_char_ == '\n') {
|
||||||
|
++line_;
|
||||||
|
column_ = 0;
|
||||||
|
} else if (current_char_ == '\t') {
|
||||||
|
column_ += kTabWidth - column_ % kTabWidth;
|
||||||
|
} else {
|
||||||
|
++column_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advance to the next character.
|
||||||
|
++buffer_pos_;
|
||||||
|
if (buffer_pos_ < buffer_size_) {
|
||||||
|
current_char_ = buffer_[buffer_pos_];
|
||||||
|
} else {
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tokenizer::Refresh() {
|
||||||
|
if (read_error_) {
|
||||||
|
current_char_ = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're in a token, append the rest of the buffer to it.
|
||||||
|
if (token_start_ >= 0 && token_start_ < buffer_size_) {
|
||||||
|
current_.text.append(buffer_ + token_start_, buffer_size_ - token_start_);
|
||||||
|
token_start_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* data = NULL;
|
||||||
|
buffer_ = NULL;
|
||||||
|
buffer_pos_ = 0;
|
||||||
|
do {
|
||||||
|
if (!input_->Next(&data, &buffer_size_)) {
|
||||||
|
// end of stream (or read error)
|
||||||
|
buffer_size_ = 0;
|
||||||
|
read_error_ = true;
|
||||||
|
current_char_ = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (buffer_size_ == 0);
|
||||||
|
|
||||||
|
buffer_ = static_cast<const char*>(data);
|
||||||
|
|
||||||
|
current_char_ = buffer_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Tokenizer::StartToken() {
|
||||||
|
token_start_ = buffer_pos_;
|
||||||
|
current_.type = TYPE_START; // Just for the sake of initializing it.
|
||||||
|
current_.text.clear();
|
||||||
|
current_.line = line_;
|
||||||
|
current_.column = column_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Tokenizer::EndToken() {
|
||||||
|
// Note: The if() is necessary because some STL implementations crash when
|
||||||
|
// you call string::append(NULL, 0), presumably because they are trying to
|
||||||
|
// be helpful by detecting the NULL pointer, even though there's nothing
|
||||||
|
// wrong with reading zero bytes from NULL.
|
||||||
|
if (buffer_pos_ != token_start_) {
|
||||||
|
current_.text.append(buffer_ + token_start_, buffer_pos_ - token_start_);
|
||||||
|
}
|
||||||
|
token_start_ = -1;
|
||||||
|
current_.end_column = column_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Helper methods that consume characters.
|
||||||
|
|
||||||
|
template<typename CharacterClass>
|
||||||
|
inline bool Tokenizer::LookingAt() {
|
||||||
|
return CharacterClass::InClass(current_char_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename CharacterClass>
|
||||||
|
inline bool Tokenizer::TryConsumeOne() {
|
||||||
|
if (CharacterClass::InClass(current_char_)) {
|
||||||
|
NextChar();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Tokenizer::TryConsume(char c) {
|
||||||
|
if (current_char_ == c) {
|
||||||
|
NextChar();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename CharacterClass>
|
||||||
|
inline void Tokenizer::ConsumeZeroOrMore() {
|
||||||
|
while (CharacterClass::InClass(current_char_)) {
|
||||||
|
NextChar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename CharacterClass>
|
||||||
|
inline void Tokenizer::ConsumeOneOrMore(const char* error) {
|
||||||
|
if (!CharacterClass::InClass(current_char_)) {
|
||||||
|
AddError(error);
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
NextChar();
|
||||||
|
} while (CharacterClass::InClass(current_char_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Methods that read whole patterns matching certain kinds of tokens
|
||||||
|
// or comments.
|
||||||
|
|
||||||
|
void Tokenizer::ConsumeString(char delimiter) {
|
||||||
|
while (true) {
|
||||||
|
switch (current_char_) {
|
||||||
|
case '\0':
|
||||||
|
case '\n': {
|
||||||
|
AddError("String literals cannot cross line boundaries.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '\\': {
|
||||||
|
// An escape sequence.
|
||||||
|
NextChar();
|
||||||
|
if (TryConsumeOne<Escape>()) {
|
||||||
|
// Valid escape sequence.
|
||||||
|
} else if (TryConsumeOne<OctalDigit>()) {
|
||||||
|
// Possibly followed by two more octal digits, but these will
|
||||||
|
// just be consumed by the main loop anyway so we don't need
|
||||||
|
// to do so explicitly here.
|
||||||
|
} else if (TryConsume('x') || TryConsume('X')) {
|
||||||
|
if (!TryConsumeOne<HexDigit>()) {
|
||||||
|
AddError("Expected hex digits for escape sequence.");
|
||||||
|
}
|
||||||
|
// Possibly followed by another hex digit, but again we don't care.
|
||||||
|
} else {
|
||||||
|
AddError("Invalid escape sequence in string literal.");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
if (current_char_ == delimiter) {
|
||||||
|
NextChar();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NextChar();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tokenizer::TokenType Tokenizer::ConsumeNumber(bool started_with_zero,
|
||||||
|
bool started_with_dot) {
|
||||||
|
bool is_float = false;
|
||||||
|
|
||||||
|
if (started_with_zero && (TryConsume('x') || TryConsume('X'))) {
|
||||||
|
// A hex number (started with "0x").
|
||||||
|
ConsumeOneOrMore<HexDigit>("\"0x\" must be followed by hex digits.");
|
||||||
|
|
||||||
|
} else if (started_with_zero && LookingAt<Digit>()) {
|
||||||
|
// An octal number (had a leading zero).
|
||||||
|
ConsumeZeroOrMore<OctalDigit>();
|
||||||
|
if (LookingAt<Digit>()) {
|
||||||
|
AddError("Numbers starting with leading zero must be in octal.");
|
||||||
|
ConsumeZeroOrMore<Digit>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// A decimal number.
|
||||||
|
if (started_with_dot) {
|
||||||
|
is_float = true;
|
||||||
|
ConsumeZeroOrMore<Digit>();
|
||||||
|
} else {
|
||||||
|
ConsumeZeroOrMore<Digit>();
|
||||||
|
|
||||||
|
if (TryConsume('.')) {
|
||||||
|
is_float = true;
|
||||||
|
ConsumeZeroOrMore<Digit>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryConsume('e') || TryConsume('E')) {
|
||||||
|
is_float = true;
|
||||||
|
TryConsume('-') || TryConsume('+');
|
||||||
|
ConsumeOneOrMore<Digit>("\"e\" must be followed by exponent.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allow_f_after_float_ && (TryConsume('f') || TryConsume('F'))) {
|
||||||
|
is_float = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LookingAt<Letter>()) {
|
||||||
|
AddError("Need space between number and identifier.");
|
||||||
|
} else if (current_char_ == '.') {
|
||||||
|
if (is_float) {
|
||||||
|
AddError(
|
||||||
|
"Already saw decimal point or exponent; can't have another one.");
|
||||||
|
} else {
|
||||||
|
AddError("Hex and octal numbers must be integers.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_float ? TYPE_FLOAT : TYPE_INTEGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tokenizer::ConsumeLineComment() {
|
||||||
|
while (current_char_ != '\0' && current_char_ != '\n') {
|
||||||
|
NextChar();
|
||||||
|
}
|
||||||
|
TryConsume('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tokenizer::ConsumeBlockComment() {
|
||||||
|
int start_line = line_;
|
||||||
|
int start_column = column_ - 2;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
while (current_char_ != '\0' &&
|
||||||
|
current_char_ != '*' &&
|
||||||
|
current_char_ != '/') {
|
||||||
|
NextChar();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryConsume('*') && TryConsume('/')) {
|
||||||
|
// End of comment.
|
||||||
|
break;
|
||||||
|
} else if (TryConsume('/') && current_char_ == '*') {
|
||||||
|
// Note: We didn't consume the '*' because if there is a '/' after it
|
||||||
|
// we want to interpret that as the end of the comment.
|
||||||
|
AddError(
|
||||||
|
"\"/*\" inside block comment. Block comments cannot be nested.");
|
||||||
|
} else if (current_char_ == '\0') {
|
||||||
|
AddError("End-of-file inside block comment.");
|
||||||
|
error_collector_->AddError(
|
||||||
|
start_line, start_column, " Comment started here.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool Tokenizer::Next() {
|
||||||
|
previous_ = current_;
|
||||||
|
|
||||||
|
// Did we skip any characters after the last token?
|
||||||
|
bool skipped_stuff = false;
|
||||||
|
|
||||||
|
while (!read_error_) {
|
||||||
|
if (TryConsumeOne<Whitespace>()) {
|
||||||
|
ConsumeZeroOrMore<Whitespace>();
|
||||||
|
|
||||||
|
} else if (comment_style_ == CPP_COMMENT_STYLE && TryConsume('/')) {
|
||||||
|
// Starting a comment?
|
||||||
|
if (TryConsume('/')) {
|
||||||
|
ConsumeLineComment();
|
||||||
|
} else if (TryConsume('*')) {
|
||||||
|
ConsumeBlockComment();
|
||||||
|
} else {
|
||||||
|
// Oops, it was just a slash. Return it.
|
||||||
|
current_.type = TYPE_SYMBOL;
|
||||||
|
current_.text = "/";
|
||||||
|
current_.line = line_;
|
||||||
|
current_.column = column_ - 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (comment_style_ == SH_COMMENT_STYLE && TryConsume('#')) {
|
||||||
|
ConsumeLineComment();
|
||||||
|
|
||||||
|
} else if (LookingAt<Unprintable>() || current_char_ == '\0') {
|
||||||
|
AddError("Invalid control characters encountered in text.");
|
||||||
|
NextChar();
|
||||||
|
// Skip more unprintable characters, too. But, remember that '\0' is
|
||||||
|
// also what current_char_ is set to after EOF / read error. We have
|
||||||
|
// to be careful not to go into an infinite loop of trying to consume
|
||||||
|
// it, so make sure to check read_error_ explicitly before consuming
|
||||||
|
// '\0'.
|
||||||
|
while (TryConsumeOne<Unprintable>() ||
|
||||||
|
(!read_error_ && TryConsume('\0'))) {
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Reading some sort of token.
|
||||||
|
StartToken();
|
||||||
|
|
||||||
|
if (TryConsumeOne<Letter>()) {
|
||||||
|
ConsumeZeroOrMore<Alphanumeric>();
|
||||||
|
current_.type = TYPE_IDENTIFIER;
|
||||||
|
} else if (TryConsume('0')) {
|
||||||
|
current_.type = ConsumeNumber(true, false);
|
||||||
|
} else if (TryConsume('.')) {
|
||||||
|
// This could be the beginning of a floating-point number, or it could
|
||||||
|
// just be a '.' symbol.
|
||||||
|
|
||||||
|
if (TryConsumeOne<Digit>()) {
|
||||||
|
// It's a floating-point number.
|
||||||
|
if (previous_.type == TYPE_IDENTIFIER && !skipped_stuff) {
|
||||||
|
// We don't accept syntax like "blah.123".
|
||||||
|
error_collector_->AddError(line_, column_ - 2,
|
||||||
|
"Need space between identifier and decimal point.");
|
||||||
|
}
|
||||||
|
current_.type = ConsumeNumber(false, true);
|
||||||
|
} else {
|
||||||
|
current_.type = TYPE_SYMBOL;
|
||||||
|
}
|
||||||
|
} else if (TryConsumeOne<Digit>()) {
|
||||||
|
current_.type = ConsumeNumber(false, false);
|
||||||
|
} else if (TryConsume('\"')) {
|
||||||
|
ConsumeString('\"');
|
||||||
|
current_.type = TYPE_STRING;
|
||||||
|
} else if (TryConsume('\'')) {
|
||||||
|
ConsumeString('\'');
|
||||||
|
current_.type = TYPE_STRING;
|
||||||
|
} else {
|
||||||
|
NextChar();
|
||||||
|
current_.type = TYPE_SYMBOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EndToken();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
skipped_stuff = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
||||||
|
current_.type = TYPE_END;
|
||||||
|
current_.text.clear();
|
||||||
|
current_.line = line_;
|
||||||
|
current_.column = column_;
|
||||||
|
current_.end_column = column_;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Token-parsing helpers. Remember that these don't need to report
|
||||||
|
// errors since any errors should already have been reported while
|
||||||
|
// tokenizing. Also, these can assume that whatever text they
|
||||||
|
// are given is text that the tokenizer actually parsed as a token
|
||||||
|
// of the given type.
|
||||||
|
|
||||||
|
bool Tokenizer::ParseInteger(const string& text, uint64 max_value,
|
||||||
|
uint64* output) {
|
||||||
|
// Sadly, we can't just use strtoul() since it is only 32-bit and strtoull()
|
||||||
|
// is non-standard. I hate the C standard library. :(
|
||||||
|
|
||||||
|
// return strtoull(text.c_str(), NULL, 0);
|
||||||
|
|
||||||
|
const char* ptr = text.c_str();
|
||||||
|
int base = 10;
|
||||||
|
if (ptr[0] == '0') {
|
||||||
|
if (ptr[1] == 'x' || ptr[1] == 'X') {
|
||||||
|
// This is hex.
|
||||||
|
base = 16;
|
||||||
|
ptr += 2;
|
||||||
|
} else {
|
||||||
|
// This is octal.
|
||||||
|
base = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 result = 0;
|
||||||
|
for (; *ptr != '\0'; ptr++) {
|
||||||
|
int digit = DigitValue(*ptr);
|
||||||
|
GOOGLE_LOG_IF(DFATAL, digit < 0 || digit >= base)
|
||||||
|
<< " Tokenizer::ParseInteger() passed text that could not have been"
|
||||||
|
" tokenized as an integer: " << CEscape(text);
|
||||||
|
if (digit > max_value || result > (max_value - digit) / base) {
|
||||||
|
// Overflow.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
result = result * base + digit;
|
||||||
|
}
|
||||||
|
|
||||||
|
*output = result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Tokenizer::ParseFloat(const string& text) {
|
||||||
|
const char* start = text.c_str();
|
||||||
|
char* end;
|
||||||
|
double result = NoLocaleStrtod(start, &end);
|
||||||
|
|
||||||
|
// "1e" is not a valid float, but if the tokenizer reads it, it will
|
||||||
|
// report an error but still return it as a valid token. We need to
|
||||||
|
// accept anything the tokenizer could possibly return, error or not.
|
||||||
|
if (*end == 'e' || *end == 'E') {
|
||||||
|
++end;
|
||||||
|
if (*end == '-' || *end == '+') ++end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Tokenizer had allow_f_after_float_ enabled, the float may be
|
||||||
|
// suffixed with the letter 'f'.
|
||||||
|
if (*end == 'f' || *end == 'F') {
|
||||||
|
++end;
|
||||||
|
}
|
||||||
|
|
||||||
|
GOOGLE_LOG_IF(DFATAL, end - start != text.size() || *start == '-')
|
||||||
|
<< " Tokenizer::ParseFloat() passed text that could not have been"
|
||||||
|
" tokenized as a float: " << CEscape(text);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tokenizer::ParseStringAppend(const string& text, string* output) {
|
||||||
|
// Reminder: text[0] is always the quote character. (If text is
|
||||||
|
// empty, it's invalid, so we'll just return.)
|
||||||
|
if (text.empty()) {
|
||||||
|
GOOGLE_LOG(DFATAL)
|
||||||
|
<< " Tokenizer::ParseStringAppend() passed text that could not"
|
||||||
|
" have been tokenized as a string: " << CEscape(text);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->reserve(output->size() + text.size());
|
||||||
|
|
||||||
|
// Loop through the string copying characters to "output" and
|
||||||
|
// interpreting escape sequences. Note that any invalid escape
|
||||||
|
// sequences or other errors were already reported while tokenizing.
|
||||||
|
// In this case we do not need to produce valid results.
|
||||||
|
for (const char* ptr = text.c_str() + 1; *ptr != '\0'; ptr++) {
|
||||||
|
if (*ptr == '\\' && ptr[1] != '\0') {
|
||||||
|
// An escape sequence.
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
if (OctalDigit::InClass(*ptr)) {
|
||||||
|
// An octal escape. May one, two, or three digits.
|
||||||
|
int code = DigitValue(*ptr);
|
||||||
|
if (OctalDigit::InClass(ptr[1])) {
|
||||||
|
++ptr;
|
||||||
|
code = code * 8 + DigitValue(*ptr);
|
||||||
|
}
|
||||||
|
if (OctalDigit::InClass(ptr[1])) {
|
||||||
|
++ptr;
|
||||||
|
code = code * 8 + DigitValue(*ptr);
|
||||||
|
}
|
||||||
|
output->push_back(static_cast<char>(code));
|
||||||
|
|
||||||
|
} else if (*ptr == 'x') {
|
||||||
|
// A hex escape. May zero, one, or two digits. (The zero case
|
||||||
|
// will have been caught as an error earlier.)
|
||||||
|
int code = 0;
|
||||||
|
if (HexDigit::InClass(ptr[1])) {
|
||||||
|
++ptr;
|
||||||
|
code = DigitValue(*ptr);
|
||||||
|
}
|
||||||
|
if (HexDigit::InClass(ptr[1])) {
|
||||||
|
++ptr;
|
||||||
|
code = code * 16 + DigitValue(*ptr);
|
||||||
|
}
|
||||||
|
output->push_back(static_cast<char>(code));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Some other escape code.
|
||||||
|
output->push_back(TranslateEscape(*ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (*ptr == text[0]) {
|
||||||
|
// Ignore quote matching the starting quote.
|
||||||
|
} else {
|
||||||
|
output->push_back(*ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace io
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue