Add protobuf library to project

This commit is contained in:
Amos 2022-02-10 00:19:49 +01:00
parent ad65ff1f63
commit f7df14d153
587 changed files with 296199 additions and 0 deletions

View File

@ -11,6 +11,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dedicated", "r5dev\dedicate
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netconsole", "r5dev\netconsole.vcxproj", "{9579B31F-CE24-4852-A941-CD1AD71E2248}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "protobuf", "r5dev\protobuf.vcxproj", "{B273A875-6618-49FE-8CA4-0B693BA264D5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -51,6 +53,14 @@ Global
{9579B31F-CE24-4852-A941-CD1AD71E2248}.Release|x64.Build.0 = Release|x64
{9579B31F-CE24-4852-A941-CD1AD71E2248}.Release|x86.ActiveCfg = Release|Win32
{9579B31F-CE24-4852-A941-CD1AD71E2248}.Release|x86.Build.0 = Release|Win32
{B273A875-6618-49FE-8CA4-0B693BA264D5}.Debug|x64.ActiveCfg = Debug|x64
{B273A875-6618-49FE-8CA4-0B693BA264D5}.Debug|x64.Build.0 = Debug|x64
{B273A875-6618-49FE-8CA4-0B693BA264D5}.Debug|x86.ActiveCfg = Debug|Win32
{B273A875-6618-49FE-8CA4-0B693BA264D5}.Debug|x86.Build.0 = Debug|Win32
{B273A875-6618-49FE-8CA4-0B693BA264D5}.Release|x64.ActiveCfg = Release|x64
{B273A875-6618-49FE-8CA4-0B693BA264D5}.Release|x64.Build.0 = Release|x64
{B273A875-6618-49FE-8CA4-0B693BA264D5}.Release|x86.ActiveCfg = Release|Win32
{B273A875-6618-49FE-8CA4-0B693BA264D5}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -0,0 +1,32 @@
Copyright 2008 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Code generated by the Protocol Buffer compiler is owned by the owner
of the input file used when generating it. This code is not
standalone and requires a support library to be linked with it. This
support library is itself covered by the above license.

758
r5dev/protobuf.vcxproj Normal file
View File

@ -0,0 +1,758 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{b273a875-6618-49fe-8ca4-0b693ba264d5}</ProjectGuid>
<RootNamespace>protobuf</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)r5dev\;$(IncludePath);</IncludePath>
<IntDir>$(SolutionDir)build\$(ProjectName)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)r5dev\;$(IncludePath);</IncludePath>
<IntDir>$(SolutionDir)build\$(ProjectName)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)r5dev\;$(IncludePath);</IncludePath>
<IntDir>$(SolutionDir)build\$(ProjectName)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)r5dev\;$(IncludePath);</IncludePath>
<IntDir>$(SolutionDir)build\$(ProjectName)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalOptions>/D _CRT_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalOptions>/D _CRT_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalOptions>/D _CRT_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalOptions>/D _CRT_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="thirdparty\protobuf\any.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\any.pb.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\any_lite.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\api.pb.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\arena.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\arenastring.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\compiler\importer.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\compiler\parser.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\descriptor.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\descriptor.pb.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\descriptor_database.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\duration.pb.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\dynamic_message.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\empty.pb.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\extension_set.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\extension_set_heavy.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\field_mask.pb.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_enum_util.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_bases.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_reflection.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_table_driven.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_table_driven_lite.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_tctable_full.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_tctable_lite.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_util.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\implicit_weak_message.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\inlined_string_field.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\coded_stream.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\gzip_stream.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\io_win32.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\printer.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\strtod.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\tokenizer.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\zero_copy_stream.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\zero_copy_stream_impl.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\zero_copy_stream_impl_lite.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\map.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\map_field.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\message.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\message_lite.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\parse_context.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\reflection_ops.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\repeated_field.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\repeated_ptr_field.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\service.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\source_context.pb.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\struct.pb.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\bytestream.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\common.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\int128.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\status.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\statusor.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\stringpiece.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\stringprintf.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\structurally_valid.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\strutil.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\substitute.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\time.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\text_format.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\timestamp.pb.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\type.pb.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\unknown_field_set.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\delimited_message_util.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\field_comparator.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\field_mask_util.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\datapiece.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\default_value_objectwriter.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\error_listener.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\field_mask_utility.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\json_escaping.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\json_objectwriter.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\json_stream_parser.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\object_writer.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\protostream_objectsource.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\protostream_objectwriter.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\proto_writer.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\type_info.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\utility.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\json_util.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\message_differencer.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\time_util.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\type_resolver_util.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\wire_format.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\wire_format_lite.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\wrappers.pb.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="thirdparty\protobuf\any.h" />
<ClInclude Include="thirdparty\protobuf\any.pb.h" />
<ClInclude Include="thirdparty\protobuf\api.pb.h" />
<ClInclude Include="thirdparty\protobuf\arena.h" />
<ClInclude Include="thirdparty\protobuf\arenastring.h" />
<ClInclude Include="thirdparty\protobuf\compiler\importer.h" />
<ClInclude Include="thirdparty\protobuf\compiler\parser.h" />
<ClInclude Include="thirdparty\protobuf\descriptor.h" />
<ClInclude Include="thirdparty\protobuf\descriptor.pb.h" />
<ClInclude Include="thirdparty\protobuf\descriptor_database.h" />
<ClInclude Include="thirdparty\protobuf\duration.pb.h" />
<ClInclude Include="thirdparty\protobuf\dynamic_message.h" />
<ClInclude Include="thirdparty\protobuf\empty.pb.h" />
<ClInclude Include="thirdparty\protobuf\extension_set.h" />
<ClInclude Include="thirdparty\protobuf\extension_set_inl.h" />
<ClInclude Include="thirdparty\protobuf\field_mask.pb.h" />
<ClInclude Include="thirdparty\protobuf\generated_enum_util.h" />
<ClInclude Include="thirdparty\protobuf\generated_message_bases.h" />
<ClInclude Include="thirdparty\protobuf\generated_message_reflection.h" />
<ClInclude Include="thirdparty\protobuf\generated_message_table_driven.h" />
<ClInclude Include="thirdparty\protobuf\generated_message_table_driven_lite.h" />
<ClInclude Include="thirdparty\protobuf\generated_message_util.h" />
<ClInclude Include="thirdparty\protobuf\implicit_weak_message.h" />
<ClInclude Include="thirdparty\protobuf\inlined_string_field.h" />
<ClInclude Include="thirdparty\protobuf\io\coded_stream.h" />
<ClInclude Include="thirdparty\protobuf\io\gzip_stream.h" />
<ClInclude Include="thirdparty\protobuf\io\io_win32.h" />
<ClInclude Include="thirdparty\protobuf\io\printer.h" />
<ClInclude Include="thirdparty\protobuf\io\strtod.h" />
<ClInclude Include="thirdparty\protobuf\io\tokenizer.h" />
<ClInclude Include="thirdparty\protobuf\io\zero_copy_stream.h" />
<ClInclude Include="thirdparty\protobuf\io\zero_copy_stream_impl.h" />
<ClInclude Include="thirdparty\protobuf\io\zero_copy_stream_impl_lite.h" />
<ClInclude Include="thirdparty\protobuf\map.h" />
<ClInclude Include="thirdparty\protobuf\map_field.h" />
<ClInclude Include="thirdparty\protobuf\message.h" />
<ClInclude Include="thirdparty\protobuf\message_lite.h" />
<ClInclude Include="thirdparty\protobuf\parse_context.h" />
<ClInclude Include="thirdparty\protobuf\reflection_ops.h" />
<ClInclude Include="thirdparty\protobuf\repeated_field.h" />
<ClInclude Include="thirdparty\protobuf\repeated_ptr_field.h" />
<ClInclude Include="thirdparty\protobuf\service.h" />
<ClInclude Include="thirdparty\protobuf\source_context.pb.h" />
<ClInclude Include="thirdparty\protobuf\struct.pb.h" />
<ClInclude Include="thirdparty\protobuf\stubs\bytestream.h" />
<ClInclude Include="thirdparty\protobuf\stubs\common.h" />
<ClInclude Include="thirdparty\protobuf\stubs\int128.h" />
<ClInclude Include="thirdparty\protobuf\stubs\status.h" />
<ClInclude Include="thirdparty\protobuf\stubs\statusor.h" />
<ClInclude Include="thirdparty\protobuf\stubs\stringpiece.h" />
<ClInclude Include="thirdparty\protobuf\stubs\stringprintf.h" />
<ClInclude Include="thirdparty\protobuf\stubs\strutil.h" />
<ClInclude Include="thirdparty\protobuf\stubs\substitute.h" />
<ClInclude Include="thirdparty\protobuf\stubs\time.h" />
<ClInclude Include="thirdparty\protobuf\text_format.h" />
<ClInclude Include="thirdparty\protobuf\timestamp.pb.h" />
<ClInclude Include="thirdparty\protobuf\type.pb.h" />
<ClInclude Include="thirdparty\protobuf\unknown_field_set.h" />
<ClInclude Include="thirdparty\protobuf\util\delimited_message_util.h" />
<ClInclude Include="thirdparty\protobuf\util\field_comparator.h" />
<ClInclude Include="thirdparty\protobuf\util\field_mask_util.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\datapiece.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\default_value_objectwriter.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\error_listener.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\field_mask_utility.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\json_escaping.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\json_objectwriter.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\json_stream_parser.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\object_writer.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\protostream_objectsource.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\protostream_objectwriter.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\proto_writer.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\type_info.h" />
<ClInclude Include="thirdparty\protobuf\util\internal\utility.h" />
<ClInclude Include="thirdparty\protobuf\util\json_util.h" />
<ClInclude Include="thirdparty\protobuf\util\message_differencer.h" />
<ClInclude Include="thirdparty\protobuf\util\time_util.h" />
<ClInclude Include="thirdparty\protobuf\util\type_resolver_util.h" />
<ClInclude Include="thirdparty\protobuf\wire_format.h" />
<ClInclude Include="thirdparty\protobuf\wire_format_lite.h" />
<ClInclude Include="thirdparty\protobuf\wrappers.pb.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="thirdparty\protobuf\version.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,546 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="thirdparty\protobuf\compiler\importer.cc">
<Filter>compiler</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\compiler\parser.cc">
<Filter>compiler</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\bytestream.cc">
<Filter>stubs</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\common.cc">
<Filter>stubs</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\int128.cc">
<Filter>stubs</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\status.cc">
<Filter>stubs</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\statusor.cc">
<Filter>stubs</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\stringpiece.cc">
<Filter>stubs</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\stringprintf.cc">
<Filter>stubs</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\structurally_valid.cc">
<Filter>stubs</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\strutil.cc">
<Filter>stubs</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\substitute.cc">
<Filter>stubs</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\stubs\time.cc">
<Filter>stubs</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\coded_stream.cc">
<Filter>io</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\gzip_stream.cc">
<Filter>io</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\io_win32.cc">
<Filter>io</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\printer.cc">
<Filter>io</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\strtod.cc">
<Filter>io</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\tokenizer.cc">
<Filter>io</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\zero_copy_stream_impl.cc">
<Filter>io</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\zero_copy_stream_impl_lite.cc">
<Filter>io</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\io\zero_copy_stream.cc">
<Filter>io</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\delimited_message_util.cc">
<Filter>util</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\field_comparator.cc">
<Filter>util</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\field_mask_util.cc">
<Filter>util</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\json_util.cc">
<Filter>util</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\message_differencer.cc">
<Filter>util</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\time_util.cc">
<Filter>util</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\type_resolver_util.cc">
<Filter>util</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\datapiece.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\default_value_objectwriter.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\error_listener.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\field_mask_utility.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\json_objectwriter.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\json_stream_parser.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\json_escaping.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\object_writer.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\proto_writer.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\protostream_objectsource.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\protostream_objectwriter.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\type_info.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\util\internal\utility.cc">
<Filter>util\internal</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\any.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\any.pb.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\any_lite.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\api.pb.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\arena.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\arenastring.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\descriptor.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\descriptor.pb.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\descriptor_database.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\duration.pb.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\dynamic_message.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\empty.pb.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\extension_set.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\extension_set_heavy.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\field_mask.pb.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_enum_util.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_bases.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_reflection.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_table_driven.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_table_driven_lite.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_tctable_full.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_tctable_lite.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\generated_message_util.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\implicit_weak_message.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\inlined_string_field.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\map.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\map_field.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\message.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\message_lite.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\parse_context.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\reflection_ops.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\repeated_field.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\repeated_ptr_field.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\service.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\source_context.pb.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\struct.pb.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\text_format.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\timestamp.pb.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\type.pb.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\unknown_field_set.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\wire_format.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\wire_format_lite.cc">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="thirdparty\protobuf\wrappers.pb.cc">
<Filter>source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="compiler">
<UniqueIdentifier>{9938338d-9b4b-4464-97e5-a47636d0b1a4}</UniqueIdentifier>
</Filter>
<Filter Include="compiler\include">
<UniqueIdentifier>{8ce9e500-f5b5-4d81-aafb-becab42d0174}</UniqueIdentifier>
</Filter>
<Filter Include="stubs">
<UniqueIdentifier>{d60db004-45fa-4ae3-b74d-47b327b69c2e}</UniqueIdentifier>
</Filter>
<Filter Include="stubs\include">
<UniqueIdentifier>{87c48269-0f18-42b5-b7be-b0ccb26a5f76}</UniqueIdentifier>
</Filter>
<Filter Include="include">
<UniqueIdentifier>{b464f51d-733d-4b4e-8441-b6cabdecd127}</UniqueIdentifier>
</Filter>
<Filter Include="io">
<UniqueIdentifier>{d80f3bd1-5ff7-4d05-a301-b391f6396dea}</UniqueIdentifier>
</Filter>
<Filter Include="io\include">
<UniqueIdentifier>{1f4012c2-e2e2-48f9-b2f3-2ffe80c9a912}</UniqueIdentifier>
</Filter>
<Filter Include="util">
<UniqueIdentifier>{e42972f8-3b4a-4e5f-8bf5-cc88ae71b499}</UniqueIdentifier>
</Filter>
<Filter Include="util\internal">
<UniqueIdentifier>{4cd49ba1-876f-42de-b9e1-fccab9db185e}</UniqueIdentifier>
</Filter>
<Filter Include="util\internal\include">
<UniqueIdentifier>{01b23346-904d-4495-b48c-e04281bfda22}</UniqueIdentifier>
</Filter>
<Filter Include="util\include">
<UniqueIdentifier>{8647c75c-0fa4-49fc-a30c-193a45680c43}</UniqueIdentifier>
</Filter>
<Filter Include="source">
<UniqueIdentifier>{23955e3f-a0de-4045-952a-188b5c12144e}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="thirdparty\protobuf\compiler\importer.h">
<Filter>compiler\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\compiler\parser.h">
<Filter>compiler\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\stubs\bytestream.h">
<Filter>stubs\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\stubs\common.h">
<Filter>stubs\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\stubs\int128.h">
<Filter>stubs\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\stubs\status.h">
<Filter>stubs\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\stubs\statusor.h">
<Filter>stubs\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\stubs\stringpiece.h">
<Filter>stubs\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\stubs\stringprintf.h">
<Filter>stubs\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\stubs\strutil.h">
<Filter>stubs\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\stubs\substitute.h">
<Filter>stubs\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\stubs\time.h">
<Filter>stubs\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\any.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\any.pb.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\api.pb.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\arena.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\arenastring.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\descriptor.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\descriptor.pb.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\descriptor_database.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\duration.pb.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\dynamic_message.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\empty.pb.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\extension_set.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\extension_set_inl.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\field_mask.pb.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\generated_enum_util.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\generated_message_bases.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\generated_message_reflection.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\generated_message_table_driven.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\generated_message_table_driven_lite.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\generated_message_util.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\implicit_weak_message.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\inlined_string_field.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\map.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\map_field.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\message.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\message_lite.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\parse_context.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\reflection_ops.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\repeated_field.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\repeated_ptr_field.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\service.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\source_context.pb.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\struct.pb.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\text_format.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\timestamp.pb.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\type.pb.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\unknown_field_set.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\wire_format_lite.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\wire_format.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\wrappers.pb.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\io\coded_stream.h">
<Filter>io\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\io\gzip_stream.h">
<Filter>io\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\io\io_win32.h">
<Filter>io\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\io\printer.h">
<Filter>io\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\io\strtod.h">
<Filter>io\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\io\tokenizer.h">
<Filter>io\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\io\zero_copy_stream_impl_lite.h">
<Filter>io\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\io\zero_copy_stream_impl.h">
<Filter>io\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\io\zero_copy_stream.h">
<Filter>io\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\datapiece.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\default_value_objectwriter.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\error_listener.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\field_mask_utility.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\json_escaping.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\json_objectwriter.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\json_stream_parser.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\object_writer.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\proto_writer.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\protostream_objectsource.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\protostream_objectwriter.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\type_info.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\internal\utility.h">
<Filter>util\internal\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\delimited_message_util.h">
<Filter>util\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\field_comparator.h">
<Filter>util\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\field_mask_util.h">
<Filter>util\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\json_util.h">
<Filter>util\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\message_differencer.h">
<Filter>util\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\time_util.h">
<Filter>util\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\protobuf\util\type_resolver_util.h">
<Filter>util\include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="thirdparty\protobuf\version.rc" />
</ItemGroup>
</Project>

83
r5dev/thirdparty/protobuf/any.cc vendored Normal file
View File

@ -0,0 +1,83 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <thirdparty/protobuf/any.h>
#include <thirdparty/protobuf/arenastring.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/generated_message_util.h>
#include <thirdparty/protobuf/message.h>
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace internal {
bool AnyMetadata::PackFrom(Arena* arena, const Message& message) {
return PackFrom(arena, message, kTypeGoogleApisComPrefix);
}
bool AnyMetadata::PackFrom(Arena* arena, const Message& message,
StringPiece type_url_prefix) {
type_url_->Set(
&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString(),
GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix), arena);
return message.SerializeToString(
value_->Mutable(ArenaStringPtr::EmptyDefault{}, arena));
}
bool AnyMetadata::UnpackTo(Message* message) const {
if (!InternalIs(message->GetDescriptor()->full_name())) {
return false;
}
return message->ParseFromString(value_->Get());
}
bool GetAnyFieldDescriptors(const Message& message,
const FieldDescriptor** type_url_field,
const FieldDescriptor** value_field) {
const Descriptor* descriptor = message.GetDescriptor();
if (descriptor->full_name() != kAnyFullTypeName) {
return false;
}
*type_url_field = descriptor->FindFieldByNumber(1);
*value_field = descriptor->FindFieldByNumber(2);
return (*type_url_field != nullptr &&
(*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
*value_field != nullptr &&
(*value_field)->type() == FieldDescriptor::TYPE_BYTES);
}
} // namespace internal
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>

156
r5dev/thirdparty/protobuf/any.h vendored Normal file
View File

@ -0,0 +1,156 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_ANY_H__
#define GOOGLE_PROTOBUF_ANY_H__
#include <string>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/arenastring.h>
#include <thirdparty/protobuf/message_lite.h>
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
class FieldDescriptor;
class Message;
namespace internal {
extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/".
std::string GetTypeUrl(StringPiece message_name,
StringPiece type_url_prefix);
// Helper class used to implement google::protobuf::Any.
class PROTOBUF_EXPORT AnyMetadata {
typedef ArenaStringPtr UrlType;
typedef ArenaStringPtr ValueType;
public:
// AnyMetadata does not take ownership of "type_url" and "value".
constexpr AnyMetadata(UrlType* type_url, ValueType* value)
: type_url_(type_url), value_(value) {}
// Packs a message using the default type URL prefix: "type.googleapis.com".
// The resulted type URL will be "type.googleapis.com/<message_full_name>".
// Returns false if serializing the message failed.
template <typename T>
bool PackFrom(Arena* arena, const T& message) {
return InternalPackFrom(arena, message, kTypeGoogleApisComPrefix,
T::FullMessageName());
}
bool PackFrom(Arena* arena, const Message& message);
// Packs a message using the given type URL prefix. The type URL will be
// constructed by concatenating the message type's full name to the prefix
// with an optional "/" separator if the prefix doesn't already end with "/".
// For example, both PackFrom(message, "type.googleapis.com") and
// PackFrom(message, "type.googleapis.com/") yield the same result type
// URL: "type.googleapis.com/<message_full_name>".
// Returns false if serializing the message failed.
template <typename T>
bool PackFrom(Arena* arena, const T& message,
StringPiece type_url_prefix) {
return InternalPackFrom(arena, message, type_url_prefix,
T::FullMessageName());
}
bool PackFrom(Arena* arena, const Message& message,
StringPiece type_url_prefix);
// Unpacks the payload into the given message. Returns false if the message's
// type doesn't match the type specified in the type URL (i.e., the full
// name after the last "/" of the type URL doesn't match the message's actual
// full name) or parsing the payload has failed.
template <typename T>
bool UnpackTo(T* message) const {
return InternalUnpackTo(T::FullMessageName(), message);
}
bool UnpackTo(Message* message) const;
// Checks whether the type specified in the type URL matches the given type.
// A type is considered matching if its full name matches the full name after
// the last "/" in the type URL.
template <typename T>
bool Is() const {
return InternalIs(T::FullMessageName());
}
private:
bool InternalPackFrom(Arena* arena, const MessageLite& message,
StringPiece type_url_prefix,
StringPiece type_name);
bool InternalUnpackTo(StringPiece type_name,
MessageLite* message) const;
bool InternalIs(StringPiece type_name) const;
UrlType* type_url_;
ValueType* value_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata);
};
// Get the proto type name from Any::type_url value. For example, passing
// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
// *full_type_name. Returns false if the type_url does not have a "/"
// in the type url separating the full type name.
//
// NOTE: this function is available publicly as:
// google::protobuf::Any() // static method on the generated message type.
bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name);
// Get the proto type name and prefix from Any::type_url value. For example,
// passing "type.googleapis.com/rpc.QueryOrigin" will return
// "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in
// *full_type_name. Returns false if the type_url does not have a "/" in the
// type url separating the full type name.
bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
std::string* full_type_name);
// See if message is of type google.protobuf.Any, if so, return the descriptors
// for "type_url" and "value" fields.
bool GetAnyFieldDescriptors(const Message& message,
const FieldDescriptor** type_url_field,
const FieldDescriptor** value_field);
} // namespace internal
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_ANY_H__

352
r5dev/thirdparty/protobuf/any.pb.cc vendored Normal file
View File

@ -0,0 +1,352 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: google/protobuf/any.proto
#include <thirdparty/protobuf/any.pb.h>
#include <algorithm>
#include <thirdparty/protobuf/io/coded_stream.h>
#include <thirdparty/protobuf/extension_set.h>
#include <thirdparty/protobuf/wire_format_lite.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/generated_message_reflection.h>
#include <thirdparty/protobuf/reflection_ops.h>
#include <thirdparty/protobuf/wire_format.h>
// @@protoc_insertion_point(includes)
#include <thirdparty/protobuf/port_def.inc>
PROTOBUF_PRAGMA_INIT_SEG
PROTOBUF_NAMESPACE_OPEN
constexpr Any::Any(
::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
: type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
, value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
, _any_metadata_(&type_url_, &value_){}
struct AnyDefaultTypeInternal {
constexpr AnyDefaultTypeInternal()
: _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
~AnyDefaultTypeInternal() {}
union {
Any _instance;
};
};
PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT AnyDefaultTypeInternal _Any_default_instance_;
PROTOBUF_NAMESPACE_CLOSE
static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fany_2eproto[1];
static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
const uint32_t TableStruct_google_2fprotobuf_2fany_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
~0u, // no _has_bits_
PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, _internal_metadata_),
~0u, // no _extensions_
~0u, // no _oneof_case_
~0u, // no _weak_field_map_
~0u, // no _inlined_string_donated_
PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, type_url_),
PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, value_),
};
static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
{ 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Any)},
};
static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::PROTOBUF_NAMESPACE_ID::_Any_default_instance_),
};
const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
"\n\031google/protobuf/any.proto\022\017google.prot"
"obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
" \001(\014Bv\n\023com.google.protobufB\010AnyProtoP\001Z"
",google.golang.org/protobuf/types/known/"
"anypb\242\002\003GPB\252\002\036Google.Protobuf.WellKnownT"
"ypesb\006proto3"
;
static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fany_2eproto_once;
const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto = {
false, false, 212, descriptor_table_protodef_google_2fprotobuf_2fany_2eproto, "google/protobuf/any.proto",
&descriptor_table_google_2fprotobuf_2fany_2eproto_once, nullptr, 0, 1,
schemas, file_default_instances, TableStruct_google_2fprotobuf_2fany_2eproto::offsets,
file_level_metadata_google_2fprotobuf_2fany_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, file_level_service_descriptors_google_2fprotobuf_2fany_2eproto,
};
PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fany_2eproto_getter() {
return &descriptor_table_google_2fprotobuf_2fany_2eproto;
}
// Force running AddDescriptors() at dynamic initialization time.
PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fany_2eproto(&descriptor_table_google_2fprotobuf_2fany_2eproto);
PROTOBUF_NAMESPACE_OPEN
// ===================================================================
bool Any::GetAnyFieldDescriptors(
const ::PROTOBUF_NAMESPACE_ID::Message& message,
const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field,
const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field) {
return ::PROTOBUF_NAMESPACE_ID::internal::GetAnyFieldDescriptors(
message, type_url_field, value_field);
}
bool Any::ParseAnyTypeUrl(
::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,
std::string* full_type_name) {
return ::PROTOBUF_NAMESPACE_ID::internal::ParseAnyTypeUrl(type_url,
full_type_name);
}
class Any::_Internal {
public:
};
Any::Any(::PROTOBUF_NAMESPACE_ID::Arena* arena,
bool is_message_owned)
: ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
_any_metadata_(&type_url_, &value_) {
SharedCtor();
if (!is_message_owned) {
RegisterArenaDtor(arena);
}
// @@protoc_insertion_point(arena_constructor:google.protobuf.Any)
}
Any::Any(const Any& from)
: ::PROTOBUF_NAMESPACE_ID::Message(),
_any_metadata_(&type_url_, &value_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
if (!from._internal_type_url().empty()) {
type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_type_url(),
GetArenaForAllocation());
}
value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
if (!from._internal_value().empty()) {
value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_value(),
GetArenaForAllocation());
}
// @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
}
inline void Any::SharedCtor() {
type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
}
Any::~Any() {
// @@protoc_insertion_point(destructor:google.protobuf.Any)
if (GetArenaForAllocation() != nullptr) return;
SharedDtor();
_internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
}
inline void Any::SharedDtor() {
GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
type_url_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
}
void Any::ArenaDtor(void* object) {
Any* _this = reinterpret_cast< Any* >(object);
(void)_this;
}
void Any::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
}
void Any::SetCachedSize(int size) const {
_cached_size_.Set(size);
}
void Any::Clear() {
// @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
uint32_t cached_has_bits = 0;
// Prevent compiler warnings about cached_has_bits being unused
(void) cached_has_bits;
type_url_.ClearToEmpty();
value_.ClearToEmpty();
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
}
const char* Any::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
while (!ctx->Done(&ptr)) {
uint32_t tag;
ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
switch (tag >> 3) {
// string type_url = 1;
case 1:
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
auto str = _internal_mutable_type_url();
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.Any.type_url"));
CHK_(ptr);
} else
goto handle_unusual;
continue;
// bytes value = 2;
case 2:
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
auto str = _internal_mutable_value();
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
CHK_(ptr);
} else
goto handle_unusual;
continue;
default:
goto handle_unusual;
} // switch
handle_unusual:
if ((tag == 0) || ((tag & 7) == 4)) {
CHK_(ptr);
ctx->SetLastTag(tag);
goto message_done;
}
ptr = UnknownFieldParse(
tag,
_internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
ptr, ctx);
CHK_(ptr != nullptr);
} // while
message_done:
return ptr;
failure:
ptr = nullptr;
goto message_done;
#undef CHK_
}
uint8_t* Any::_InternalSerialize(
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
uint32_t cached_has_bits = 0;
(void) cached_has_bits;
// string type_url = 1;
if (!this->_internal_type_url().empty()) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->_internal_type_url().data(), static_cast<int>(this->_internal_type_url().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Any.type_url");
target = stream->WriteStringMaybeAliased(
1, this->_internal_type_url(), target);
}
// bytes value = 2;
if (!this->_internal_value().empty()) {
target = stream->WriteBytesMaybeAliased(
2, this->_internal_value(), target);
}
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
_internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
}
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any)
return target;
}
size_t Any::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any)
size_t total_size = 0;
uint32_t cached_has_bits = 0;
// Prevent compiler warnings about cached_has_bits being unused
(void) cached_has_bits;
// string type_url = 1;
if (!this->_internal_type_url().empty()) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
this->_internal_type_url());
}
// bytes value = 2;
if (!this->_internal_value().empty()) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize(
this->_internal_value());
}
return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);
}
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Any::_class_data_ = {
::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
Any::MergeImpl
};
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Any::GetClassData() const { return &_class_data_; }
void Any::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to,
const ::PROTOBUF_NAMESPACE_ID::Message& from) {
static_cast<Any *>(to)->MergeFrom(
static_cast<const Any &>(from));
}
void Any::MergeFrom(const Any& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any)
GOOGLE_DCHECK_NE(&from, this);
uint32_t cached_has_bits = 0;
(void) cached_has_bits;
if (!from._internal_type_url().empty()) {
_internal_set_type_url(from._internal_type_url());
}
if (!from._internal_value().empty()) {
_internal_set_value(from._internal_value());
}
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
}
void Any::CopyFrom(const Any& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Any)
if (&from == this) return;
Clear();
MergeFrom(from);
}
bool Any::IsInitialized() const {
return true;
}
void Any::InternalSwap(Any* other) {
using std::swap;
auto* lhs_arena = GetArenaForAllocation();
auto* rhs_arena = other->GetArenaForAllocation();
_internal_metadata_.InternalSwap(&other->_internal_metadata_);
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
&type_url_, lhs_arena,
&other->type_url_, rhs_arena
);
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
&value_, lhs_arena,
&other->value_, rhs_arena
);
}
::PROTOBUF_NAMESPACE_ID::Metadata Any::GetMetadata() const {
return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
&descriptor_table_google_2fprotobuf_2fany_2eproto_getter, &descriptor_table_google_2fprotobuf_2fany_2eproto_once,
file_level_metadata_google_2fprotobuf_2fany_2eproto[0]);
}
// @@protoc_insertion_point(namespace_scope)
PROTOBUF_NAMESPACE_CLOSE
PROTOBUF_NAMESPACE_OPEN
template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Any >(Arena* arena) {
return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Any >(arena);
}
PROTOBUF_NAMESPACE_CLOSE
// @@protoc_insertion_point(global_scope)
#include <thirdparty/protobuf/port_undef.inc>

391
r5dev/thirdparty/protobuf/any.pb.h vendored Normal file
View File

@ -0,0 +1,391 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: google/protobuf/any.proto
#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
#include <limits>
#include <string>
#include <thirdparty/protobuf/port_def.inc>
#if PROTOBUF_VERSION < 3019000
#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 3019004 < 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 <thirdparty/protobuf/port_undef.inc>
#include <thirdparty/protobuf/io/coded_stream.h>
#include <thirdparty/protobuf/arena.h>
#include <thirdparty/protobuf/arenastring.h>
#include <thirdparty/protobuf/generated_message_table_driven.h>
#include <thirdparty/protobuf/generated_message_util.h>
#include <thirdparty/protobuf/metadata_lite.h>
#include <thirdparty/protobuf/generated_message_reflection.h>
#include <thirdparty/protobuf/message.h>
#include <thirdparty/protobuf/repeated_field.h> // IWYU pragma: export
#include <thirdparty/protobuf/extension_set.h> // IWYU pragma: export
#include <thirdparty/protobuf/unknown_field_set.h>
// @@protoc_insertion_point(includes)
#include <thirdparty/protobuf/port_def.inc>
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fany_2eproto PROTOBUF_EXPORT
PROTOBUF_NAMESPACE_OPEN
namespace internal {
class AnyMetadata;
} // namespace internal
PROTOBUF_NAMESPACE_CLOSE
// Internal implementation detail -- do not use these members.
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fany_2eproto {
static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1]
PROTOBUF_SECTION_VARIABLE(protodesc_cold);
static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[];
static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
static const uint32_t offsets[];
};
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto;
PROTOBUF_NAMESPACE_OPEN
class Any;
struct AnyDefaultTypeInternal;
PROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
PROTOBUF_NAMESPACE_CLOSE
PROTOBUF_NAMESPACE_OPEN
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Any>(Arena*);
PROTOBUF_NAMESPACE_CLOSE
PROTOBUF_NAMESPACE_OPEN
// ===================================================================
class PROTOBUF_EXPORT Any final :
public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ {
public:
inline Any() : Any(nullptr) {}
~Any() override;
explicit constexpr Any(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
Any(const Any& from);
Any(Any&& from) noexcept
: Any() {
*this = ::std::move(from);
}
inline Any& operator=(const Any& from) {
CopyFrom(from);
return *this;
}
inline Any& operator=(Any&& from) noexcept {
if (this == &from) return *this;
if (GetOwningArena() == from.GetOwningArena()
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
&& GetOwningArena() != nullptr
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
) {
InternalSwap(&from);
} else {
CopyFrom(from);
}
return *this;
}
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
return GetDescriptor();
}
static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
return default_instance().GetMetadata().descriptor;
}
static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
return default_instance().GetMetadata().reflection;
}
static const Any& default_instance() {
return *internal_default_instance();
}
static inline const Any* internal_default_instance() {
return reinterpret_cast<const Any*>(
&_Any_default_instance_);
}
static constexpr int kIndexInFileMessages =
0;
// implements Any -----------------------------------------------
bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message) {
return _any_metadata_.PackFrom(GetArena(), message);
}
bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message,
::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
return _any_metadata_.PackFrom(GetArena(), message, type_url_prefix);
}
bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const {
return _any_metadata_.UnpackTo(message);
}
static bool GetAnyFieldDescriptors(
const ::PROTOBUF_NAMESPACE_ID::Message& message,
const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field,
const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field);
template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
bool PackFrom(const T& message) {
return _any_metadata_.PackFrom<T>(GetArena(), message);
}
template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
bool PackFrom(const T& message,
::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
return _any_metadata_.PackFrom<T>(GetArena(), message, type_url_prefix);}
template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
bool UnpackTo(T* message) const {
return _any_metadata_.UnpackTo<T>(message);
}
template<typename T> bool Is() const {
return _any_metadata_.Is<T>();
}
static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,
std::string* full_type_name);
friend void swap(Any& a, Any& b) {
a.Swap(&b);
}
inline void Swap(Any* other) {
if (other == this) return;
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
if (GetOwningArena() != nullptr &&
GetOwningArena() == other->GetOwningArena()) {
#else // PROTOBUF_FORCE_COPY_IN_SWAP
if (GetOwningArena() == other->GetOwningArena()) {
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
InternalSwap(other);
} else {
::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
}
}
void UnsafeArenaSwap(Any* other) {
if (other == this) return;
GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
InternalSwap(other);
}
// implements Message ----------------------------------------------
Any* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<Any>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
void CopyFrom(const Any& from);
using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
void MergeFrom(const Any& from);
private:
static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from);
public:
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
bool IsInitialized() const final;
size_t ByteSizeLong() const final;
const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
uint8_t* _InternalSerialize(
uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
int GetCachedSize() const final { return _cached_size_.Get(); }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(Any* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.Any";
}
protected:
explicit Any(::PROTOBUF_NAMESPACE_ID::Arena* arena,
bool is_message_owned = false);
private:
static void ArenaDtor(void* object);
inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
public:
static const ClassData _class_data_;
const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
enum : int {
kTypeUrlFieldNumber = 1,
kValueFieldNumber = 2,
};
// string type_url = 1;
void clear_type_url();
const std::string& type_url() const;
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_type_url(ArgT0&& arg0, ArgT... args);
std::string* mutable_type_url();
PROTOBUF_NODISCARD std::string* release_type_url();
void set_allocated_type_url(std::string* type_url);
private:
const std::string& _internal_type_url() const;
inline PROTOBUF_ALWAYS_INLINE void _internal_set_type_url(const std::string& value);
std::string* _internal_mutable_type_url();
public:
// bytes value = 2;
void clear_value();
const std::string& value() const;
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_value(ArgT0&& arg0, ArgT... args);
std::string* mutable_value();
PROTOBUF_NODISCARD std::string* release_value();
void set_allocated_value(std::string* value);
private:
const std::string& _internal_value() const;
inline PROTOBUF_ALWAYS_INLINE void _internal_set_value(const std::string& value);
std::string* _internal_mutable_value();
public:
// @@protoc_insertion_point(class_scope:google.protobuf.Any)
private:
class _Internal;
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_;
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr type_url_;
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr value_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata _any_metadata_;
friend struct ::TableStruct_google_2fprotobuf_2fany_2eproto;
};
// ===================================================================
// ===================================================================
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif // __GNUC__
// Any
// string type_url = 1;
inline void Any::clear_type_url() {
type_url_.ClearToEmpty();
}
inline const std::string& Any::type_url() const {
// @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
return _internal_type_url();
}
template <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void Any::set_type_url(ArgT0&& arg0, ArgT... args) {
type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
// @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
}
inline std::string* Any::mutable_type_url() {
std::string* _s = _internal_mutable_type_url();
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
return _s;
}
inline const std::string& Any::_internal_type_url() const {
return type_url_.Get();
}
inline void Any::_internal_set_type_url(const std::string& value) {
type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
}
inline std::string* Any::_internal_mutable_type_url() {
return type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
}
inline std::string* Any::release_type_url() {
// @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
return type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
}
inline void Any::set_allocated_type_url(std::string* type_url) {
if (type_url != nullptr) {
} else {
}
type_url_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), type_url,
GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
if (type_url_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
}
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
}
// bytes value = 2;
inline void Any::clear_value() {
value_.ClearToEmpty();
}
inline const std::string& Any::value() const {
// @@protoc_insertion_point(field_get:google.protobuf.Any.value)
return _internal_value();
}
template <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void Any::set_value(ArgT0&& arg0, ArgT... args) {
value_.SetBytes(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
// @@protoc_insertion_point(field_set:google.protobuf.Any.value)
}
inline std::string* Any::mutable_value() {
std::string* _s = _internal_mutable_value();
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
return _s;
}
inline const std::string& Any::_internal_value() const {
return value_.Get();
}
inline void Any::_internal_set_value(const std::string& value) {
value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
}
inline std::string* Any::_internal_mutable_value() {
return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
}
inline std::string* Any::release_value() {
// @@protoc_insertion_point(field_release:google.protobuf.Any.value)
return value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
}
inline void Any::set_allocated_value(std::string* value) {
if (value != nullptr) {
} else {
}
value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value,
GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
if (value_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
}
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif // __GNUC__
// @@protoc_insertion_point(namespace_scope)
PROTOBUF_NAMESPACE_CLOSE
// @@protoc_insertion_point(global_scope)
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto

158
r5dev/thirdparty/protobuf/any.proto vendored Normal file
View File

@ -0,0 +1,158 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package google.protobuf;
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option go_package = "google.golang.org/protobuf/types/known/anypb";
option java_package = "com.google.protobuf";
option java_outer_classname = "AnyProto";
option java_multiple_files = true;
option objc_class_prefix = "GPB";
// `Any` contains an arbitrary serialized protocol buffer message along with a
// URL that describes the type of the serialized message.
//
// Protobuf library provides support to pack/unpack Any values in the form
// of utility functions or additional generated methods of the Any type.
//
// Example 1: Pack and unpack a message in C++.
//
// Foo foo = ...;
// Any any;
// any.PackFrom(foo);
// ...
// if (any.UnpackTo(&foo)) {
// ...
// }
//
// Example 2: Pack and unpack a message in Java.
//
// Foo foo = ...;
// Any any = Any.pack(foo);
// ...
// if (any.is(Foo.class)) {
// foo = any.unpack(Foo.class);
// }
//
// Example 3: Pack and unpack a message in Python.
//
// foo = Foo(...)
// any = Any()
// any.Pack(foo)
// ...
// if any.Is(Foo.DESCRIPTOR):
// any.Unpack(foo)
// ...
//
// Example 4: Pack and unpack a message in Go
//
// foo := &pb.Foo{...}
// any, err := anypb.New(foo)
// if err != nil {
// ...
// }
// ...
// foo := &pb.Foo{}
// if err := any.UnmarshalTo(foo); err != nil {
// ...
// }
//
// The pack methods provided by protobuf library will by default use
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
// methods only use the fully qualified type name after the last '/'
// in the type URL, for example "foo.bar.com/x/y.z" will yield type
// name "y.z".
//
//
// JSON
// ====
// The JSON representation of an `Any` value uses the regular
// representation of the deserialized, embedded message, with an
// additional field `@type` which contains the type URL. Example:
//
// package google.profile;
// message Person {
// string first_name = 1;
// string last_name = 2;
// }
//
// {
// "@type": "type.googleapis.com/google.profile.Person",
// "firstName": <string>,
// "lastName": <string>
// }
//
// If the embedded message type is well-known and has a custom JSON
// representation, that representation will be embedded adding a field
// `value` which holds the custom JSON in addition to the `@type`
// field. Example (for message [google.protobuf.Duration][]):
//
// {
// "@type": "type.googleapis.com/google.protobuf.Duration",
// "value": "1.212s"
// }
//
message Any {
// A URL/resource name that uniquely identifies the type of the serialized
// protocol buffer message. This string must contain at least
// one "/" character. The last segment of the URL's path must represent
// the fully qualified name of the type (as in
// `path/google.protobuf.Duration`). The name should be in a canonical form
// (e.g., leading "." is not accepted).
//
// In practice, teams usually precompile into the binary all types that they
// expect it to use in the context of Any. However, for URLs which use the
// scheme `http`, `https`, or no scheme, one can optionally set up a type
// server that maps type URLs to message definitions as follows:
//
// * If no scheme is provided, `https` is assumed.
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
// value in binary format, or produce an error.
// * Applications are allowed to cache lookup results based on the
// URL, or have them precompiled into a binary to avoid any
// lookup. Therefore, binary compatibility needs to be preserved
// on changes to types. (Use versioned type names to manage
// breaking changes.)
//
// Note: this functionality is not currently available in the official
// protobuf release, and it is not used for type URLs beginning with
// type.googleapis.com.
//
// Schemes other than `http`, `https` (or the empty scheme) might be
// used with implementation specific semantics.
//
string type_url = 1;
// Must be a valid serialized protocol buffer of the above specified type.
bytes value = 2;
}

99
r5dev/thirdparty/protobuf/any_lite.cc vendored Normal file
View File

@ -0,0 +1,99 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <thirdparty/protobuf/any.h>
#include <thirdparty/protobuf/io/zero_copy_stream_impl_lite.h>
#include <thirdparty/protobuf/arenastring.h>
#include <thirdparty/protobuf/generated_message_util.h>
#include <thirdparty/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace internal {
std::string GetTypeUrl(StringPiece message_name,
StringPiece type_url_prefix) {
if (!type_url_prefix.empty() &&
type_url_prefix[type_url_prefix.size() - 1] == '/') {
return StrCat(type_url_prefix, message_name);
} else {
return StrCat(type_url_prefix, "/", message_name);
}
}
const char kAnyFullTypeName[] = "google.protobuf.Any";
const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
bool AnyMetadata::InternalPackFrom(Arena* arena, const MessageLite& message,
StringPiece type_url_prefix,
StringPiece type_name) {
type_url_->Set(&::google::protobuf::internal::GetEmptyString(),
GetTypeUrl(type_name, type_url_prefix), arena);
return message.SerializeToString(
value_->Mutable(ArenaStringPtr::EmptyDefault{}, arena));
}
bool AnyMetadata::InternalUnpackTo(StringPiece type_name,
MessageLite* message) const {
if (!InternalIs(type_name)) {
return false;
}
return message->ParseFromString(value_->Get());
}
bool AnyMetadata::InternalIs(StringPiece type_name) const {
StringPiece type_url = type_url_->Get();
return type_url.size() >= type_name.size() + 1 &&
type_url[type_url.size() - type_name.size() - 1] == '/' &&
HasSuffixString(type_url, type_name);
}
bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
std::string* full_type_name) {
size_t pos = type_url.find_last_of('/');
if (pos == std::string::npos || pos + 1 == type_url.size()) {
return false;
}
if (url_prefix) {
*url_prefix = std::string(type_url.substr(0, pos + 1));
}
*full_type_name = std::string(type_url.substr(pos + 1));
return true;
}
bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name) {
return ParseAnyTypeUrl(type_url, nullptr, full_type_name);
}
} // namespace internal
} // namespace protobuf
} // namespace google

184
r5dev/thirdparty/protobuf/any_test.cc vendored Normal file
View File

@ -0,0 +1,184 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <thirdparty/protobuf/any_test.pb.h>
#include <thirdparty/protobuf/unittest.pb.h>
#include <gtest/gtest.h>
// Must be included last.
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace {
TEST(AnyMetadataTest, ConstInit) {
PROTOBUF_CONSTINIT static internal::AnyMetadata metadata(nullptr, nullptr);
(void)metadata;
}
TEST(AnyTest, TestPackAndUnpack) {
protobuf_unittest::TestAny submessage;
submessage.set_int32_value(12345);
protobuf_unittest::TestAny message;
ASSERT_TRUE(message.mutable_any_value()->PackFrom(submessage));
std::string data = message.SerializeAsString();
ASSERT_TRUE(message.ParseFromString(data));
EXPECT_TRUE(message.has_any_value());
submessage.Clear();
ASSERT_TRUE(message.any_value().UnpackTo(&submessage));
EXPECT_EQ(12345, submessage.int32_value());
}
TEST(AnyTest, TestPackFromSerializationExceedsSizeLimit) {
protobuf_unittest::TestAny submessage;
submessage.mutable_text()->resize(INT_MAX, 'a');
protobuf_unittest::TestAny message;
EXPECT_FALSE(message.mutable_any_value()->PackFrom(submessage));
}
TEST(AnyTest, TestUnpackWithTypeMismatch) {
protobuf_unittest::TestAny payload;
payload.set_int32_value(13);
google::protobuf::Any any;
any.PackFrom(payload);
// Attempt to unpack into the wrong type.
protobuf_unittest::TestAllTypes dest;
EXPECT_FALSE(any.UnpackTo(&dest));
}
TEST(AnyTest, TestPackAndUnpackAny) {
// We can pack a Any message inside another Any message.
protobuf_unittest::TestAny submessage;
submessage.set_int32_value(12345);
google::protobuf::Any any;
any.PackFrom(submessage);
protobuf_unittest::TestAny message;
message.mutable_any_value()->PackFrom(any);
std::string data = message.SerializeAsString();
ASSERT_TRUE(message.ParseFromString(data));
EXPECT_TRUE(message.has_any_value());
any.Clear();
submessage.Clear();
ASSERT_TRUE(message.any_value().UnpackTo(&any));
ASSERT_TRUE(any.UnpackTo(&submessage));
EXPECT_EQ(12345, submessage.int32_value());
}
TEST(AnyTest, TestPackWithCustomTypeUrl) {
protobuf_unittest::TestAny submessage;
submessage.set_int32_value(12345);
google::protobuf::Any any;
// Pack with a custom type URL prefix.
any.PackFrom(submessage, "type.myservice.com");
EXPECT_EQ("type.myservice.com/protobuf_unittest.TestAny", any.type_url());
// Pack with a custom type URL prefix ending with '/'.
any.PackFrom(submessage, "type.myservice.com/");
EXPECT_EQ("type.myservice.com/protobuf_unittest.TestAny", any.type_url());
// Pack with an empty type URL prefix.
any.PackFrom(submessage, "");
EXPECT_EQ("/protobuf_unittest.TestAny", any.type_url());
// Test unpacking the type.
submessage.Clear();
EXPECT_TRUE(any.UnpackTo(&submessage));
EXPECT_EQ(12345, submessage.int32_value());
}
TEST(AnyTest, TestIs) {
protobuf_unittest::TestAny submessage;
submessage.set_int32_value(12345);
google::protobuf::Any any;
any.PackFrom(submessage);
ASSERT_TRUE(any.ParseFromString(any.SerializeAsString()));
EXPECT_TRUE(any.Is<protobuf_unittest::TestAny>());
EXPECT_FALSE(any.Is<google::protobuf::Any>());
protobuf_unittest::TestAny message;
message.mutable_any_value()->PackFrom(any);
ASSERT_TRUE(message.ParseFromString(message.SerializeAsString()));
EXPECT_FALSE(message.any_value().Is<protobuf_unittest::TestAny>());
EXPECT_TRUE(message.any_value().Is<google::protobuf::Any>());
any.set_type_url("/protobuf_unittest.TestAny");
EXPECT_TRUE(any.Is<protobuf_unittest::TestAny>());
// The type URL must contain at least one "/".
any.set_type_url("protobuf_unittest.TestAny");
EXPECT_FALSE(any.Is<protobuf_unittest::TestAny>());
// The type name after the slash must be fully qualified.
any.set_type_url("/TestAny");
EXPECT_FALSE(any.Is<protobuf_unittest::TestAny>());
}
TEST(AnyTest, MoveConstructor) {
protobuf_unittest::TestAny payload;
payload.set_int32_value(12345);
google::protobuf::Any src;
src.PackFrom(payload);
const char* type_url = src.type_url().data();
google::protobuf::Any dst(std::move(src));
EXPECT_EQ(type_url, dst.type_url().data());
payload.Clear();
ASSERT_TRUE(dst.UnpackTo(&payload));
EXPECT_EQ(12345, payload.int32_value());
}
TEST(AnyTest, MoveAssignment) {
protobuf_unittest::TestAny payload;
payload.set_int32_value(12345);
google::protobuf::Any src;
src.PackFrom(payload);
const char* type_url = src.type_url().data();
google::protobuf::Any dst;
dst = std::move(src);
EXPECT_EQ(type_url, dst.type_url().data());
payload.Clear();
ASSERT_TRUE(dst.UnpackTo(&payload));
EXPECT_EQ(12345, payload.int32_value());
}
} // namespace
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>

View File

@ -0,0 +1,44 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package protobuf_unittest;
import "google/protobuf/any.proto";
option java_outer_classname = "TestAnyProto";
message TestAny {
int32 int32_value = 1;
google.protobuf.Any any_value = 2;
repeated google.protobuf.Any repeated_any_value = 3;
string text = 4;
}

1291
r5dev/thirdparty/protobuf/api.pb.cc vendored Normal file

File diff suppressed because it is too large Load Diff

1448
r5dev/thirdparty/protobuf/api.pb.h vendored Normal file

File diff suppressed because it is too large Load Diff

208
r5dev/thirdparty/protobuf/api.proto vendored Normal file
View File

@ -0,0 +1,208 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package google.protobuf;
import "google/protobuf/source_context.proto";
import "google/protobuf/type.proto";
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option java_package = "com.google.protobuf";
option java_outer_classname = "ApiProto";
option java_multiple_files = true;
option objc_class_prefix = "GPB";
option go_package = "google.golang.org/protobuf/types/known/apipb";
// Api is a light-weight descriptor for an API Interface.
//
// Interfaces are also described as "protocol buffer services" in some contexts,
// such as by the "service" keyword in a .proto file, but they are different
// from API Services, which represent a concrete implementation of an interface
// as opposed to simply a description of methods and bindings. They are also
// sometimes simply referred to as "APIs" in other contexts, such as the name of
// this message itself. See https://cloud.google.com/apis/design/glossary for
// detailed terminology.
message Api {
// The fully qualified name of this interface, including package name
// followed by the interface's simple name.
string name = 1;
// The methods of this interface, in unspecified order.
repeated Method methods = 2;
// Any metadata attached to the interface.
repeated Option options = 3;
// A version string for this interface. If specified, must have the form
// `major-version.minor-version`, as in `1.10`. If the minor version is
// omitted, it defaults to zero. If the entire version field is empty, the
// major version is derived from the package name, as outlined below. If the
// field is not empty, the version in the package name will be verified to be
// consistent with what is provided here.
//
// The versioning schema uses [semantic
// versioning](http://semver.org) where the major version number
// indicates a breaking change and the minor version an additive,
// non-breaking change. Both version numbers are signals to users
// what to expect from different versions, and should be carefully
// chosen based on the product plan.
//
// The major version is also reflected in the package name of the
// interface, which must end in `v<major-version>`, as in
// `google.feature.v1`. For major versions 0 and 1, the suffix can
// be omitted. Zero major versions must only be used for
// experimental, non-GA interfaces.
//
//
string version = 4;
// Source context for the protocol buffer service represented by this
// message.
SourceContext source_context = 5;
// Included interfaces. See [Mixin][].
repeated Mixin mixins = 6;
// The source syntax of the service.
Syntax syntax = 7;
}
// Method represents a method of an API interface.
message Method {
// The simple name of this method.
string name = 1;
// A URL of the input message type.
string request_type_url = 2;
// If true, the request is streamed.
bool request_streaming = 3;
// The URL of the output message type.
string response_type_url = 4;
// If true, the response is streamed.
bool response_streaming = 5;
// Any metadata attached to the method.
repeated Option options = 6;
// The source syntax of this method.
Syntax syntax = 7;
}
// Declares an API Interface to be included in this interface. The including
// interface must redeclare all the methods from the included interface, but
// documentation and options are inherited as follows:
//
// - If after comment and whitespace stripping, the documentation
// string of the redeclared method is empty, it will be inherited
// from the original method.
//
// - Each annotation belonging to the service config (http,
// visibility) which is not set in the redeclared method will be
// inherited.
//
// - If an http annotation is inherited, the path pattern will be
// modified as follows. Any version prefix will be replaced by the
// version of the including interface plus the [root][] path if
// specified.
//
// Example of a simple mixin:
//
// package google.acl.v1;
// service AccessControl {
// // Get the underlying ACL object.
// rpc GetAcl(GetAclRequest) returns (Acl) {
// option (google.api.http).get = "/v1/{resource=**}:getAcl";
// }
// }
//
// package google.storage.v2;
// service Storage {
// rpc GetAcl(GetAclRequest) returns (Acl);
//
// // Get a data record.
// rpc GetData(GetDataRequest) returns (Data) {
// option (google.api.http).get = "/v2/{resource=**}";
// }
// }
//
// Example of a mixin configuration:
//
// apis:
// - name: google.storage.v2.Storage
// mixins:
// - name: google.acl.v1.AccessControl
//
// The mixin construct implies that all methods in `AccessControl` are
// also declared with same name and request/response types in
// `Storage`. A documentation generator or annotation processor will
// see the effective `Storage.GetAcl` method after inheriting
// documentation and annotations as follows:
//
// service Storage {
// // Get the underlying ACL object.
// rpc GetAcl(GetAclRequest) returns (Acl) {
// option (google.api.http).get = "/v2/{resource=**}:getAcl";
// }
// ...
// }
//
// Note how the version in the path pattern changed from `v1` to `v2`.
//
// If the `root` field in the mixin is specified, it should be a
// relative path under which inherited HTTP paths are placed. Example:
//
// apis:
// - name: google.storage.v2.Storage
// mixins:
// - name: google.acl.v1.AccessControl
// root: acls
//
// This implies the following inherited HTTP annotation:
//
// service Storage {
// // Get the underlying ACL object.
// rpc GetAcl(GetAclRequest) returns (Acl) {
// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
// }
// ...
// }
message Mixin {
// The fully qualified name of the interface which is included.
string name = 1;
// If non-empty specifies a path under which inherited HTTP paths
// are rooted.
string root = 2;
}

511
r5dev/thirdparty/protobuf/arena.cc vendored Normal file
View File

@ -0,0 +1,511 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <thirdparty/protobuf/arena.h>
#include <algorithm>
#include <atomic>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <typeinfo>
#include <thirdparty/protobuf/arena_impl.h>
#include <thirdparty/protobuf/stubs/mutex.h>
#ifdef ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif // ADDRESS_SANITIZER
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace internal {
static SerialArena::Memory AllocateMemory(const AllocationPolicy* policy_ptr,
size_t last_size, size_t min_bytes) {
AllocationPolicy policy; // default policy
if (policy_ptr) policy = *policy_ptr;
size_t size;
if (last_size != 0) {
// Double the current block size, up to a limit.
auto max_size = policy.max_block_size;
size = std::min(2 * last_size, max_size);
} else {
size = policy.start_block_size;
}
// Verify that min_bytes + kBlockHeaderSize won't overflow.
GOOGLE_CHECK_LE(min_bytes,
std::numeric_limits<size_t>::max() - SerialArena::kBlockHeaderSize);
size = std::max(size, SerialArena::kBlockHeaderSize + min_bytes);
void* mem;
if (policy.block_alloc == nullptr) {
mem = ::operator new(size);
} else {
mem = policy.block_alloc(size);
}
return {mem, size};
}
class GetDeallocator {
public:
GetDeallocator(const AllocationPolicy* policy, size_t* space_allocated)
: dealloc_(policy ? policy->block_dealloc : nullptr),
space_allocated_(space_allocated) {}
void operator()(SerialArena::Memory mem) const {
#ifdef ADDRESS_SANITIZER
// This memory was provided by the underlying allocator as unpoisoned,
// so return it in an unpoisoned state.
ASAN_UNPOISON_MEMORY_REGION(mem.ptr, mem.size);
#endif // ADDRESS_SANITIZER
if (dealloc_) {
dealloc_(mem.ptr, mem.size);
} else {
#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
::operator delete(mem.ptr, mem.size);
#else
::operator delete(mem.ptr);
#endif
}
*space_allocated_ += mem.size;
}
private:
void (*dealloc_)(void*, size_t);
size_t* space_allocated_;
};
SerialArena::SerialArena(Block* b, void* owner) : space_allocated_(b->size) {
owner_ = owner;
head_ = b;
ptr_ = b->Pointer(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize);
limit_ = b->Pointer(b->size & static_cast<size_t>(-8));
}
SerialArena* SerialArena::New(Memory mem, void* owner) {
GOOGLE_DCHECK_LE(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize, mem.size);
auto b = new (mem.ptr) Block{nullptr, mem.size};
return new (b->Pointer(kBlockHeaderSize)) SerialArena(b, owner);
}
template <typename Deallocator>
SerialArena::Memory SerialArena::Free(Deallocator deallocator) {
Block* b = head_;
Memory mem = {b, b->size};
while (b->next) {
b = b->next; // We must first advance before deleting this block
deallocator(mem);
mem = {b, b->size};
}
return mem;
}
PROTOBUF_NOINLINE
std::pair<void*, SerialArena::CleanupNode*>
SerialArena::AllocateAlignedWithCleanupFallback(
size_t n, const AllocationPolicy* policy) {
AllocateNewBlock(n + kCleanupSize, policy);
return AllocateFromExistingWithCleanupFallback(n);
}
PROTOBUF_NOINLINE
void* SerialArena::AllocateAlignedFallback(size_t n,
const AllocationPolicy* policy) {
AllocateNewBlock(n, policy);
return AllocateFromExisting(n);
}
void SerialArena::AllocateNewBlock(size_t n, const AllocationPolicy* policy) {
// Sync limit to block
head_->start = reinterpret_cast<CleanupNode*>(limit_);
// Record how much used in this block.
space_used_ += ptr_ - head_->Pointer(kBlockHeaderSize);
auto mem = AllocateMemory(policy, head_->size, n);
// We don't want to emit an expensive RMW instruction that requires
// exclusive access to a cacheline. Hence we write it in terms of a
// regular add.
auto relaxed = std::memory_order_relaxed;
space_allocated_.store(space_allocated_.load(relaxed) + mem.size, relaxed);
head_ = new (mem.ptr) Block{head_, mem.size};
ptr_ = head_->Pointer(kBlockHeaderSize);
limit_ = head_->Pointer(head_->size);
#ifdef ADDRESS_SANITIZER
ASAN_POISON_MEMORY_REGION(ptr_, limit_ - ptr_);
#endif // ADDRESS_SANITIZER
}
uint64_t SerialArena::SpaceUsed() const {
uint64_t space_used = ptr_ - head_->Pointer(kBlockHeaderSize);
space_used += space_used_;
// Remove the overhead of the SerialArena itself.
space_used -= ThreadSafeArena::kSerialArenaSize;
return space_used;
}
void SerialArena::CleanupList() {
Block* b = head_;
b->start = reinterpret_cast<CleanupNode*>(limit_);
do {
auto* limit = reinterpret_cast<CleanupNode*>(
b->Pointer(b->size & static_cast<size_t>(-8)));
auto it = b->start;
auto num = limit - it;
if (num > 0) {
for (; it < limit; it++) {
it->cleanup(it->elem);
}
}
b = b->next;
} while (b);
}
ThreadSafeArena::CacheAlignedLifecycleIdGenerator
ThreadSafeArena::lifecycle_id_generator_;
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() {
static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
new internal::ThreadLocalStorage<ThreadCache>();
return *thread_cache_->Get();
}
#elif defined(PROTOBUF_USE_DLLS)
ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() {
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_ = {
0, static_cast<LifecycleIdAtomic>(-1), nullptr};
return thread_cache_;
}
#else
PROTOBUF_THREAD_LOCAL ThreadSafeArena::ThreadCache
ThreadSafeArena::thread_cache_ = {0, static_cast<LifecycleIdAtomic>(-1),
nullptr};
#endif
void ThreadSafeArena::InitializeFrom(void* mem, size_t size) {
GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0u);
GOOGLE_DCHECK(!AllocPolicy()); // Reset should call InitializeWithPolicy instead.
Init();
// Ignore initial block if it is too small.
if (mem != nullptr && size >= kBlockHeaderSize + kSerialArenaSize) {
alloc_policy_.set_is_user_owned_initial_block(true);
SetInitialBlock(mem, size);
}
}
void ThreadSafeArena::InitializeWithPolicy(void* mem, size_t size,
AllocationPolicy policy) {
#ifndef NDEBUG
const uint64_t old_alloc_policy = alloc_policy_.get_raw();
// If there was a policy (e.g., in Reset()), make sure flags were preserved.
#define GOOGLE_DCHECK_POLICY_FLAGS_() \
if (old_alloc_policy > 3) \
GOOGLE_CHECK_EQ(old_alloc_policy & 3, alloc_policy_.get_raw() & 3)
#else
#define GOOGLE_DCHECK_POLICY_FLAGS_()
#endif // NDEBUG
if (policy.IsDefault()) {
// Legacy code doesn't use the API above, but provides the initial block
// through ArenaOptions. I suspect most do not touch the allocation
// policy parameters.
InitializeFrom(mem, size);
GOOGLE_DCHECK_POLICY_FLAGS_();
return;
}
GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0u);
Init();
// Ignore initial block if it is too small. We include an optional
// AllocationPolicy in this check, so that this can be allocated on the
// first block.
constexpr size_t kAPSize = internal::AlignUpTo8(sizeof(AllocationPolicy));
constexpr size_t kMinimumSize = kBlockHeaderSize + kSerialArenaSize + kAPSize;
// The value for alloc_policy_ stores whether or not allocations should be
// recorded.
alloc_policy_.set_should_record_allocs(
policy.metrics_collector != nullptr &&
policy.metrics_collector->RecordAllocs());
// Make sure we have an initial block to store the AllocationPolicy.
if (mem != nullptr && size >= kMinimumSize) {
alloc_policy_.set_is_user_owned_initial_block(true);
} else {
auto tmp = AllocateMemory(&policy, 0, kMinimumSize);
mem = tmp.ptr;
size = tmp.size;
}
SetInitialBlock(mem, size);
auto sa = threads_.load(std::memory_order_relaxed);
// We ensured enough space so this cannot fail.
void* p;
if (!sa || !sa->MaybeAllocateAligned(kAPSize, &p)) {
GOOGLE_LOG(FATAL) << "MaybeAllocateAligned cannot fail here.";
return;
}
new (p) AllocationPolicy{policy};
// Low bits store flags, so they mustn't be overwritten.
GOOGLE_DCHECK_EQ(0, reinterpret_cast<uintptr_t>(p) & 3);
alloc_policy_.set_policy(reinterpret_cast<AllocationPolicy*>(p));
GOOGLE_DCHECK_POLICY_FLAGS_();
#undef GOOGLE_DCHECK_POLICY_FLAGS_
}
void ThreadSafeArena::Init() {
#ifndef NDEBUG
const bool was_message_owned = IsMessageOwned();
#endif // NDEBUG
ThreadCache& tc = thread_cache();
auto id = tc.next_lifecycle_id;
// We increment lifecycle_id's by multiples of two so we can use bit 0 as
// a tag.
constexpr uint64_t kDelta = 2;
constexpr uint64_t kInc = ThreadCache::kPerThreadIds * kDelta;
if (PROTOBUF_PREDICT_FALSE((id & (kInc - 1)) == 0)) {
constexpr auto relaxed = std::memory_order_relaxed;
// On platforms that don't support uint64_t atomics we can certainly not
// afford to increment by large intervals and expect uniqueness due to
// wrapping, hence we only add by 1.
id = lifecycle_id_generator_.id.fetch_add(1, relaxed) * kInc;
}
tc.next_lifecycle_id = id + kDelta;
// Message ownership is stored in tag_and_id_, and is set in the constructor.
// This flag bit must be preserved, even across calls to Reset().
tag_and_id_ = id | (tag_and_id_ & kMessageOwnedArena);
hint_.store(nullptr, std::memory_order_relaxed);
threads_.store(nullptr, std::memory_order_relaxed);
#ifndef NDEBUG
GOOGLE_CHECK_EQ(was_message_owned, IsMessageOwned());
#endif // NDEBUG
}
void ThreadSafeArena::SetInitialBlock(void* mem, size_t size) {
SerialArena* serial = SerialArena::New({mem, size}, &thread_cache());
serial->set_next(NULL);
threads_.store(serial, std::memory_order_relaxed);
CacheSerialArena(serial);
}
ThreadSafeArena::~ThreadSafeArena() {
// Have to do this in a first pass, because some of the destructors might
// refer to memory in other blocks.
CleanupList();
size_t space_allocated = 0;
auto mem = Free(&space_allocated);
// Policy is about to get deleted.
auto* p = alloc_policy_.get();
ArenaMetricsCollector* collector = p ? p->metrics_collector : nullptr;
if (alloc_policy_.is_user_owned_initial_block()) {
space_allocated += mem.size;
} else {
GetDeallocator(alloc_policy_.get(), &space_allocated)(mem);
}
if (collector) collector->OnDestroy(space_allocated);
}
SerialArena::Memory ThreadSafeArena::Free(size_t* space_allocated) {
SerialArena::Memory mem = {nullptr, 0};
auto deallocator = GetDeallocator(alloc_policy_.get(), space_allocated);
PerSerialArena([deallocator, &mem](SerialArena* a) {
if (mem.ptr) deallocator(mem);
mem = a->Free(deallocator);
});
return mem;
}
uint64_t ThreadSafeArena::Reset() {
// Have to do this in a first pass, because some of the destructors might
// refer to memory in other blocks.
CleanupList();
// Discard all blocks except the special block (if present).
size_t space_allocated = 0;
auto mem = Free(&space_allocated);
AllocationPolicy* policy = alloc_policy_.get();
if (policy) {
auto saved_policy = *policy;
if (alloc_policy_.is_user_owned_initial_block()) {
space_allocated += mem.size;
} else {
GetDeallocator(alloc_policy_.get(), &space_allocated)(mem);
mem.ptr = nullptr;
mem.size = 0;
}
ArenaMetricsCollector* collector = saved_policy.metrics_collector;
if (collector) collector->OnReset(space_allocated);
InitializeWithPolicy(mem.ptr, mem.size, saved_policy);
} else {
GOOGLE_DCHECK(!alloc_policy_.should_record_allocs());
// Nullptr policy
if (alloc_policy_.is_user_owned_initial_block()) {
space_allocated += mem.size;
InitializeFrom(mem.ptr, mem.size);
} else {
GetDeallocator(alloc_policy_.get(), &space_allocated)(mem);
Init();
}
}
return space_allocated;
}
std::pair<void*, SerialArena::CleanupNode*>
ThreadSafeArena::AllocateAlignedWithCleanup(size_t n,
const std::type_info* type) {
SerialArena* arena;
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
GetSerialArenaFast(&arena))) {
return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get());
} else {
return AllocateAlignedWithCleanupFallback(n, type);
}
}
void ThreadSafeArena::AddCleanup(void* elem, void (*cleanup)(void*)) {
SerialArena* arena;
if (PROTOBUF_PREDICT_FALSE(!GetSerialArenaFast(&arena))) {
arena = GetSerialArenaFallback(&thread_cache());
}
arena->AddCleanup(elem, cleanup, AllocPolicy());
}
PROTOBUF_NOINLINE
void* ThreadSafeArena::AllocateAlignedFallback(size_t n,
const std::type_info* type) {
if (alloc_policy_.should_record_allocs()) {
alloc_policy_.RecordAlloc(type, n);
SerialArena* arena;
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
return arena->AllocateAligned(n, alloc_policy_.get());
}
}
return GetSerialArenaFallback(&thread_cache())
->AllocateAligned(n, alloc_policy_.get());
}
PROTOBUF_NOINLINE
std::pair<void*, SerialArena::CleanupNode*>
ThreadSafeArena::AllocateAlignedWithCleanupFallback(
size_t n, const std::type_info* type) {
if (alloc_policy_.should_record_allocs()) {
alloc_policy_.RecordAlloc(type, n);
SerialArena* arena;
if (GetSerialArenaFast(&arena)) {
return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get());
}
}
return GetSerialArenaFallback(&thread_cache())
->AllocateAlignedWithCleanup(n, alloc_policy_.get());
}
uint64_t ThreadSafeArena::SpaceAllocated() const {
SerialArena* serial = threads_.load(std::memory_order_acquire);
uint64_t res = 0;
for (; serial; serial = serial->next()) {
res += serial->SpaceAllocated();
}
return res;
}
uint64_t ThreadSafeArena::SpaceUsed() const {
SerialArena* serial = threads_.load(std::memory_order_acquire);
uint64_t space_used = 0;
for (; serial; serial = serial->next()) {
space_used += serial->SpaceUsed();
}
return space_used - (alloc_policy_.get() ? sizeof(AllocationPolicy) : 0);
}
void ThreadSafeArena::CleanupList() {
PerSerialArena([](SerialArena* a) { a->CleanupList(); });
}
PROTOBUF_NOINLINE
SerialArena* ThreadSafeArena::GetSerialArenaFallback(void* me) {
// Look for this SerialArena in our linked list.
SerialArena* serial = threads_.load(std::memory_order_acquire);
for (; serial; serial = serial->next()) {
if (serial->owner() == me) {
break;
}
}
if (!serial) {
// This thread doesn't have any SerialArena, which also means it doesn't
// have any blocks yet. So we'll allocate its first block now.
serial = SerialArena::New(
AllocateMemory(alloc_policy_.get(), 0, kSerialArenaSize), me);
SerialArena* head = threads_.load(std::memory_order_relaxed);
do {
serial->set_next(head);
} while (!threads_.compare_exchange_weak(
head, serial, std::memory_order_release, std::memory_order_relaxed));
}
CacheSerialArena(serial);
return serial;
}
} // namespace internal
PROTOBUF_FUNC_ALIGN(32)
void* Arena::AllocateAlignedNoHook(size_t n) {
return impl_.AllocateAligned(n, nullptr);
}
PROTOBUF_FUNC_ALIGN(32)
void* Arena::AllocateAlignedWithHook(size_t n, const std::type_info* type) {
return impl_.AllocateAligned(n, type);
}
PROTOBUF_FUNC_ALIGN(32)
std::pair<void*, internal::SerialArena::CleanupNode*>
Arena::AllocateAlignedWithCleanup(size_t n, const std::type_info* type) {
return impl_.AllocateAlignedWithCleanup(n, type);
}
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>

821
r5dev/thirdparty/protobuf/arena.h vendored Normal file
View File

@ -0,0 +1,821 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This file defines an Arena allocator for better allocation performance.
#ifndef GOOGLE_PROTOBUF_ARENA_H__
#define GOOGLE_PROTOBUF_ARENA_H__
#include <limits>
#include <type_traits>
#include <utility>
#ifdef max
#undef max // Visual Studio defines this macro
#endif
#if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS
// Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
#include <exception>
#include <typeinfo>
namespace std {
using type_info = ::type_info;
}
#else
#include <typeinfo>
#endif
#include <type_traits>
#include <thirdparty/protobuf/arena_impl.h>
#include <thirdparty/protobuf/port.h>
#include <thirdparty/protobuf/port_def.inc>
#ifdef SWIG
#error "You cannot SWIG proto headers"
#endif
namespace google {
namespace protobuf {
struct ArenaOptions; // defined below
class Arena; // defined below
class Message; // defined in message.h
class MessageLite;
template <typename Key, typename T>
class Map;
namespace arena_metrics {
void EnableArenaMetrics(ArenaOptions* options);
} // namespace arena_metrics
namespace TestUtil {
class ReflectionTester; // defined in test_util.h
} // namespace TestUtil
namespace internal {
struct ArenaStringPtr; // defined in arenastring.h
class InlinedStringField; // defined in inlined_string_field.h
class LazyField; // defined in lazy_field.h
class EpsCopyInputStream; // defined in parse_context.h
template <typename Type>
class GenericTypeHandler; // defined in repeated_field.h
inline PROTOBUF_ALWAYS_INLINE
void* AlignTo(void* ptr, size_t align) {
return reinterpret_cast<void*>(
(reinterpret_cast<uintptr_t>(ptr) + align - 1) & (~align + 1));
}
// Templated cleanup methods.
template <typename T>
void arena_destruct_object(void* object) {
reinterpret_cast<T*>(object)->~T();
}
template <bool destructor_skippable, typename T>
struct ObjectDestructor {
constexpr static void (*destructor)(void*) = &arena_destruct_object<T>;
};
template <typename T>
struct ObjectDestructor<true, T> {
constexpr static void (*destructor)(void*) = nullptr;
};
template <typename T>
void arena_delete_object(void* object) {
delete reinterpret_cast<T*>(object);
}
} // namespace internal
// ArenaOptions provides optional additional parameters to arena construction
// that control its block-allocation behavior.
struct ArenaOptions {
// This defines the size of the first block requested from the system malloc.
// Subsequent block sizes will increase in a geometric series up to a maximum.
size_t start_block_size;
// This defines the maximum block size requested from system malloc (unless an
// individual arena allocation request occurs with a size larger than this
// maximum). Requested block sizes increase up to this value, then remain
// here.
size_t max_block_size;
// An initial block of memory for the arena to use, or NULL for none. If
// provided, the block must live at least as long as the arena itself. The
// creator of the Arena retains ownership of the block after the Arena is
// destroyed.
char* initial_block;
// The size of the initial block, if provided.
size_t initial_block_size;
// A function pointer to an alloc method that returns memory blocks of size
// requested. By default, it contains a ptr to the malloc function.
//
// NOTE: block_alloc and dealloc functions are expected to behave like
// malloc and free, including Asan poisoning.
void* (*block_alloc)(size_t);
// A function pointer to a dealloc method that takes ownership of the blocks
// from the arena. By default, it contains a ptr to a wrapper function that
// calls free.
void (*block_dealloc)(void*, size_t);
ArenaOptions()
: start_block_size(internal::AllocationPolicy::kDefaultStartBlockSize),
max_block_size(internal::AllocationPolicy::kDefaultMaxBlockSize),
initial_block(NULL),
initial_block_size(0),
block_alloc(nullptr),
block_dealloc(nullptr),
make_metrics_collector(nullptr) {}
private:
// If make_metrics_collector is not nullptr, it will be called at Arena init
// time. It may return a pointer to a collector instance that will be notified
// of interesting events related to the arena.
internal::ArenaMetricsCollector* (*make_metrics_collector)();
internal::ArenaMetricsCollector* MetricsCollector() const {
return make_metrics_collector ? (*make_metrics_collector)() : nullptr;
}
internal::AllocationPolicy AllocationPolicy() const {
internal::AllocationPolicy res;
res.start_block_size = start_block_size;
res.max_block_size = max_block_size;
res.block_alloc = block_alloc;
res.block_dealloc = block_dealloc;
res.metrics_collector = MetricsCollector();
return res;
}
friend void arena_metrics::EnableArenaMetrics(ArenaOptions*);
friend class Arena;
friend class ArenaOptionsTestFriend;
};
// Support for non-RTTI environments. (The metrics hooks API uses type
// information.)
#if PROTOBUF_RTTI
#define RTTI_TYPE_ID(type) (&typeid(type))
#else
#define RTTI_TYPE_ID(type) (NULL)
#endif
// Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
// with new/delete, and improves performance by aggregating allocations into
// larger blocks and freeing allocations all at once. Protocol messages are
// allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and
// are automatically freed when the arena is destroyed.
//
// This is a thread-safe implementation: multiple threads may allocate from the
// arena concurrently. Destruction is not thread-safe and the destructing
// thread must synchronize with users of the arena first.
//
// An arena provides two allocation interfaces: CreateMessage<T>, which works
// for arena-enabled proto2 message types as well as other types that satisfy
// the appropriate protocol (described below), and Create<T>, which works for
// any arbitrary type T. CreateMessage<T> is better when the type T supports it,
// because this interface (i) passes the arena pointer to the created object so
// that its sub-objects and internal allocations can use the arena too, and (ii)
// elides the object's destructor call when possible. Create<T> does not place
// any special requirements on the type T, and will invoke the object's
// destructor when the arena is destroyed.
//
// The arena message allocation protocol, required by
// CreateMessage<T>(Arena* arena, Args&&... args), is as follows:
//
// - The type T must have (at least) two constructors: a constructor callable
// with `args` (without `arena`), called when a T is allocated on the heap;
// and a constructor callable with `Arena* arena, Args&&... args`, called when
// a T is allocated on an arena. If the second constructor is called with a
// NULL arena pointer, it must be equivalent to invoking the first
// (`args`-only) constructor.
//
// - The type T must have a particular type trait: a nested type
// |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
// such type trait exists, then the instantiation CreateMessage<T> will fail
// to compile.
//
// - The type T *may* have the type trait |DestructorSkippable_|. If this type
// trait is present in the type, then its destructor will not be called if and
// only if it was passed a non-NULL arena pointer. If this type trait is not
// present on the type, then its destructor is always called when the
// containing arena is destroyed.
//
// This protocol is implemented by all arena-enabled proto2 message classes as
// well as protobuf container types like RepeatedPtrField and Map. The protocol
// is internal to protobuf and is not guaranteed to be stable. Non-proto types
// should not rely on this protocol.
class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
public:
// Default constructor with sensible default options, tuned for average
// use-cases.
inline Arena() : impl_() {}
// Construct an arena with default options, except for the supplied
// initial block. It is more efficient to use this constructor
// instead of passing ArenaOptions if the only configuration needed
// by the caller is supplying an initial block.
inline Arena(char* initial_block, size_t initial_block_size)
: impl_(initial_block, initial_block_size) {}
// Arena constructor taking custom options. See ArenaOptions above for
// descriptions of the options available.
explicit Arena(const ArenaOptions& options)
: impl_(options.initial_block, options.initial_block_size,
options.AllocationPolicy()) {}
// Block overhead. Use this as a guide for how much to over-allocate the
// initial block if you want an allocation of size N to fit inside it.
//
// WARNING: if you allocate multiple objects, it is difficult to guarantee
// that a series of allocations will fit in the initial block, especially if
// Arena changes its alignment guarantees in the future!
static const size_t kBlockOverhead =
internal::ThreadSafeArena::kBlockHeaderSize +
internal::ThreadSafeArena::kSerialArenaSize;
inline ~Arena() {}
// TODO(protobuf-team): Fix callers to use constructor and delete this method.
void Init(const ArenaOptions&) {}
// API to create proto2 message objects on the arena. If the arena passed in
// is NULL, then a heap allocated object is returned. Type T must be a message
// defined in a .proto file with cc_enable_arenas set to true, otherwise a
// compilation error will occur.
//
// RepeatedField and RepeatedPtrField may also be instantiated directly on an
// arena with this method.
//
// This function also accepts any type T that satisfies the arena message
// allocation protocol, documented above.
template <typename T, typename... Args>
PROTOBUF_ALWAYS_INLINE static T* CreateMessage(Arena* arena, Args&&... args) {
static_assert(
InternalHelper<T>::is_arena_constructable::value,
"CreateMessage can only construct types that are ArenaConstructable");
// We must delegate to CreateMaybeMessage() and NOT CreateMessageInternal()
// because protobuf generated classes specialize CreateMaybeMessage() and we
// need to use that specialization for code size reasons.
return Arena::CreateMaybeMessage<T>(arena, static_cast<Args&&>(args)...);
}
// API to create any objects on the arena. Note that only the object will
// be created on the arena; the underlying ptrs (in case of a proto2 message)
// will be still heap allocated. Proto messages should usually be allocated
// with CreateMessage<T>() instead.
//
// Note that even if T satisfies the arena message construction protocol
// (InternalArenaConstructable_ trait and optional DestructorSkippable_
// trait), as described above, this function does not follow the protocol;
// instead, it treats T as a black-box type, just as if it did not have these
// traits. Specifically, T's constructor arguments will always be only those
// passed to Create<T>() -- no additional arena pointer is implicitly added.
// Furthermore, the destructor will always be called at arena destruction time
// (unless the destructor is trivial). Hence, from T's point of view, it is as
// if the object were allocated on the heap (except that the underlying memory
// is obtained from the arena).
template <typename T, typename... Args>
PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) {
return CreateInternal<T>(arena, std::is_convertible<T*, MessageLite*>(),
static_cast<Args&&>(args)...);
}
// Create an array of object type T on the arena *without* invoking the
// constructor of T. If `arena` is null, then the return value should be freed
// with `delete[] x;` (or `::operator delete[](x);`).
// To ensure safe uses, this function checks at compile time
// (when compiled as C++11) that T is trivially default-constructible and
// trivially destructible.
template <typename T>
PROTOBUF_NDEBUG_INLINE static T* CreateArray(Arena* arena,
size_t num_elements) {
static_assert(std::is_trivial<T>::value,
"CreateArray requires a trivially constructible type");
static_assert(std::is_trivially_destructible<T>::value,
"CreateArray requires a trivially destructible type");
GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
<< "Requested size is too large to fit into size_t.";
if (arena == NULL) {
return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
} else {
return arena->CreateInternalRawArray<T>(num_elements);
}
}
// The following are routines are for monitoring. They will approximate the
// total sum allocated and used memory, but the exact value is an
// implementation deal. For instance allocated space depends on growth
// policies. Do not use these in unit tests.
// Returns the total space allocated by the arena, which is the sum of the
// sizes of the underlying blocks.
uint64_t SpaceAllocated() const { return impl_.SpaceAllocated(); }
// Returns the total space used by the arena. Similar to SpaceAllocated but
// does not include free space and block overhead. The total space returned
// may not include space used by other threads executing concurrently with
// the call to this method.
uint64_t SpaceUsed() const { return impl_.SpaceUsed(); }
// Frees all storage allocated by this arena after calling destructors
// registered with OwnDestructor() and freeing objects registered with Own().
// Any objects allocated on this arena are unusable after this call. It also
// returns the total space used by the arena which is the sums of the sizes
// of the allocated blocks. This method is not thread-safe.
uint64_t Reset() { return impl_.Reset(); }
// Adds |object| to a list of heap-allocated objects to be freed with |delete|
// when the arena is destroyed or reset.
template <typename T>
PROTOBUF_ALWAYS_INLINE void Own(T* object) {
OwnInternal(object, std::is_convertible<T*, MessageLite*>());
}
// Adds |object| to a list of objects whose destructors will be manually
// called when the arena is destroyed or reset. This differs from Own() in
// that it does not free the underlying memory with |delete|; hence, it is
// normally only used for objects that are placement-newed into
// arena-allocated memory.
template <typename T>
PROTOBUF_ALWAYS_INLINE void OwnDestructor(T* object) {
if (object != NULL) {
impl_.AddCleanup(object, &internal::arena_destruct_object<T>);
}
}
// Adds a custom member function on an object to the list of destructors that
// will be manually called when the arena is destroyed or reset. This differs
// from OwnDestructor() in that any member function may be specified, not only
// the class destructor.
PROTOBUF_ALWAYS_INLINE void OwnCustomDestructor(void* object,
void (*destruct)(void*)) {
impl_.AddCleanup(object, destruct);
}
// Retrieves the arena associated with |value| if |value| is an arena-capable
// message, or NULL otherwise. If possible, the call resolves at compile time.
// Note that we can often devirtualize calls to `value->GetArena()` so usually
// calling this method is unnecessary.
template <typename T>
PROTOBUF_ALWAYS_INLINE static Arena* GetArena(const T* value) {
return GetArenaInternal(value);
}
template <typename T>
class InternalHelper {
public:
// Provides access to protected GetOwningArena to generated messages.
static Arena* GetOwningArena(const T* p) { return p->GetOwningArena(); }
// Provides access to protected GetArenaForAllocation to generated messages.
static Arena* GetArenaForAllocation(const T* p) {
return GetArenaForAllocationInternal(
p, std::is_convertible<T*, MessageLite*>());
}
// Creates message-owned arena.
static Arena* CreateMessageOwnedArena() {
return new Arena(internal::MessageOwned{});
}
// Checks whether the given arena is message-owned.
static bool IsMessageOwnedArena(Arena* arena) {
return arena->IsMessageOwned();
}
private:
static Arena* GetArenaForAllocationInternal(
const T* p, std::true_type /*is_derived_from<MessageLite>*/) {
return p->GetArenaForAllocation();
}
static Arena* GetArenaForAllocationInternal(
const T* p, std::false_type /*is_derived_from<MessageLite>*/) {
return GetArenaForAllocationForNonMessage(
p, typename is_arena_constructable::type());
}
static Arena* GetArenaForAllocationForNonMessage(
const T* p, std::true_type /*is_arena_constructible*/) {
return p->GetArena();
}
static Arena* GetArenaForAllocationForNonMessage(
const T* p, std::false_type /*is_arena_constructible*/) {
return GetArenaForAllocationForNonMessageNonArenaConstructible(
p, typename has_get_arena::type());
}
static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
const T* p, std::true_type /*has_get_arena*/) {
return p->GetArena();
}
static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
const T* /* p */, std::false_type /*has_get_arena*/) {
return nullptr;
}
template <typename U>
static char DestructorSkippable(const typename U::DestructorSkippable_*);
template <typename U>
static double DestructorSkippable(...);
typedef std::integral_constant<
bool, sizeof(DestructorSkippable<T>(static_cast<const T*>(0))) ==
sizeof(char) ||
std::is_trivially_destructible<T>::value>
is_destructor_skippable;
template <typename U>
static char ArenaConstructable(
const typename U::InternalArenaConstructable_*);
template <typename U>
static double ArenaConstructable(...);
typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>(
static_cast<const T*>(0))) ==
sizeof(char)>
is_arena_constructable;
template <typename U,
typename std::enable_if<
std::is_same<Arena*, decltype(std::declval<const U>()
.GetArena())>::value,
int>::type = 0>
static char HasGetArena(decltype(&U::GetArena));
template <typename U>
static double HasGetArena(...);
typedef std::integral_constant<bool, sizeof(HasGetArena<T>(nullptr)) ==
sizeof(char)>
has_get_arena;
template <typename... Args>
static T* Construct(void* ptr, Args&&... args) {
return new (ptr) T(static_cast<Args&&>(args)...);
}
static inline PROTOBUF_ALWAYS_INLINE T* New() {
return new T(nullptr);
}
static Arena* GetArena(const T* p) { return p->GetArena(); }
friend class Arena;
friend class TestUtil::ReflectionTester;
};
// Helper typetraits that indicates support for arenas in a type T at compile
// time. This is public only to allow construction of higher-level templated
// utilities.
//
// is_arena_constructable<T>::value is true if the message type T has arena
// support enabled, and false otherwise.
//
// is_destructor_skippable<T>::value is true if the message type T has told
// the arena that it is safe to skip the destructor, and false otherwise.
//
// This is inside Arena because only Arena has the friend relationships
// necessary to see the underlying generated code traits.
template <typename T>
struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {};
template <typename T>
struct is_destructor_skippable : InternalHelper<T>::is_destructor_skippable {
};
private:
internal::ThreadSafeArena impl_;
template <typename T>
struct has_get_arena : InternalHelper<T>::has_get_arena {};
// Constructor solely used by message-owned arena.
inline Arena(internal::MessageOwned) : impl_(internal::MessageOwned{}) {}
// Checks whether this arena is message-owned.
PROTOBUF_ALWAYS_INLINE bool IsMessageOwned() const {
return impl_.IsMessageOwned();
}
template <typename T, typename... Args>
PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena,
Args&&... args) {
static_assert(
InternalHelper<T>::is_arena_constructable::value,
"CreateMessage can only construct types that are ArenaConstructable");
if (arena == NULL) {
return new T(nullptr, static_cast<Args&&>(args)...);
} else {
return arena->DoCreateMessage<T>(static_cast<Args&&>(args)...);
}
}
// This specialization for no arguments is necessary, because its behavior is
// slightly different. When the arena pointer is nullptr, it calls T()
// instead of T(nullptr).
template <typename T>
PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena) {
static_assert(
InternalHelper<T>::is_arena_constructable::value,
"CreateMessage can only construct types that are ArenaConstructable");
if (arena == NULL) {
// Generated arena constructor T(Arena*) is protected. Call via
// InternalHelper.
return InternalHelper<T>::New();
} else {
return arena->DoCreateMessage<T>();
}
}
// Allocate and also optionally call collector with the allocated type info
// when allocation recording is enabled.
PROTOBUF_NDEBUG_INLINE void* AllocateInternal(size_t size, size_t align,
void (*destructor)(void*),
const std::type_info* type) {
// Monitor allocation if needed.
if (destructor == nullptr) {
return AllocateAlignedWithHook(size, align, type);
} else {
if (align <= 8) {
auto res = AllocateAlignedWithCleanup(internal::AlignUpTo8(size), type);
res.second->elem = res.first;
res.second->cleanup = destructor;
return res.first;
} else {
auto res = AllocateAlignedWithCleanup(size + align - 8, type);
auto ptr = internal::AlignTo(res.first, align);
res.second->elem = ptr;
res.second->cleanup = destructor;
return ptr;
}
}
}
// CreateMessage<T> requires that T supports arenas, but this private method
// works whether or not T supports arenas. These are not exposed to user code
// as it can cause confusing API usages, and end up having double free in
// user code. These are used only internally from LazyField and Repeated
// fields, since they are designed to work in all mode combinations.
template <typename Msg, typename... Args>
PROTOBUF_ALWAYS_INLINE static Msg* DoCreateMaybeMessage(Arena* arena,
std::true_type,
Args&&... args) {
return CreateMessageInternal<Msg>(arena, std::forward<Args>(args)...);
}
template <typename T, typename... Args>
PROTOBUF_ALWAYS_INLINE static T* DoCreateMaybeMessage(Arena* arena,
std::false_type,
Args&&... args) {
return Create<T>(arena, std::forward<Args>(args)...);
}
template <typename T, typename... Args>
PROTOBUF_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena,
Args&&... args) {
return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(),
std::forward<Args>(args)...);
}
// Just allocate the required size for the given type assuming the
// type has a trivial constructor.
template <typename T>
PROTOBUF_NDEBUG_INLINE T* CreateInternalRawArray(size_t num_elements) {
GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
<< "Requested size is too large to fit into size_t.";
// We count on compiler to realize that if sizeof(T) is a multiple of
// 8 AlignUpTo can be elided.
const size_t n = sizeof(T) * num_elements;
return static_cast<T*>(
AllocateAlignedWithHook(n, alignof(T), RTTI_TYPE_ID(T)));
}
template <typename T, typename... Args>
PROTOBUF_NDEBUG_INLINE T* DoCreateMessage(Args&&... args) {
return InternalHelper<T>::Construct(
AllocateInternal(sizeof(T), alignof(T),
internal::ObjectDestructor<
InternalHelper<T>::is_destructor_skippable::value,
T>::destructor,
RTTI_TYPE_ID(T)),
this, std::forward<Args>(args)...);
}
// CreateInArenaStorage is used to implement map field. Without it,
// Map need to call generated message's protected arena constructor,
// which needs to declare Map as friend of generated message.
template <typename T, typename... Args>
static void CreateInArenaStorage(T* ptr, Arena* arena, Args&&... args) {
CreateInArenaStorageInternal(ptr, arena,
typename is_arena_constructable<T>::type(),
std::forward<Args>(args)...);
if (arena != nullptr) {
RegisterDestructorInternal(
ptr, arena,
typename InternalHelper<T>::is_destructor_skippable::type());
}
}
template <typename T, typename... Args>
static void CreateInArenaStorageInternal(T* ptr, Arena* arena,
std::true_type, Args&&... args) {
InternalHelper<T>::Construct(ptr, arena, std::forward<Args>(args)...);
}
template <typename T, typename... Args>
static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */,
std::false_type, Args&&... args) {
new (ptr) T(std::forward<Args>(args)...);
}
template <typename T>
static void RegisterDestructorInternal(T* /* ptr */, Arena* /* arena */,
std::true_type) {}
template <typename T>
static void RegisterDestructorInternal(T* ptr, Arena* arena,
std::false_type) {
arena->OwnDestructor(ptr);
}
// These implement Create(). The second parameter has type 'true_type' if T is
// a subtype of Message and 'false_type' otherwise.
template <typename T, typename... Args>
PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::true_type,
Args&&... args) {
if (arena == nullptr) {
return new T(std::forward<Args>(args)...);
} else {
auto destructor =
internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
T>::destructor;
T* result =
new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
RTTI_TYPE_ID(T)))
T(std::forward<Args>(args)...);
return result;
}
}
template <typename T, typename... Args>
PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::false_type,
Args&&... args) {
if (arena == nullptr) {
return new T(std::forward<Args>(args)...);
} else {
auto destructor =
internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
T>::destructor;
return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
RTTI_TYPE_ID(T)))
T(std::forward<Args>(args)...);
}
}
// These implement Own(), which registers an object for deletion (destructor
// call and operator delete()). The second parameter has type 'true_type' if T
// is a subtype of Message and 'false_type' otherwise. Collapsing
// all template instantiations to one for generic Message reduces code size,
// using the virtual destructor instead.
template <typename T>
PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) {
if (object != NULL) {
impl_.AddCleanup(object, &internal::arena_delete_object<MessageLite>);
}
}
template <typename T>
PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::false_type) {
if (object != NULL) {
impl_.AddCleanup(object, &internal::arena_delete_object<T>);
}
}
// Implementation for GetArena(). Only message objects with
// InternalArenaConstructable_ tags can be associated with an arena, and such
// objects must implement a GetArena() method.
template <typename T, typename std::enable_if<
is_arena_constructable<T>::value, int>::type = 0>
PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
return InternalHelper<T>::GetArena(value);
}
template <typename T,
typename std::enable_if<!is_arena_constructable<T>::value &&
has_get_arena<T>::value,
int>::type = 0>
PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
return value->GetArena();
}
template <typename T,
typename std::enable_if<!is_arena_constructable<T>::value &&
!has_get_arena<T>::value,
int>::type = 0>
PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
(void)value;
return nullptr;
}
template <typename T>
PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArena(const T* value) {
return GetOwningArenaInternal(
value, std::is_convertible<T*, MessageLite*>());
}
// Implementation for GetOwningArena(). All and only message objects have
// GetOwningArena() method.
template <typename T>
PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArenaInternal(
const T* value, std::true_type) {
return InternalHelper<T>::GetOwningArena(value);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArenaInternal(
const T* /* value */, std::false_type) {
return nullptr;
}
// For friends of arena.
void* AllocateAligned(size_t n, size_t align = 8) {
if (align <= 8) {
return AllocateAlignedNoHook(internal::AlignUpTo8(n));
} else {
// We are wasting space by over allocating align - 8 bytes. Compared
// to a dedicated function that takes current alignment in consideration.
// Such a scheme would only waste (align - 8)/2 bytes on average, but
// requires a dedicated function in the outline arena allocation
// functions. Possibly re-evaluate tradeoffs later.
return internal::AlignTo(AllocateAlignedNoHook(n + align - 8), align);
}
}
void* AllocateAlignedWithHook(size_t n, size_t align,
const std::type_info* type) {
if (align <= 8) {
return AllocateAlignedWithHook(internal::AlignUpTo8(n), type);
} else {
// We are wasting space by over allocating align - 8 bytes. Compared
// to a dedicated function that takes current alignment in consideration.
// Such a schemee would only waste (align - 8)/2 bytes on average, but
// requires a dedicated function in the outline arena allocation
// functions. Possibly re-evaluate tradeoffs later.
return internal::AlignTo(AllocateAlignedWithHook(n + align - 8, type),
align);
}
}
void* AllocateAlignedNoHook(size_t n);
void* AllocateAlignedWithHook(size_t n, const std::type_info* type);
std::pair<void*, internal::SerialArena::CleanupNode*>
AllocateAlignedWithCleanup(size_t n, const std::type_info* type);
template <typename Type>
friend class internal::GenericTypeHandler;
friend struct internal::ArenaStringPtr; // For AllocateAligned.
friend class internal::InlinedStringField; // For AllocateAligned.
friend class internal::LazyField; // For CreateMaybeMessage.
friend class internal::EpsCopyInputStream; // For parser performance
friend class MessageLite;
template <typename Key, typename T>
friend class Map;
};
// Defined above for supporting environments without RTTI.
#undef RTTI_TYPE_ID
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_ARENA_H__

562
r5dev/thirdparty/protobuf/arena_impl.h vendored Normal file
View File

@ -0,0 +1,562 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This file defines an Arena allocator for better allocation performance.
#ifndef GOOGLE_PROTOBUF_ARENA_IMPL_H__
#define GOOGLE_PROTOBUF_ARENA_IMPL_H__
#include <atomic>
#include <limits>
#include <typeinfo>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/stubs/logging.h>
#ifdef ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif // ADDRESS_SANITIZER
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace internal {
inline constexpr size_t AlignUpTo8(size_t n) {
// Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
return (n + 7) & static_cast<size_t>(-8);
}
using LifecycleIdAtomic = uint64_t;
// MetricsCollector collects stats for a particular arena.
class PROTOBUF_EXPORT ArenaMetricsCollector {
public:
ArenaMetricsCollector(bool record_allocs) : record_allocs_(record_allocs) {}
// Invoked when the arena is about to be destroyed. This method will
// typically finalize any metric collection and delete the collector.
// space_allocated is the space used by the arena.
virtual void OnDestroy(uint64_t space_allocated) = 0;
// OnReset() is called when the associated arena is reset.
// space_allocated is the space used by the arena just before the reset.
virtual void OnReset(uint64_t space_allocated) = 0;
// OnAlloc is called when an allocation happens.
// type_info is promised to be static - its lifetime extends to
// match program's lifetime (It is given by typeid operator).
// Note: typeid(void) will be passed as allocated_type every time we
// intentionally want to avoid monitoring an allocation. (i.e. internal
// allocations for managing the arena)
virtual void OnAlloc(const std::type_info* allocated_type,
uint64_t alloc_size) = 0;
// Does OnAlloc() need to be called? If false, metric collection overhead
// will be reduced since we will not do extra work per allocation.
bool RecordAllocs() { return record_allocs_; }
protected:
// This class is destructed by the call to OnDestroy().
~ArenaMetricsCollector() = default;
const bool record_allocs_;
};
struct AllocationPolicy {
static constexpr size_t kDefaultStartBlockSize = 256;
static constexpr size_t kDefaultMaxBlockSize = 8192;
size_t start_block_size = kDefaultStartBlockSize;
size_t max_block_size = kDefaultMaxBlockSize;
void* (*block_alloc)(size_t) = nullptr;
void (*block_dealloc)(void*, size_t) = nullptr;
ArenaMetricsCollector* metrics_collector = nullptr;
bool IsDefault() const {
return start_block_size == kDefaultMaxBlockSize &&
max_block_size == kDefaultMaxBlockSize && block_alloc == nullptr &&
block_dealloc == nullptr && metrics_collector == nullptr;
}
};
// Tagged pointer to an AllocationPolicy.
class TaggedAllocationPolicyPtr {
public:
constexpr TaggedAllocationPolicyPtr() : policy_(0) {}
explicit TaggedAllocationPolicyPtr(AllocationPolicy* policy)
: policy_(reinterpret_cast<uintptr_t>(policy)) {}
void set_policy(AllocationPolicy* policy) {
auto bits = policy_ & kTagsMask;
policy_ = reinterpret_cast<uintptr_t>(policy) | bits;
}
AllocationPolicy* get() {
return reinterpret_cast<AllocationPolicy*>(policy_ & kPtrMask);
}
const AllocationPolicy* get() const {
return reinterpret_cast<const AllocationPolicy*>(policy_ & kPtrMask);
}
AllocationPolicy& operator*() { return *get(); }
const AllocationPolicy& operator*() const { return *get(); }
AllocationPolicy* operator->() { return get(); }
const AllocationPolicy* operator->() const { return get(); }
bool is_user_owned_initial_block() const {
return static_cast<bool>(get_mask<kUserOwnedInitialBlock>());
}
void set_is_user_owned_initial_block(bool v) {
set_mask<kUserOwnedInitialBlock>(v);
}
bool should_record_allocs() const {
return static_cast<bool>(get_mask<kRecordAllocs>());
}
void set_should_record_allocs(bool v) { set_mask<kRecordAllocs>(v); }
uintptr_t get_raw() const { return policy_; }
inline void RecordAlloc(const std::type_info* allocated_type,
size_t n) const {
get()->metrics_collector->OnAlloc(allocated_type, n);
}
private:
enum : uintptr_t {
kUserOwnedInitialBlock = 1,
kRecordAllocs = 2,
};
static constexpr uintptr_t kTagsMask = 7;
static constexpr uintptr_t kPtrMask = ~kTagsMask;
template <uintptr_t kMask>
uintptr_t get_mask() const {
return policy_ & kMask;
}
template <uintptr_t kMask>
void set_mask(bool v) {
if (v) {
policy_ |= kMask;
} else {
policy_ &= ~kMask;
}
}
uintptr_t policy_;
};
// A simple arena allocator. Calls to allocate functions must be properly
// serialized by the caller, hence this class cannot be used as a general
// purpose allocator in a multi-threaded program. It serves as a building block
// for ThreadSafeArena, which provides a thread-safe arena allocator.
//
// This class manages
// 1) Arena bump allocation + owning memory blocks.
// 2) Maintaining a cleanup list.
// It delagetes the actual memory allocation back to ThreadSafeArena, which
// contains the information on block growth policy and backing memory allocation
// used.
class PROTOBUF_EXPORT SerialArena {
public:
struct Memory {
void* ptr;
size_t size;
};
// Node contains the ptr of the object to be cleaned up and the associated
// cleanup function ptr.
struct CleanupNode {
void* elem; // Pointer to the object to be cleaned up.
void (*cleanup)(void*); // Function pointer to the destructor or deleter.
};
void CleanupList();
uint64_t SpaceAllocated() const {
return space_allocated_.load(std::memory_order_relaxed);
}
uint64_t SpaceUsed() const;
bool HasSpace(size_t n) { return n <= static_cast<size_t>(limit_ - ptr_); }
void* AllocateAligned(size_t n, const AllocationPolicy* policy) {
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
GOOGLE_DCHECK_GE(limit_, ptr_);
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) {
return AllocateAlignedFallback(n, policy);
}
return AllocateFromExisting(n);
}
private:
void* AllocateFromExisting(size_t n) {
void* ret = ptr_;
ptr_ += n;
#ifdef ADDRESS_SANITIZER
ASAN_UNPOISON_MEMORY_REGION(ret, n);
#endif // ADDRESS_SANITIZER
return ret;
}
public:
// Allocate space if the current region provides enough space.
bool MaybeAllocateAligned(size_t n, void** out) {
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
GOOGLE_DCHECK_GE(limit_, ptr_);
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false;
*out = AllocateFromExisting(n);
return true;
}
std::pair<void*, CleanupNode*> AllocateAlignedWithCleanup(
size_t n, const AllocationPolicy* policy) {
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
if (PROTOBUF_PREDICT_FALSE(!HasSpace(n + kCleanupSize))) {
return AllocateAlignedWithCleanupFallback(n, policy);
}
return AllocateFromExistingWithCleanupFallback(n);
}
private:
std::pair<void*, CleanupNode*> AllocateFromExistingWithCleanupFallback(
size_t n) {
void* ret = ptr_;
ptr_ += n;
limit_ -= kCleanupSize;
#ifdef ADDRESS_SANITIZER
ASAN_UNPOISON_MEMORY_REGION(ret, n);
ASAN_UNPOISON_MEMORY_REGION(limit_, kCleanupSize);
#endif // ADDRESS_SANITIZER
return CreatePair(ret, reinterpret_cast<CleanupNode*>(limit_));
}
public:
void AddCleanup(void* elem, void (*cleanup)(void*),
const AllocationPolicy* policy) {
auto res = AllocateAlignedWithCleanup(0, policy);
res.second->elem = elem;
res.second->cleanup = cleanup;
}
void* owner() const { return owner_; }
SerialArena* next() const { return next_; }
void set_next(SerialArena* next) { next_ = next; }
private:
friend class ThreadSafeArena;
friend class ArenaBenchmark;
// Creates a new SerialArena inside mem using the remaining memory as for
// future allocations.
static SerialArena* New(SerialArena::Memory mem, void* owner);
// Free SerialArena returning the memory passed in to New
template <typename Deallocator>
Memory Free(Deallocator deallocator);
// Blocks are variable length malloc-ed objects. The following structure
// describes the common header for all blocks.
struct Block {
Block(Block* next, size_t size) : next(next), size(size), start(nullptr) {}
char* Pointer(size_t n) {
GOOGLE_DCHECK(n <= size);
return reinterpret_cast<char*>(this) + n;
}
Block* const next;
const size_t size;
CleanupNode* start;
// data follows
};
void* owner_; // &ThreadCache of this thread;
Block* head_; // Head of linked list of blocks.
SerialArena* next_; // Next SerialArena in this linked list.
size_t space_used_ = 0; // Necessary for metrics.
std::atomic<size_t> space_allocated_;
// Next pointer to allocate from. Always 8-byte aligned. Points inside
// head_ (and head_->pos will always be non-canonical). We keep these
// here to reduce indirection.
char* ptr_;
char* limit_;
// Constructor is private as only New() should be used.
inline SerialArena(Block* b, void* owner);
void* AllocateAlignedFallback(size_t n, const AllocationPolicy* policy);
std::pair<void*, CleanupNode*> AllocateAlignedWithCleanupFallback(
size_t n, const AllocationPolicy* policy);
void AllocateNewBlock(size_t n, const AllocationPolicy* policy);
std::pair<void*, CleanupNode*> CreatePair(void* ptr, CleanupNode* node) {
return {ptr, node};
}
public:
static constexpr size_t kBlockHeaderSize = AlignUpTo8(sizeof(Block));
static constexpr size_t kCleanupSize = AlignUpTo8(sizeof(CleanupNode));
};
// Tag type used to invoke the constructor of message-owned arena.
// Only message-owned arenas use this constructor for creation.
// Such constructors are internal implementation details of the library.
struct MessageOwned {
explicit MessageOwned() = default;
};
// This class provides the core Arena memory allocation library. Different
// implementations only need to implement the public interface below.
// Arena is not a template type as that would only be useful if all protos
// in turn would be templates, which will/cannot happen. However separating
// the memory allocation part from the cruft of the API users expect we can
// use #ifdef the select the best implementation based on hardware / OS.
class PROTOBUF_EXPORT ThreadSafeArena {
public:
ThreadSafeArena() { Init(); }
// Constructor solely used by message-owned arena.
ThreadSafeArena(internal::MessageOwned) : tag_and_id_(kMessageOwnedArena) {
Init();
}
ThreadSafeArena(char* mem, size_t size) { InitializeFrom(mem, size); }
explicit ThreadSafeArena(void* mem, size_t size,
const AllocationPolicy& policy) {
InitializeWithPolicy(mem, size, policy);
}
// Destructor deletes all owned heap allocated objects, and destructs objects
// that have non-trivial destructors, except for proto2 message objects whose
// destructors can be skipped. Also, frees all blocks except the initial block
// if it was passed in.
~ThreadSafeArena();
uint64_t Reset();
uint64_t SpaceAllocated() const;
uint64_t SpaceUsed() const;
void* AllocateAligned(size_t n, const std::type_info* type) {
SerialArena* arena;
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
GetSerialArenaFast(&arena))) {
return arena->AllocateAligned(n, AllocPolicy());
} else {
return AllocateAlignedFallback(n, type);
}
}
// This function allocates n bytes if the common happy case is true and
// returns true. Otherwise does nothing and returns false. This strange
// semantics is necessary to allow callers to program functions that only
// have fallback function calls in tail position. This substantially improves
// code for the happy path.
PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
SerialArena* a;
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
GetSerialArenaFromThreadCache(&a))) {
return a->MaybeAllocateAligned(n, out);
}
return false;
}
std::pair<void*, SerialArena::CleanupNode*> AllocateAlignedWithCleanup(
size_t n, const std::type_info* type);
// Add object pointer and cleanup function pointer to the list.
void AddCleanup(void* elem, void (*cleanup)(void*));
// Checks whether this arena is message-owned.
PROTOBUF_ALWAYS_INLINE bool IsMessageOwned() const {
return tag_and_id_ & kMessageOwnedArena;
}
private:
// Unique for each arena. Changes on Reset().
uint64_t tag_and_id_ = 0;
// The LSB of tag_and_id_ indicates if the arena is message-owned.
enum : uint64_t { kMessageOwnedArena = 1 };
TaggedAllocationPolicyPtr alloc_policy_; // Tagged pointer to AllocPolicy.
// Pointer to a linked list of SerialArena.
std::atomic<SerialArena*> threads_;
std::atomic<SerialArena*> hint_; // Fast thread-local block access
const AllocationPolicy* AllocPolicy() const { return alloc_policy_.get(); }
void InitializeFrom(void* mem, size_t size);
void InitializeWithPolicy(void* mem, size_t size, AllocationPolicy policy);
void* AllocateAlignedFallback(size_t n, const std::type_info* type);
std::pair<void*, SerialArena::CleanupNode*>
AllocateAlignedWithCleanupFallback(size_t n, const std::type_info* type);
void Init();
void SetInitialBlock(void* mem, size_t size);
// Delete or Destruct all objects owned by the arena.
void CleanupList();
inline uint64_t LifeCycleId() const {
return tag_and_id_ & ~kMessageOwnedArena;
}
inline void CacheSerialArena(SerialArena* serial) {
thread_cache().last_serial_arena = serial;
thread_cache().last_lifecycle_id_seen = tag_and_id_;
// TODO(haberman): evaluate whether we would gain efficiency by getting rid
// of hint_. It's the only write we do to ThreadSafeArena in the allocation
// path, which will dirty the cache line.
hint_.store(serial, std::memory_order_release);
}
PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(SerialArena** arena) {
if (GetSerialArenaFromThreadCache(arena)) return true;
// Check whether we own the last accessed SerialArena on this arena. This
// fast path optimizes the case where a single thread uses multiple arenas.
ThreadCache* tc = &thread_cache();
SerialArena* serial = hint_.load(std::memory_order_acquire);
if (PROTOBUF_PREDICT_TRUE(serial != NULL && serial->owner() == tc)) {
*arena = serial;
return true;
}
return false;
}
PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFromThreadCache(
SerialArena** arena) {
// If this thread already owns a block in this arena then try to use that.
// This fast path optimizes the case where multiple threads allocate from
// the same arena.
ThreadCache* tc = &thread_cache();
if (PROTOBUF_PREDICT_TRUE(tc->last_lifecycle_id_seen == tag_and_id_)) {
*arena = tc->last_serial_arena;
return true;
}
return false;
}
SerialArena* GetSerialArenaFallback(void* me);
template <typename Functor>
void PerSerialArena(Functor fn) {
// By omitting an Acquire barrier we ensure that any user code that doesn't
// properly synchronize Reset() or the destructor will throw a TSAN warning.
SerialArena* serial = threads_.load(std::memory_order_relaxed);
for (; serial; serial = serial->next()) fn(serial);
}
// Releases all memory except the first block which it returns. The first
// block might be owned by the user and thus need some extra checks before
// deleting.
SerialArena::Memory Free(size_t* space_allocated);
#ifdef _MSC_VER
#pragma warning(disable : 4324)
#endif
struct alignas(64) ThreadCache {
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
// If we are using the ThreadLocalStorage class to store the ThreadCache,
// then the ThreadCache's default constructor has to be responsible for
// initializing it.
ThreadCache()
: next_lifecycle_id(0),
last_lifecycle_id_seen(-1),
last_serial_arena(NULL) {}
#endif
// Number of per-thread lifecycle IDs to reserve. Must be power of two.
// To reduce contention on a global atomic, each thread reserves a batch of
// IDs. The following number is calculated based on a stress test with
// ~6500 threads all frequently allocating a new arena.
static constexpr size_t kPerThreadIds = 256;
// Next lifecycle ID available to this thread. We need to reserve a new
// batch, if `next_lifecycle_id & (kPerThreadIds - 1) == 0`.
uint64_t next_lifecycle_id;
// The ThreadCache is considered valid as long as this matches the
// lifecycle_id of the arena being used.
uint64_t last_lifecycle_id_seen;
SerialArena* last_serial_arena;
};
// Lifecycle_id can be highly contended variable in a situation of lots of
// arena creation. Make sure that other global variables are not sharing the
// cacheline.
#ifdef _MSC_VER
#pragma warning(disable : 4324)
#endif
struct alignas(64) CacheAlignedLifecycleIdGenerator {
std::atomic<LifecycleIdAtomic> id;
};
static CacheAlignedLifecycleIdGenerator lifecycle_id_generator_;
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
// iOS does not support __thread keyword so we use a custom thread local
// storage class we implemented.
static ThreadCache& thread_cache();
#elif defined(PROTOBUF_USE_DLLS)
// Thread local variables cannot be exposed through DLL interface but we can
// wrap them in static functions.
static ThreadCache& thread_cache();
#else
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_;
static ThreadCache& thread_cache() { return thread_cache_; }
#endif
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadSafeArena);
// All protos have pointers back to the arena hence Arena must have
// pointer stability.
ThreadSafeArena(ThreadSafeArena&&) = delete;
ThreadSafeArena& operator=(ThreadSafeArena&&) = delete;
public:
// kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8
// to protect the invariant that pos is always at a multiple of 8.
static constexpr size_t kBlockHeaderSize = SerialArena::kBlockHeaderSize;
static constexpr size_t kSerialArenaSize =
(sizeof(SerialArena) + 7) & static_cast<size_t>(-8);
static_assert(kBlockHeaderSize % 8 == 0,
"kBlockHeaderSize must be a multiple of 8.");
static_assert(kSerialArenaSize % 8 == 0,
"kSerialArenaSize must be a multiple of 8.");
};
} // namespace internal
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_ARENA_IMPL_H__

View File

@ -0,0 +1,50 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <thirdparty/protobuf/arena_test_util.h>
#include <thirdparty/protobuf/stubs/logging.h>
#include <thirdparty/protobuf/stubs/common.h>
#define EXPECT_EQ GOOGLE_CHECK_EQ
namespace google {
namespace protobuf {
namespace internal {
NoHeapChecker::~NoHeapChecker() {
capture_alloc.Unhook();
EXPECT_EQ(0, capture_alloc.alloc_count());
EXPECT_EQ(0, capture_alloc.free_count());
}
} // namespace internal
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,126 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
#define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
#include <thirdparty/protobuf/stubs/logging.h>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/io/coded_stream.h>
#include <thirdparty/protobuf/io/zero_copy_stream_impl_lite.h>
#include <thirdparty/protobuf/arena.h>
namespace google {
namespace protobuf {
template <typename T, bool use_arena>
void TestParseCorruptedString(const T& message) {
int success_count = 0;
std::string s;
{
// Map order is not deterministic. To make the test deterministic we want
// to serialize the proto deterministically.
io::StringOutputStream output(&s);
io::CodedOutputStream out(&output);
out.SetSerializationDeterministic(true);
message.SerializePartialToCodedStream(&out);
}
const int kMaxIters = 900;
const int stride = s.size() <= kMaxIters ? 1 : s.size() / kMaxIters;
const int start = stride == 1 || use_arena ? 0 : (stride + 1) / 2;
for (int i = start; i < s.size(); i += stride) {
for (int c = 1 + (i % 17); c < 256; c += 2 * c + (i & 3)) {
s[i] ^= c;
Arena arena;
T* message = Arena::CreateMessage<T>(use_arena ? &arena : nullptr);
if (message->ParseFromString(s)) {
++success_count;
}
if (!use_arena) {
delete message;
}
s[i] ^= c; // Restore s to its original state.
}
}
// This next line is a low bar. But getting through the test without crashing
// due to use-after-free or other bugs is a big part of what we're checking.
GOOGLE_CHECK_GT(success_count, 0);
}
namespace internal {
class NoHeapChecker {
public:
NoHeapChecker() { capture_alloc.Hook(); }
~NoHeapChecker();
private:
class NewDeleteCapture {
public:
// TODO(xiaofeng): Implement this for opensource protobuf.
void Hook() {}
void Unhook() {}
int alloc_count() { return 0; }
int free_count() { return 0; }
} capture_alloc;
};
// Owns the internal T only if it's not owned by an arena.
// T needs to be arena constructible and destructor skippable.
template <typename T>
class ArenaHolder {
public:
explicit ArenaHolder(Arena* arena)
: field_(Arena::CreateMessage<T>(arena)),
owned_by_arena_(arena != nullptr) {
GOOGLE_DCHECK(google::protobuf::Arena::is_arena_constructable<T>::value);
GOOGLE_DCHECK(google::protobuf::Arena::is_destructor_skippable<T>::value);
}
~ArenaHolder() {
if (!owned_by_arena_) {
delete field_;
}
}
T* get() { return field_; }
T* operator->() { return field_; }
T& operator*() { return *field_; }
private:
T* field_;
bool owned_by_arena_;
};
} // namespace internal
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__

File diff suppressed because it is too large Load Diff

286
r5dev/thirdparty/protobuf/arenastring.cc vendored Normal file
View File

@ -0,0 +1,286 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <thirdparty/protobuf/arenastring.h>
#include <thirdparty/protobuf/stubs/logging.h>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/parse_context.h>
#include <thirdparty/protobuf/io/coded_stream.h>
#include <thirdparty/protobuf/message_lite.h>
#include <thirdparty/protobuf/stubs/mutex.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/stubs/stl_util.h>
// clang-format off
#include <thirdparty/protobuf/port_def.inc>
// clang-format on
namespace google {
namespace protobuf {
namespace internal {
const std::string& LazyString::Init() const {
static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED};
mu.Lock();
const std::string* res = inited_.load(std::memory_order_acquire);
if (res == nullptr) {
auto init_value = init_value_;
res = ::new (static_cast<void*>(string_buf_))
std::string(init_value.ptr, init_value.size);
inited_.store(res, std::memory_order_release);
}
mu.Unlock();
return *res;
}
std::string* ArenaStringPtr::SetAndReturnNewString() {
std::string* new_string = new std::string();
tagged_ptr_.Set(new_string);
return new_string;
}
void ArenaStringPtr::DestroyNoArenaSlowPath() { delete UnsafeMutablePointer(); }
void ArenaStringPtr::Set(const std::string* default_value,
ConstStringParam value, ::google::protobuf::Arena* arena) {
if (IsDefault(default_value)) {
tagged_ptr_.Set(Arena::Create<std::string>(arena, value));
} else {
UnsafeMutablePointer()->assign(value.data(), value.length());
}
}
void ArenaStringPtr::Set(const std::string* default_value, std::string&& value,
::google::protobuf::Arena* arena) {
if (IsDefault(default_value)) {
if (arena == nullptr) {
tagged_ptr_.Set(new std::string(std::move(value)));
} else {
tagged_ptr_.Set(Arena::Create<std::string>(arena, std::move(value)));
}
} else if (IsDonatedString()) {
std::string* current = tagged_ptr_.Get();
auto* s = new (current) std::string(std::move(value));
arena->OwnDestructor(s);
tagged_ptr_.Set(s);
} else /* !IsDonatedString() */ {
*UnsafeMutablePointer() = std::move(value);
}
}
void ArenaStringPtr::Set(EmptyDefault, ConstStringParam value,
::google::protobuf::Arena* arena) {
Set(&GetEmptyStringAlreadyInited(), value, arena);
}
void ArenaStringPtr::Set(EmptyDefault, std::string&& value,
::google::protobuf::Arena* arena) {
Set(&GetEmptyStringAlreadyInited(), std::move(value), arena);
}
void ArenaStringPtr::Set(NonEmptyDefault, ConstStringParam value,
::google::protobuf::Arena* arena) {
Set(nullptr, value, arena);
}
void ArenaStringPtr::Set(NonEmptyDefault, std::string&& value,
::google::protobuf::Arena* arena) {
Set(nullptr, std::move(value), arena);
}
std::string* ArenaStringPtr::Mutable(EmptyDefault, ::google::protobuf::Arena* arena) {
if (!IsDonatedString() && !IsDefault(&GetEmptyStringAlreadyInited())) {
return UnsafeMutablePointer();
} else {
return MutableSlow(arena);
}
}
std::string* ArenaStringPtr::Mutable(const LazyString& default_value,
::google::protobuf::Arena* arena) {
if (!IsDonatedString() && !IsDefault(nullptr)) {
return UnsafeMutablePointer();
} else {
return MutableSlow(arena, default_value);
}
}
std::string* ArenaStringPtr::MutableNoCopy(const std::string* default_value,
::google::protobuf::Arena* arena) {
if (!IsDonatedString() && !IsDefault(default_value)) {
return UnsafeMutablePointer();
} else {
GOOGLE_DCHECK(IsDefault(default_value));
// Allocate empty. The contents are not relevant.
std::string* new_string = Arena::Create<std::string>(arena);
tagged_ptr_.Set(new_string);
return new_string;
}
}
template <typename... Lazy>
std::string* ArenaStringPtr::MutableSlow(::google::protobuf::Arena* arena,
const Lazy&... lazy_default) {
const std::string* const default_value =
sizeof...(Lazy) == 0 ? &GetEmptyStringAlreadyInited() : nullptr;
GOOGLE_DCHECK(IsDefault(default_value));
std::string* new_string =
Arena::Create<std::string>(arena, lazy_default.get()...);
tagged_ptr_.Set(new_string);
return new_string;
}
std::string* ArenaStringPtr::Release(const std::string* default_value,
::google::protobuf::Arena* arena) {
if (IsDefault(default_value)) {
return nullptr;
} else {
return ReleaseNonDefault(default_value, arena);
}
}
std::string* ArenaStringPtr::ReleaseNonDefault(const std::string* default_value,
::google::protobuf::Arena* arena) {
GOOGLE_DCHECK(!IsDefault(default_value));
if (!IsDonatedString()) {
std::string* released;
if (arena != nullptr) {
released = new std::string;
released->swap(*UnsafeMutablePointer());
} else {
released = UnsafeMutablePointer();
}
tagged_ptr_.Set(const_cast<std::string*>(default_value));
return released;
} else /* IsDonatedString() */ {
GOOGLE_DCHECK(arena != nullptr);
std::string* released = new std::string(Get());
tagged_ptr_.Set(const_cast<std::string*>(default_value));
return released;
}
}
void ArenaStringPtr::SetAllocated(const std::string* default_value,
std::string* value, ::google::protobuf::Arena* arena) {
// Release what we have first.
if (arena == nullptr && !IsDefault(default_value)) {
delete UnsafeMutablePointer();
}
if (value == nullptr) {
tagged_ptr_.Set(const_cast<std::string*>(default_value));
} else {
#ifdef NDEBUG
tagged_ptr_.Set(value);
if (arena != nullptr) {
arena->Own(value);
}
#else
// On debug builds, copy the string so the address differs. delete will
// fail if value was a stack-allocated temporary/etc., which would have
// failed when arena ran its cleanup list.
std::string* new_value = Arena::Create<std::string>(arena, *value);
delete value;
tagged_ptr_.Set(new_value);
#endif
}
}
void ArenaStringPtr::Destroy(const std::string* default_value,
::google::protobuf::Arena* arena) {
if (arena == nullptr) {
GOOGLE_DCHECK(!IsDonatedString());
if (!IsDefault(default_value)) {
delete UnsafeMutablePointer();
}
}
}
void ArenaStringPtr::Destroy(EmptyDefault, ::google::protobuf::Arena* arena) {
Destroy(&GetEmptyStringAlreadyInited(), arena);
}
void ArenaStringPtr::Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena) {
Destroy(nullptr, arena);
}
void ArenaStringPtr::ClearToEmpty() {
if (IsDefault(&GetEmptyStringAlreadyInited())) {
// Already set to default -- do nothing.
} else {
// Unconditionally mask away the tag.
//
// UpdateDonatedString uses assign when capacity is larger than the new
// value, which is trivially true in the donated string case.
// const_cast<std::string*>(PtrValue<std::string>())->clear();
tagged_ptr_.Get()->clear();
}
}
void ArenaStringPtr::ClearToDefault(const LazyString& default_value,
::google::protobuf::Arena* arena) {
(void)arena;
if (IsDefault(nullptr)) {
// Already set to default -- do nothing.
} else if (!IsDonatedString()) {
UnsafeMutablePointer()->assign(default_value.get());
}
}
inline void SetStrWithHeapBuffer(std::string* str, ArenaStringPtr* s) {
TaggedPtr<std::string> res;
res.Set(str);
s->UnsafeSetTaggedPointer(res);
}
const char* EpsCopyInputStream::ReadArenaString(const char* ptr,
ArenaStringPtr* s,
Arena* arena) {
GOOGLE_DCHECK(arena != nullptr);
int size = ReadSize(&ptr);
if (!ptr) return nullptr;
auto* str = Arena::Create<std::string>(arena);
ptr = ReadString(ptr, size, str);
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
SetStrWithHeapBuffer(str, s);
return ptr;
}
} // namespace internal
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>

420
r5dev/thirdparty/protobuf/arenastring.h vendored Normal file
View File

@ -0,0 +1,420 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_ARENASTRING_H__
#define GOOGLE_PROTOBUF_ARENASTRING_H__
#include <string>
#include <type_traits>
#include <utility>
#include <thirdparty/protobuf/stubs/logging.h>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/arena.h>
#include <thirdparty/protobuf/port.h>
#include <thirdparty/protobuf/port_def.inc>
#ifdef SWIG
#error "You cannot SWIG proto headers"
#endif
namespace google {
namespace protobuf {
namespace internal {
template <typename T>
class ExplicitlyConstructed;
class SwapFieldHelper;
// Lazy string instance to support string fields with non-empty default.
// These are initialized on the first call to .get().
class PROTOBUF_EXPORT LazyString {
public:
// We explicitly make LazyString an aggregate so that MSVC can do constant
// initialization on it without marking it `constexpr`.
// We do not want to use `constexpr` because it makes it harder to have extern
// storage for it and causes library bloat.
struct InitValue {
const char* ptr;
size_t size;
};
// We keep a union of the initialization value and the std::string to save on
// space. We don't need the string array after Init() is done.
union {
mutable InitValue init_value_;
alignas(std::string) mutable char string_buf_[sizeof(std::string)];
};
mutable std::atomic<const std::string*> inited_;
const std::string& get() const {
// This check generates less code than a call-once invocation.
auto* res = inited_.load(std::memory_order_acquire);
if (PROTOBUF_PREDICT_FALSE(res == nullptr)) return Init();
return *res;
}
private:
// Initialize the string in `string_buf_`, update `inited_` and return it.
// We return it here to avoid having to read it again in the inlined code.
const std::string& Init() const;
};
template <typename T>
class TaggedPtr {
public:
TaggedPtr() = default;
explicit constexpr TaggedPtr(const ExplicitlyConstructed<std::string>* ptr)
: ptr_(const_cast<ExplicitlyConstructed<std::string>*>(ptr)) {}
void SetTagged(T* p) {
Set(p);
ptr_ = reinterpret_cast<void*>(as_int() | 1);
}
void Set(T* p) { ptr_ = p; }
T* Get() const { return reinterpret_cast<T*>(as_int() & -2); }
bool IsTagged() const { return as_int() & 1; }
// Returned value is only safe to dereference if IsTagged() == false.
// It is safe to compare.
T* UnsafeGet() const { return static_cast<T*>(ptr_); }
bool IsNull() { return ptr_ == nullptr; }
private:
uintptr_t as_int() const { return reinterpret_cast<uintptr_t>(ptr_); }
void* ptr_;
};
static_assert(std::is_trivial<TaggedPtr<std::string>>::value,
"TaggedPtr must be trivial");
// This class encapsulates a pointer to a std::string with or without a donated
// buffer, tagged by bottom bit. It is a high-level wrapper that almost directly
// corresponds to the interface required by string fields in generated
// code. It replaces the old std::string* pointer in such cases.
//
// The object has different but similar code paths for when the default value is
// the empty string and when it is a non-empty string.
// The empty string is handled different throughout the library and there is a
// single global instance of it we can share.
//
// For fields with an empty string default value, there are three distinct
// states:
//
// - Pointer set to 'String' tag (LSB is 0), equal to
// &GetEmptyStringAlreadyInited(): field is set to its default value. Points
// to a true std::string*, but we do not own that std::string* (it's a
// globally shared instance).
//
// - Pointer set to 'String' tag (LSB is 0), but not equal to the global empty
// string: field points to a true std::string* instance that we own. This
// instance is either on the heap or on the arena (i.e. registered on
// free()/destructor-call list) as appropriate.
//
// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string
// instance with a buffer on the arena (arena is never nullptr in this case).
//
// For fields with a non-empty string default value, there are three distinct
// states:
//
// - Pointer set to 'String' tag (LSB is 0), equal to `nullptr`:
// Field is in "default" mode and does not point to any actual instance.
// Methods that might need to create an instance of the object will pass a
// `const LazyString&` for it.
//
// - Pointer set to 'String' tag (LSB is 0), but not equal to `nullptr`:
// field points to a true std::string* instance that we own. This instance is
// either on the heap or on the arena (i.e. registered on
// free()/destructor-call list) as appropriate.
//
// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string
// instance with a buffer on the arena (arena is never nullptr in this case).
//
// Generated code and reflection code both ensure that ptr_ is never null for
// fields with an empty default.
// Because ArenaStringPtr is used in oneof unions, its constructor is a NOP and
// so the field is always manually initialized via method calls.
//
// Side-note: why pass information about the default on every API call? Because
// we don't want to hold it in a member variable, or else this would go into
// every proto message instance. This would be a huge waste of space, since the
// default instance pointer is typically a global (static class field). We want
// the generated code to be as efficient as possible, and if we take
// the default value information as a parameter that's in practice taken from a
// static class field, and compare ptr_ to the default value, we end up with a
// single "cmp %reg, GLOBAL" in the resulting machine code. (Note that this also
// requires the String tag to be 0 so we can avoid the mask before comparing.)
struct PROTOBUF_EXPORT ArenaStringPtr {
ArenaStringPtr() = default;
explicit constexpr ArenaStringPtr(
const ExplicitlyConstructed<std::string>* default_value)
: tagged_ptr_(default_value) {}
// Some methods below are overloaded on a `default_value` and on tags.
// The tagged overloads help reduce code size in the callers in generated
// code, while the `default_value` overloads are useful from reflection.
// By-value empty struct arguments are elided in the ABI.
struct EmptyDefault {};
struct NonEmptyDefault {};
void Set(const std::string* default_value, ConstStringParam value,
::google::protobuf::Arena* arena);
void Set(const std::string* default_value, std::string&& value,
::google::protobuf::Arena* arena);
void Set(EmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena);
void Set(EmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
void Set(NonEmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena);
void Set(NonEmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
template <typename FirstParam>
void Set(FirstParam p1, const char* str, ::google::protobuf::Arena* arena) {
Set(p1, ConstStringParam(str), arena);
}
template <typename FirstParam>
void Set(FirstParam p1, const char* str, size_t size,
::google::protobuf::Arena* arena) {
ConstStringParam sp{str, size}; // for string_view and `const string &`
Set(p1, sp, arena);
}
template <typename FirstParam, typename RefWrappedType>
void Set(FirstParam p1,
std::reference_wrapper<RefWrappedType> const_string_ref,
::google::protobuf::Arena* arena) {
Set(p1, const_string_ref.get(), arena);
}
template <typename FirstParam, typename SecondParam>
void SetBytes(FirstParam p1, SecondParam&& p2, ::google::protobuf::Arena* arena) {
Set(p1, static_cast<SecondParam&&>(p2), arena);
}
template <typename FirstParam>
void SetBytes(FirstParam p1, const void* str, size_t size,
::google::protobuf::Arena* arena) {
// must work whether ConstStringParam is string_view or `const string &`
ConstStringParam sp{static_cast<const char*>(str), size};
Set(p1, sp, arena);
}
// Basic accessors.
PROTOBUF_NDEBUG_INLINE const std::string& Get() const {
// Unconditionally mask away the tag.
return *tagged_ptr_.Get();
}
PROTOBUF_NDEBUG_INLINE const std::string* GetPointer() const {
// Unconditionally mask away the tag.
return tagged_ptr_.Get();
}
// For fields with an empty default value.
std::string* Mutable(EmptyDefault, ::google::protobuf::Arena* arena);
// For fields with a non-empty default value.
std::string* Mutable(const LazyString& default_value, ::google::protobuf::Arena* arena);
// Release returns a std::string* instance that is heap-allocated and is not
// Own()'d by any arena. If the field is not set, this returns nullptr. The
// caller retains ownership. Clears this field back to nullptr state. Used to
// implement release_<field>() methods on generated classes.
PROTOBUF_NODISCARD std::string* Release(const std::string* default_value,
::google::protobuf::Arena* arena);
PROTOBUF_NODISCARD std::string* ReleaseNonDefault(
const std::string* default_value, ::google::protobuf::Arena* arena);
// Takes a std::string that is heap-allocated, and takes ownership. The
// std::string's destructor is registered with the arena. Used to implement
// set_allocated_<field> in generated classes.
void SetAllocated(const std::string* default_value, std::string* value,
::google::protobuf::Arena* arena);
// Swaps internal pointers. Arena-safety semantics: this is guarded by the
// logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
// 'unsafe' if called directly.
inline PROTOBUF_NDEBUG_INLINE static void InternalSwap(
const std::string* default_value, ArenaStringPtr* rhs, Arena* rhs_arena,
ArenaStringPtr* lhs, Arena* lhs_arena);
// Frees storage (if not on an arena).
void Destroy(const std::string* default_value, ::google::protobuf::Arena* arena);
void Destroy(EmptyDefault, ::google::protobuf::Arena* arena);
void Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena);
// Clears content, but keeps allocated std::string, to avoid the overhead of
// heap operations. After this returns, the content (as seen by the user) will
// always be the empty std::string. Assumes that |default_value| is an empty
// std::string.
void ClearToEmpty();
// Clears content, assuming that the current value is not the empty
// string default.
void ClearNonDefaultToEmpty();
// Clears content, but keeps allocated std::string if arena != nullptr, to
// avoid the overhead of heap operations. After this returns, the content
// (as seen by the user) will always be equal to |default_value|.
void ClearToDefault(const LazyString& default_value, ::google::protobuf::Arena* arena);
// Called from generated code / reflection runtime only. Resets value to point
// to a default string pointer, with the semantics that this
// ArenaStringPtr does not own the pointed-to memory. Disregards initial value
// of ptr_ (so this is the *ONLY* safe method to call after construction or
// when reinitializing after becoming the active field in a oneof union).
inline void UnsafeSetDefault(const std::string* default_value);
// Returns a mutable pointer, but doesn't initialize the string to the
// default value.
std::string* MutableNoArenaNoDefault(const std::string* default_value);
// Get a mutable pointer with unspecified contents.
// Similar to `MutableNoArenaNoDefault`, but also handles the arena case.
// If the value was donated, the contents are discarded.
std::string* MutableNoCopy(const std::string* default_value,
::google::protobuf::Arena* arena);
// Destroy the string. Assumes `arena == nullptr`.
void DestroyNoArena(const std::string* default_value);
// Internal setter used only at parse time to directly set a donated string
// value.
void UnsafeSetTaggedPointer(TaggedPtr<std::string> value) {
tagged_ptr_ = value;
}
// Generated code only! An optimization, in certain cases the generated
// code is certain we can obtain a std::string with no default checks and
// tag tests.
std::string* UnsafeMutablePointer() PROTOBUF_RETURNS_NONNULL;
inline bool IsDefault(const std::string* default_value) const {
// Relies on the fact that kPtrTagString == 0, so if IsString(), ptr_ is the
// actual std::string pointer (and if !IsString(), ptr_ will never be equal
// to any aligned |default_value| pointer). The key is that we want to avoid
// masking in the fastpath const-pointer Get() case for non-arena code.
return tagged_ptr_.UnsafeGet() == default_value;
}
private:
TaggedPtr<std::string> tagged_ptr_;
bool IsDonatedString() const { return false; }
// Swaps tagged pointer without debug hardening. This is to allow python
// protobuf to maintain pointer stability even in DEBUG builds.
inline PROTOBUF_NDEBUG_INLINE static void UnsafeShallowSwap(
ArenaStringPtr* rhs, ArenaStringPtr* lhs) {
std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_);
}
friend class ::google::protobuf::internal::SwapFieldHelper;
// Slow paths.
// MutableSlow requires that !IsString() || IsDefault
// Variadic to support 0 args for EmptyDefault and 1 arg for LazyString.
template <typename... Lazy>
std::string* MutableSlow(::google::protobuf::Arena* arena, const Lazy&... lazy_default);
// Sets value to a newly allocated string and returns it
std::string* SetAndReturnNewString();
// Destroys the non-default string value out-of-line
void DestroyNoArenaSlowPath();
};
inline void ArenaStringPtr::UnsafeSetDefault(const std::string* value) {
tagged_ptr_.Set(const_cast<std::string*>(value));
}
// Make sure rhs_arena allocated rhs, and lhs_arena allocated lhs.
inline PROTOBUF_NDEBUG_INLINE void ArenaStringPtr::InternalSwap( //
const std::string* default_value, //
ArenaStringPtr* rhs, Arena* rhs_arena, //
ArenaStringPtr* lhs, Arena* lhs_arena) {
// Silence unused variable warnings in release buildls.
(void)default_value;
(void)rhs_arena;
(void)lhs_arena;
std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_);
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
auto force_realloc = [default_value](ArenaStringPtr* p, Arena* arena) {
if (p->IsDefault(default_value)) return;
std::string* old_value = p->tagged_ptr_.Get();
std::string* new_value =
p->IsDonatedString()
? Arena::Create<std::string>(arena, *old_value)
: Arena::Create<std::string>(arena, std::move(*old_value));
if (arena == nullptr) delete old_value;
p->tagged_ptr_.Set(new_value);
};
// Because, at this point, tagged_ptr_ has been swapped, arena should also be
// swapped.
force_realloc(lhs, rhs_arena);
force_realloc(rhs, lhs_arena);
#endif // PROTOBUF_FORCE_COPY_IN_SWAP
}
inline void ArenaStringPtr::ClearNonDefaultToEmpty() {
// Unconditionally mask away the tag.
tagged_ptr_.Get()->clear();
}
inline std::string* ArenaStringPtr::MutableNoArenaNoDefault(
const std::string* default_value) {
// VERY IMPORTANT for performance and code size: this will reduce to a member
// variable load, a pointer check (against |default_value|, in practice a
// static global) and a branch to the slowpath (which calls operator new and
// the ctor). DO NOT add any tagged-pointer operations here.
if (IsDefault(default_value)) {
return SetAndReturnNewString();
} else {
return UnsafeMutablePointer();
}
}
inline void ArenaStringPtr::DestroyNoArena(const std::string* default_value) {
if (!IsDefault(default_value)) {
DestroyNoArenaSlowPath();
}
}
inline std::string* ArenaStringPtr::UnsafeMutablePointer() {
GOOGLE_DCHECK(!tagged_ptr_.IsTagged());
GOOGLE_DCHECK(tagged_ptr_.UnsafeGet() != nullptr);
return tagged_ptr_.UnsafeGet();
}
} // namespace internal
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_ARENASTRING_H__

View File

@ -0,0 +1,157 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <thirdparty/protobuf/arenastring.h>
#include <algorithm>
#include <cstdlib>
#include <memory>
#include <string>
#include <vector>
#include <thirdparty/protobuf/stubs/logging.h>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/io/coded_stream.h>
#include <thirdparty/protobuf/io/zero_copy_stream_impl.h>
#include <thirdparty/protobuf/generated_message_util.h>
#include <thirdparty/protobuf/message_lite.h>
#include <gtest/gtest.h>
#include <thirdparty/protobuf/stubs/strutil.h>
// Must be included last.
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
using internal::ArenaStringPtr;
using EmptyDefault = ArenaStringPtr::EmptyDefault;
const internal::LazyString nonempty_default{{{"default", 7}}, {nullptr}};
const std::string* empty_default = &internal::GetEmptyString();
class SingleArena : public testing::TestWithParam<bool> {
public:
std::unique_ptr<Arena> GetArena() {
if (this->GetParam()) return nullptr;
return std::unique_ptr<Arena>(new Arena());
}
};
INSTANTIATE_TEST_SUITE_P(ArenaString, SingleArena, testing::Bool());
TEST_P(SingleArena, GetSet) {
auto arena = GetArena();
ArenaStringPtr field;
field.UnsafeSetDefault(empty_default);
EXPECT_EQ("", field.Get());
field.Set(empty_default, "Test short", arena.get());
EXPECT_EQ("Test short", field.Get());
field.Set(empty_default, "Test long long long long value", arena.get());
EXPECT_EQ("Test long long long long value", field.Get());
field.Set(empty_default, "", arena.get());
field.Destroy(empty_default, arena.get());
}
TEST_P(SingleArena, MutableAccessor) {
auto arena = GetArena();
ArenaStringPtr field;
const std::string* empty_default = &internal::GetEmptyString();
field.UnsafeSetDefault(empty_default);
std::string* mut = field.Mutable(EmptyDefault{}, arena.get());
EXPECT_EQ(mut, field.Mutable(EmptyDefault{}, arena.get()));
EXPECT_EQ(mut, &field.Get());
EXPECT_NE(empty_default, mut);
EXPECT_EQ("", *mut);
*mut = "Test long long long long value"; // ensure string allocates storage
EXPECT_EQ("Test long long long long value", field.Get());
field.Destroy(empty_default, arena.get());
}
TEST_P(SingleArena, NullDefault) {
auto arena = GetArena();
ArenaStringPtr field;
field.UnsafeSetDefault(nullptr);
std::string* mut = field.Mutable(nonempty_default, arena.get());
EXPECT_EQ(mut, field.Mutable(nonempty_default, arena.get()));
EXPECT_EQ(mut, &field.Get());
EXPECT_NE(nullptr, mut);
EXPECT_EQ("default", *mut);
*mut = "Test long long long long value"; // ensure string allocates storage
EXPECT_EQ("Test long long long long value", field.Get());
field.Destroy(nullptr, arena.get());
}
class DualArena : public testing::TestWithParam<std::tuple<bool, bool>> {
public:
std::unique_ptr<Arena> GetLhsArena() {
if (std::get<0>(this->GetParam())) return nullptr;
return std::unique_ptr<Arena>(new Arena());
}
std::unique_ptr<Arena> GetRhsArena() {
if (std::get<1>(this->GetParam())) return nullptr;
return std::unique_ptr<Arena>(new Arena());
}
};
INSTANTIATE_TEST_SUITE_P(ArenaString, DualArena,
testing::Combine(testing::Bool(), testing::Bool()));
TEST_P(DualArena, Swap) {
auto lhs_arena = GetLhsArena();
ArenaStringPtr lhs;
lhs.UnsafeSetDefault(empty_default);
ArenaStringPtr rhs;
rhs.UnsafeSetDefault(empty_default);
{
auto rhs_arena = GetRhsArena();
lhs.Set(empty_default, "lhs value that has some heft", lhs_arena.get());
rhs.Set(empty_default, "rhs value that has some heft", rhs_arena.get());
ArenaStringPtr::InternalSwap(empty_default, //
&lhs, lhs_arena.get(), //
&rhs, rhs_arena.get());
EXPECT_EQ("rhs value that has some heft", lhs.Get());
EXPECT_EQ("lhs value that has some heft", rhs.Get());
lhs.Destroy(empty_default, rhs_arena.get());
}
EXPECT_EQ("lhs value that has some heft", rhs.Get());
rhs.Destroy(empty_default, lhs_arena.get());
}
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>

View File

@ -0,0 +1,168 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <thirdparty/protobuf/compiler/annotation_test_util.h>
#include <cstdint>
#include <memory>
#include <thirdparty/protobuf/testing/file.h>
#include <thirdparty/protobuf/testing/file.h>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/compiler/command_line_interface.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/io/zero_copy_stream_impl_lite.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace annotation_test_util {
namespace {
// A CodeGenerator that captures the FileDescriptor it's passed as a
// FileDescriptorProto.
class DescriptorCapturingGenerator : public CodeGenerator {
public:
// Does not own file; file must outlive the Generator.
explicit DescriptorCapturingGenerator(FileDescriptorProto* file)
: file_(file) {}
virtual bool Generate(const FileDescriptor* file,
const std::string& parameter, GeneratorContext* context,
std::string* error) const {
file->CopyTo(file_);
return true;
}
private:
FileDescriptorProto* file_;
};
} // namespace
void AddFile(const std::string& filename, const std::string& data) {
GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/" + filename, data,
true));
}
bool RunProtoCompiler(const std::string& filename,
const std::string& plugin_specific_args,
CommandLineInterface* cli, FileDescriptorProto* file) {
cli->SetInputsAreProtoPathRelative(true);
DescriptorCapturingGenerator capturing_generator(file);
cli->RegisterGenerator("--capture_out", &capturing_generator, "");
std::string proto_path = "-I" + TestTempDir();
std::string capture_out = "--capture_out=" + TestTempDir();
const char* argv[] = {"protoc", proto_path.c_str(),
plugin_specific_args.c_str(), capture_out.c_str(),
filename.c_str()};
return cli->Run(5, argv) == 0;
}
bool DecodeMetadata(const std::string& path, GeneratedCodeInfo* info) {
std::string data;
GOOGLE_CHECK_OK(File::GetContents(path, &data, true));
io::ArrayInputStream input(data.data(), data.size());
return info->ParseFromZeroCopyStream(&input);
}
void FindAnnotationsOnPath(
const GeneratedCodeInfo& info, const std::string& source_file,
const std::vector<int>& path,
std::vector<const GeneratedCodeInfo::Annotation*>* annotations) {
for (int i = 0; i < info.annotation_size(); ++i) {
const GeneratedCodeInfo::Annotation* annotation = &info.annotation(i);
if (annotation->source_file() != source_file ||
annotation->path_size() != path.size()) {
continue;
}
int node = 0;
for (; node < path.size(); ++node) {
if (annotation->path(node) != path[node]) {
break;
}
}
if (node == path.size()) {
annotations->push_back(annotation);
}
}
}
const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
const GeneratedCodeInfo& info, const std::string& source_file,
const std::vector<int>& path) {
std::vector<const GeneratedCodeInfo::Annotation*> annotations;
FindAnnotationsOnPath(info, source_file, path, &annotations);
if (annotations.empty()) {
return NULL;
}
return annotations[0];
}
bool AtLeastOneAnnotationMatchesSubstring(
const std::string& file_content,
const std::vector<const GeneratedCodeInfo::Annotation*>& annotations,
const std::string& expected_text) {
for (std::vector<const GeneratedCodeInfo::Annotation*>::const_iterator
i = annotations.begin(),
e = annotations.end();
i != e; ++i) {
const GeneratedCodeInfo::Annotation* annotation = *i;
uint32_t begin = annotation->begin();
uint32_t end = annotation->end();
if (end < begin || end > file_content.size()) {
return false;
}
if (file_content.substr(begin, end - begin) == expected_text) {
return true;
}
}
return false;
}
bool AnnotationMatchesSubstring(const std::string& file_content,
const GeneratedCodeInfo::Annotation* annotation,
const std::string& expected_text) {
std::vector<const GeneratedCodeInfo::Annotation*> annotations;
annotations.push_back(annotation);
return AtLeastOneAnnotationMatchesSubstring(file_content, annotations,
expected_text);
}
} // namespace annotation_test_util
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,115 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
#define GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
// Utilities that assist in writing tests for generator annotations.
// See java/internal/annotation_unittest.cc for an example.
namespace google {
namespace protobuf {
namespace compiler {
namespace annotation_test_util {
// Struct that contains the file generated from a .proto file and its
// GeneratedCodeInfo. For example, the Java generator will fill this struct
// (for some 'foo.proto') with:
// file_path = "Foo.java"
// file_content = content of Foo.java
// file_info = parsed content of Foo.java.pb.meta
struct ExpectedOutput {
std::string file_path;
std::string file_content;
GeneratedCodeInfo file_info;
explicit ExpectedOutput(const std::string& file_path)
: file_path(file_path) {}
};
// Creates a file with name `filename` and content `data` in temp test
// directory.
void AddFile(const std::string& filename, const std::string& data);
// Runs proto compiler. Captures proto file structure in FileDescriptorProto.
// Files will be generated in TestTempDir() folder. Callers of this
// function must read generated files themselves.
//
// filename: source .proto file used to generate code.
// plugin_specific_args: command line arguments specific to current generator.
// For Java, this value might be "--java_out=annotate_code:test_temp_dir"
// cli: instance of command line interface to run generator. See Java's
// annotation_unittest.cc for an example of how to initialize it.
// file: output parameter, will be set to the descriptor of the proto file
// specified in filename.
bool RunProtoCompiler(const std::string& filename,
const std::string& plugin_specific_args,
CommandLineInterface* cli, FileDescriptorProto* file);
bool DecodeMetadata(const std::string& path, GeneratedCodeInfo* info);
// Finds all of the Annotations for a given source file and path.
// See Location.path in https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto for
// explanation of what path vector is.
void FindAnnotationsOnPath(
const GeneratedCodeInfo& info, const std::string& source_file,
const std::vector<int>& path,
std::vector<const GeneratedCodeInfo::Annotation*>* annotations);
// Finds the Annotation for a given source file and path (or returns null if it
// couldn't). If there are several annotations for given path, returns the first
// one. See Location.path in
// https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto for explanation of what path
// vector is.
const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
const GeneratedCodeInfo& info, const std::string& source_file,
const std::vector<int>& path);
// Returns true if at least one of the provided annotations covers a given
// substring in file_content.
bool AtLeastOneAnnotationMatchesSubstring(
const std::string& file_content,
const std::vector<const GeneratedCodeInfo::Annotation*>& annotations,
const std::string& expected_text);
// Returns true if the provided annotation covers a given substring in
// file_content.
bool AnnotationMatchesSubstring(const std::string& file_content,
const GeneratedCodeInfo::Annotation* annotation,
const std::string& expected_text);
} // namespace annotation_test_util
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__

View File

@ -0,0 +1,137 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/stubs/logging.h>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/compiler/plugin.pb.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
CodeGenerator::~CodeGenerator() {}
bool CodeGenerator::GenerateAll(const std::vector<const FileDescriptor*>& files,
const std::string& parameter,
GeneratorContext* generator_context,
std::string* error) const {
// Default implementation is just to call the per file method, and prefix any
// error string with the file to provide context.
bool succeeded = true;
for (int i = 0; i < files.size(); i++) {
const FileDescriptor* file = files[i];
succeeded = Generate(file, parameter, generator_context, error);
if (!succeeded && error && error->empty()) {
*error =
"Code generator returned false but provided no error "
"description.";
}
if (error && !error->empty()) {
*error = file->name() + ": " + *error;
break;
}
if (!succeeded) {
break;
}
}
return succeeded;
}
GeneratorContext::~GeneratorContext() {}
io::ZeroCopyOutputStream* GeneratorContext::OpenForAppend(
const std::string& filename) {
return NULL;
}
io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert(
const std::string& filename, const std::string& insertion_point) {
GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion.";
return NULL; // make compiler happy
}
io::ZeroCopyOutputStream* GeneratorContext::OpenForInsertWithGeneratedCodeInfo(
const std::string& filename, const std::string& insertion_point,
const google::protobuf::GeneratedCodeInfo& /*info*/) {
return OpenForInsert(filename, insertion_point);
}
void GeneratorContext::ListParsedFiles(
std::vector<const FileDescriptor*>* output) {
GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles";
}
void GeneratorContext::GetCompilerVersion(Version* version) const {
version->set_major(GOOGLE_PROTOBUF_VERSION / 1000000);
version->set_minor(GOOGLE_PROTOBUF_VERSION / 1000 % 1000);
version->set_patch(GOOGLE_PROTOBUF_VERSION % 1000);
version->set_suffix(GOOGLE_PROTOBUF_VERSION_SUFFIX);
}
// Parses a set of comma-delimited name/value pairs.
void ParseGeneratorParameter(
const std::string& text,
std::vector<std::pair<std::string, std::string> >* output) {
std::vector<std::string> parts = Split(text, ",", true);
for (int i = 0; i < parts.size(); i++) {
std::string::size_type equals_pos = parts[i].find_first_of('=');
std::pair<std::string, std::string> value;
if (equals_pos == std::string::npos) {
value.first = parts[i];
value.second = "";
} else {
value.first = parts[i].substr(0, equals_pos);
value.second = parts[i].substr(equals_pos + 1);
}
output->push_back(value);
}
}
// Strips ".proto" or ".protodevel" from the end of a filename.
std::string StripProto(const std::string& filename) {
if (HasSuffixString(filename, ".protodevel")) {
return StripSuffixString(filename, ".protodevel");
} else {
return StripSuffixString(filename, ".proto");
}
}
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,206 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// Defines the abstract interface implemented by each of the language-specific
// code generators.
#ifndef GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
#define GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
#include <string>
#include <utility>
#include <vector>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace io {
class ZeroCopyOutputStream;
}
class FileDescriptor;
class GeneratedCodeInfo;
namespace compiler {
class AccessInfoMap;
class Version;
// Defined in this file.
class CodeGenerator;
class GeneratorContext;
// The abstract interface to a class which generates code implementing a
// particular proto file in a particular language. A number of these may
// be registered with CommandLineInterface to support various languages.
class PROTOC_EXPORT CodeGenerator {
public:
inline CodeGenerator() {}
virtual ~CodeGenerator();
// Generates code for the given proto file, generating one or more files in
// the given output directory.
//
// A parameter to be passed to the generator can be specified on the command
// line. This is intended to be used to pass generator specific parameters.
// It is empty if no parameter was given. ParseGeneratorParameter (below),
// can be used to accept multiple parameters within the single parameter
// command line flag.
//
// Returns true if successful. Otherwise, sets *error to a description of
// the problem (e.g. "invalid parameter") and returns false.
virtual bool Generate(const FileDescriptor* file,
const std::string& parameter,
GeneratorContext* generator_context,
std::string* error) const = 0;
// Generates code for all given proto files.
//
// WARNING: The canonical code generator design produces one or two output
// files per input .proto file, and we do not wish to encourage alternate
// designs.
//
// A parameter is given as passed on the command line, as in |Generate()|
// above.
//
// Returns true if successful. Otherwise, sets *error to a description of
// the problem (e.g. "invalid parameter") and returns false.
virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files,
const std::string& parameter,
GeneratorContext* generator_context,
std::string* error) const;
// This must be kept in sync with plugin.proto. See that file for
// documentation on each value.
enum Feature {
FEATURE_PROTO3_OPTIONAL = 1,
};
// Implement this to indicate what features this code generator supports.
//
// This must be a bitwise OR of values from the Feature enum above (or zero).
virtual uint64_t GetSupportedFeatures() const { return 0; }
// This is no longer used, but this class is part of the opensource protobuf
// library, so it has to remain to keep vtables the same for the current
// version of the library. When protobufs does a api breaking change, the
// method can be removed.
virtual bool HasGenerateAll() const { return true; }
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator);
};
// CodeGenerators generate one or more files in a given directory. This
// abstract interface represents the directory to which the CodeGenerator is
// to write and other information about the context in which the Generator
// runs.
class PROTOC_EXPORT GeneratorContext {
public:
inline GeneratorContext() {
}
virtual ~GeneratorContext();
// Opens the given file, truncating it if it exists, and returns a
// ZeroCopyOutputStream that writes to the file. The caller takes ownership
// of the returned object. This method never fails (a dummy stream will be
// returned instead).
//
// The filename given should be relative to the root of the source tree.
// E.g. the C++ generator, when generating code for "foo/bar.proto", will
// generate the files "foo/bar.pb.h" and "foo/bar.pb.cc"; note that
// "foo/" is included in these filenames. The filename is not allowed to
// contain "." or ".." components.
virtual io::ZeroCopyOutputStream* Open(const std::string& filename) = 0;
// Similar to Open() but the output will be appended to the file if exists
virtual io::ZeroCopyOutputStream* OpenForAppend(const std::string& filename);
// Creates a ZeroCopyOutputStream which will insert code into the given file
// at the given insertion point. See plugin.proto (plugin.pb.h) for more
// information on insertion points. The default implementation
// assert-fails -- it exists only for backwards-compatibility.
//
// WARNING: This feature is currently EXPERIMENTAL and is subject to change.
virtual io::ZeroCopyOutputStream* OpenForInsert(
const std::string& filename, const std::string& insertion_point);
// Similar to OpenForInsert, but if `info` is non-empty, will open (or create)
// filename.pb.meta and insert info at the appropriate place with the
// necessary shifts. The default implementation ignores `info`.
//
// WARNING: This feature will be REMOVED in the near future.
virtual io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo(
const std::string& filename, const std::string& insertion_point,
const google::protobuf::GeneratedCodeInfo& info);
// Returns a vector of FileDescriptors for all the files being compiled
// in this run. Useful for languages, such as Go, that treat files
// differently when compiled as a set rather than individually.
virtual void ListParsedFiles(std::vector<const FileDescriptor*>* output);
// Retrieves the version number of the protocol compiler associated with
// this GeneratorContext.
virtual void GetCompilerVersion(Version* version) const;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
};
// The type GeneratorContext was once called OutputDirectory. This typedef
// provides backward compatibility.
typedef GeneratorContext OutputDirectory;
// Several code generators treat the parameter argument as holding a
// list of options separated by commas. This helper function parses
// a set of comma-delimited name/value pairs: e.g.,
// "foo=bar,baz,qux=corge"
// parses to the pairs:
// ("foo", "bar"), ("baz", ""), ("qux", "corge")
PROTOC_EXPORT void ParseGeneratorParameter(
const std::string&, std::vector<std::pair<std::string, std::string> >*);
// Strips ".proto" or ".protodevel" from the end of a filename.
PROTOC_EXPORT std::string StripProto(const std::string& filename);
} // namespace compiler
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,462 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// Implements the Protocol Compiler front-end such that it may be reused by
// custom compilers written to support other languages.
#ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
#define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
#include <cstdint>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
class Descriptor; // descriptor.h
class DescriptorDatabase; // descriptor_database.h
class DescriptorPool; // descriptor.h
class FileDescriptor; // descriptor.h
class FileDescriptorSet; // descriptor.h
class FileDescriptorProto; // descriptor.pb.h
template <typename T>
class RepeatedPtrField; // repeated_field.h
class SimpleDescriptorDatabase; // descriptor_database.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
//
// The .proto file to compile can be specified on the command line using either
// its physical file path, or a virtual path relative to a directory specified
// in --proto_path. For example, for src/foo.proto, the following two protoc
// invocations work the same way:
// 1. protoc --proto_path=src src/foo.proto (physical file path)
// 2. protoc --proto_path=src foo.proto (virtual path relative to src)
//
// If a file path can be interpreted both as a physical file path and as a
// relative virtual path, the physical file path takes precedence.
//
// For a full description of the command-line syntax, invoke it with --help.
class PROTOC_EXPORT CommandLineInterface {
public:
static const char* const kPathSeparator;
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 std::string& flag_name, CodeGenerator* generator,
const std::string& help_text);
// Register a code generator for a language.
// Besides flag_name you can specify another option_flag_name that could be
// used to pass extra parameters to the registered code generator.
// Suppose you have registered a generator by calling:
// command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...)
// Then you could invoke the compiler with a command like:
// protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz
// This will pass "enable_bar,enable_baz" as the parameter to the generator.
void RegisterGenerator(const std::string& flag_name,
const std::string& option_flag_name,
CodeGenerator* generator,
const std::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-gen-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 (see below). 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.
//
// Plugins can have generator parameters similar to normal built-in
// generators. Extra generator parameters can be passed in via a matching
// "_opt" parameter. For example:
// protoc --plug_out=enable_bar:outdir --plug_opt=enable_baz
// This will pass "enable_bar,enable_baz" as the parameter to the plugin.
//
void AllowPlugins(const std::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[]);
// DEPRECATED. Calling this method has no effect. Protocol compiler now
// always try to find the .proto file relative to the current directory
// first and if the file is not found, it will then treat the input path
// as a virtual path.
void SetInputsAreProtoPathRelative(bool /* 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 std::string& text) { version_info_ = text; }
private:
// -----------------------------------------------------------------
class ErrorPrinter;
class GeneratorContextImpl;
class MemoryOutputStream;
typedef std::unordered_map<std::string, std::unique_ptr<GeneratorContextImpl>>
GeneratorContextMap;
// Clear state from previous Run().
void Clear();
// Remaps the proto file so that it is relative to one of the directories
// in proto_path_. Returns false if an error occurred.
bool MakeProtoProtoPathRelative(DiskSourceTree* source_tree,
std::string* proto,
DescriptorDatabase* fallback_database);
// 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.
bool MakeInputsBeProtoPathRelative(DiskSourceTree* source_tree,
DescriptorDatabase* fallback_database);
// Fails if these files use proto3 optional and the code generator doesn't
// support it. This is a permanent check.
bool EnforceProto3OptionalSupport(
const std::string& codegen_name, uint64_t supported_features,
const std::vector<const FileDescriptor*>& parsed_files) const;
// Return status for ParseArguments() and InterpretArgument().
enum ParseArgumentStatus {
PARSE_ARGUMENT_DONE_AND_CONTINUE,
PARSE_ARGUMENT_DONE_AND_EXIT,
PARSE_ARGUMENT_FAIL
};
// Parse all command-line arguments.
ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
// Read an argument file and append the file's content to the list of
// arguments. Return false if the file cannot be read.
bool ExpandArgumentFile(const std::string& file,
std::vector<std::string>* arguments);
// 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.
//
// Examples:
// "-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, std::string* name, std::string* value);
// Interprets arguments parsed with ParseArgument.
ParseArgumentStatus InterpretArgument(const std::string& name,
const std::string& value);
// Print the --help text to stderr.
void PrintHelpText();
// Loads proto_path_ into the provided source_tree.
bool InitializeDiskSourceTree(DiskSourceTree* source_tree,
DescriptorDatabase* fallback_database);
// Verify that all the input files exist in the given database.
bool VerifyInputFilesInDescriptors(DescriptorDatabase* fallback_database);
// Parses input_files_ into parsed_files
bool ParseInputFiles(DescriptorPool* descriptor_pool,
DiskSourceTree* source_tree,
std::vector<const FileDescriptor*>* parsed_files);
// Generate the given output file from the given input.
struct OutputDirective; // see below
bool GenerateOutput(const std::vector<const FileDescriptor*>& parsed_files,
const OutputDirective& output_directive,
GeneratorContext* generator_context);
bool GeneratePluginOutput(
const std::vector<const FileDescriptor*>& parsed_files,
const std::string& plugin_name, const std::string& parameter,
GeneratorContext* generator_context, std::string* error);
// Implements --encode and --decode.
bool EncodeOrDecode(const DescriptorPool* pool);
// Implements the --descriptor_set_out option.
bool WriteDescriptorSet(
const std::vector<const FileDescriptor*>& parsed_files);
// Implements the --dependency_out option
bool GenerateDependencyManifestFile(
const std::vector<const FileDescriptor*>& parsed_files,
const GeneratorContextMap& output_directories,
DiskSourceTree* source_tree);
// Get all transitive dependencies of the given file (including the file
// itself), adding them to the given list of FileDescriptorProtos. The
// protos will be ordered such that every file is listed before any file that
// depends on it, so that you can call DescriptorPool::BuildFile() on them
// in order. Any files in *already_seen will not be added, and each file
// added will be inserted into *already_seen. If include_source_code_info is
// true then include the source code information in the FileDescriptorProtos.
// If include_json_name is true, populate the json_name field of
// FieldDescriptorProto for all fields.
static void GetTransitiveDependencies(
const FileDescriptor* file, bool include_json_name,
bool include_source_code_info,
std::set<const FileDescriptor*>* already_seen,
RepeatedPtrField<FileDescriptorProto>* output);
// Implements the --print_free_field_numbers. This function prints free field
// numbers into stdout for the message and it's nested message types in
// post-order, i.e. nested types first. Printed range are left-right
// inclusive, i.e. [a, b].
//
// Groups:
// For historical reasons, groups are considered to share the same
// field number space with the parent message, thus it will not print free
// field numbers for groups. The field numbers used in the groups are
// excluded in the free field numbers of the parent message.
//
// Extension Ranges:
// Extension ranges are considered ocuppied field numbers and they will not be
// listed as free numbers in the output.
void PrintFreeFieldNumbers(const Descriptor* descriptor);
// -----------------------------------------------------------------
// The name of the executable as invoked (i.e. argv[0]).
std::string executable_name_;
// Version info set with SetVersionInfo().
std::string version_info_;
// Registered generators.
struct GeneratorInfo {
std::string flag_name;
std::string option_flag_name;
CodeGenerator* generator;
std::string help_text;
};
typedef std::map<std::string, GeneratorInfo> GeneratorMap;
GeneratorMap generators_by_flag_name_;
GeneratorMap generators_by_option_name_;
// A map from generator names to the parameters specified using the option
// flag. For example, if the user invokes the compiler with:
// protoc --foo_out=outputdir --foo_opt=enable_bar ...
// Then there will be an entry ("--foo_out", "enable_bar") in this map.
std::map<std::string, std::string> generator_parameters_;
// Similar to generator_parameters_, but stores the parameters for plugins.
std::map<std::string, std::string> plugin_parameters_;
// See AllowPlugins(). If this is empty, plugins aren't allowed.
std::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.
std::map<std::string, std::string> plugins_;
// Stuff parsed from command line.
enum Mode {
MODE_COMPILE, // Normal mode: parse .proto files and compile them.
MODE_ENCODE, // --encode: read text from stdin, write binary to stdout.
MODE_DECODE, // --decode: read binary from stdin, write text to stdout.
MODE_PRINT, // Print mode: print info of the given .proto files and exit.
};
Mode mode_ = MODE_COMPILE;
enum PrintMode {
PRINT_NONE, // Not in MODE_PRINT
PRINT_FREE_FIELDS, // --print_free_fields
};
PrintMode print_mode_ = PRINT_NONE;
enum ErrorFormat {
ERROR_FORMAT_GCC, // GCC error output format (default).
ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs).
};
ErrorFormat error_format_ = ERROR_FORMAT_GCC;
// True if we should treat warnings as errors that fail the compilation.
bool fatal_warnings_ = false;
std::vector<std::pair<std::string, std::string> >
proto_path_; // Search path for proto files.
std::vector<std::string> input_files_; // Names of the input proto files.
// Names of proto files which are allowed to be imported. Used by build
// systems to enforce depend-on-what-you-import.
std::set<std::string> direct_dependencies_;
bool direct_dependencies_explicitly_set_ = false;
// If there's a violation of depend-on-what-you-import, this string will be
// presented to the user. "%s" will be replaced with the violating import.
std::string direct_dependencies_violation_msg_;
// output_directives_ lists all the files we are supposed to output and what
// generator to use for each.
struct OutputDirective {
std::string name; // E.g. "--foo_out"
CodeGenerator* generator; // NULL for plugins
std::string parameter;
std::string output_location;
};
std::vector<OutputDirective> output_directives_;
// When using --encode or --decode, this names the type we are encoding or
// decoding. (Empty string indicates --decode_raw.)
std::string codec_type_;
// If --descriptor_set_in was given, these are filenames containing
// parsed FileDescriptorSets to be used for loading protos. Otherwise, empty.
std::vector<std::string> descriptor_set_in_names_;
// If --descriptor_set_out was given, this is the filename to which the
// FileDescriptorSet should be written. Otherwise, empty.
std::string descriptor_set_out_name_;
// If --dependency_out was given, this is the path to the file where the
// dependency file will be written. Otherwise, empty.
std::string dependency_out_name_;
// True if --include_imports was given, meaning that we should
// write all transitive dependencies to the DescriptorSet. Otherwise, only
// the .proto files listed on the command-line are added.
bool imports_in_descriptor_set_;
// True if --include_source_info was given, meaning that we should not strip
// SourceCodeInfo from the DescriptorSet.
bool source_info_in_descriptor_set_ = false;
// Was the --disallow_services flag used?
bool disallow_services_ = false;
// When using --encode, this will be passed to SetSerializationDeterministic.
bool deterministic_output_ = false;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface);
};
} // namespace compiler
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,195 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// This test insures that net/proto2/proto/descriptor.pb.{h,cc} match exactly
// what would be generated by the protocol compiler. These files are not
// generated automatically at build time because they are compiled into the
// protocol compiler itself. So, if they were auto-generated, you'd have a
// chicken-and-egg problem.
//
// If this test fails, run the script
// "generate_descriptor_proto.sh" and add
// descriptor.pb.{h,cc} to your changelist.
#include <map>
#include <thirdparty/protobuf/testing/file.h>
#include <thirdparty/protobuf/testing/file.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_generator.h>
#include <thirdparty/protobuf/compiler/importer.h>
#include <thirdparty/protobuf/test_util2.h>
#include <thirdparty/protobuf/io/zero_copy_stream_impl.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <thirdparty/protobuf/stubs/substitute.h>
#include <thirdparty/protobuf/stubs/map_util.h>
#include <thirdparty/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
class MockErrorCollector : public MultiFileErrorCollector {
public:
MockErrorCollector() {}
~MockErrorCollector() {}
std::string text_;
// implements ErrorCollector ---------------------------------------
void AddError(const std::string& filename, int line, int column,
const std::string& message) {
strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
message);
}
};
class MockGeneratorContext : public GeneratorContext {
public:
void ExpectFileMatches(const std::string& virtual_filename,
const std::string& physical_filename) {
auto it = files_.find(virtual_filename);
ASSERT_TRUE(it != files_.end())
<< "Generator failed to generate file: " << virtual_filename;
std::string expected_contents = *it->second;
std::string actual_contents;
GOOGLE_CHECK_OK(
File::GetContents(TestUtil::TestSourceDir() + "/" + physical_filename,
&actual_contents, true))
<< physical_filename;
CleanStringLineEndings(&actual_contents, false);
#ifdef WRITE_FILES // Define to debug mismatched files.
GOOGLE_CHECK_OK(File::SetContents("/tmp/expected.cc", expected_contents,
true));
GOOGLE_CHECK_OK(
File::SetContents("/tmp/actual.cc", actual_contents, true));
#endif
ASSERT_EQ(expected_contents, actual_contents)
<< physical_filename
<< " needs to be regenerated. Please run "
"generate_descriptor_proto.sh. "
"Then add this file to your CL.";
}
// implements GeneratorContext --------------------------------------
virtual io::ZeroCopyOutputStream* Open(const std::string& filename) {
auto& map_slot = files_[filename];
map_slot.reset(new std::string);
return new io::StringOutputStream(map_slot.get());
}
private:
std::map<std::string, std::unique_ptr<std::string>> files_;
};
const char kDescriptorParameter[] = "dllexport_decl=PROTOBUF_EXPORT";
const char kPluginParameter[] = "dllexport_decl=PROTOC_EXPORT";
const char* test_protos[][2] = {
{"google/protobuf/descriptor", kDescriptorParameter},
{"google/protobuf/compiler/plugin", kPluginParameter},
};
TEST(BootstrapTest, GeneratedFilesMatch) {
// We need a mapping from the actual file to virtual and actual path
// of the data to compare to.
std::map<std::string, std::string> vpath_map;
std::map<std::string, std::string> rpath_map;
rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto2"] =
"net/proto2/z_generated_example/test_messages_proto2";
rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto3"] =
"net/proto2/z_generated_example/test_messages_proto3";
rpath_map["net/proto2/internal/proto2_weak"] =
"net/proto2/z_generated_example/proto2_weak";
DiskSourceTree source_tree;
source_tree.MapPath("", TestUtil::TestSourceDir());
for (auto file_parameter : test_protos) {
MockErrorCollector error_collector;
Importer importer(&source_tree, &error_collector);
const FileDescriptor* file =
importer.Import(file_parameter[0] + std::string(".proto"));
ASSERT_TRUE(file != nullptr)
<< "Can't import file " << file_parameter[0] + std::string(".proto")
<< "\n";
EXPECT_EQ("", error_collector.text_);
CppGenerator generator;
MockGeneratorContext context;
#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE
generator.set_opensource_runtime(true);
generator.set_runtime_include_base(GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE);
#endif
std::string error;
ASSERT_TRUE(generator.Generate(file, file_parameter[1], &context, &error));
std::string vpath =
FindWithDefault(vpath_map, file_parameter[0], file_parameter[0]);
std::string rpath =
FindWithDefault(rpath_map, file_parameter[0], file_parameter[0]);
context.ExpectFileMatches(vpath + ".pb.cc", rpath + ".pb.cc");
context.ExpectFileMatches(vpath + ".pb.h", rpath + ".pb.h");
}
}
// test Generate in cpp_generator.cc
TEST(BootstrapTest, OptionNotExist) {
cpp::CppGenerator generator;
DescriptorPool pool;
GeneratorContext* generator_context = nullptr;
std::string parameter = "aaa";
std::string error;
ASSERT_FALSE(generator.Generate(
pool.FindFileByName("google/protobuf/descriptor.proto"), parameter,
generator_context, &error));
EXPECT_EQ(error, "Unknown generator option: " + parameter);
}
} // namespace
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,438 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <thirdparty/protobuf/compiler/cpp/cpp_enum.h>
#include <cstdint>
#include <limits>
#include <map>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_names.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value
// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
// generation of the GOOGLE_ARRAYSIZE constant.
bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
int32_t max_value = descriptor->value(0)->number();
for (int i = 0; i < descriptor->value_count(); i++) {
if (descriptor->value(i)->number() > max_value) {
max_value = descriptor->value(i)->number();
}
}
return max_value != std::numeric_limits<int32_t>::max();
}
// Returns the number of unique numeric enum values. This is less than
// descriptor->value_count() when there are aliased values.
int CountUniqueValues(const EnumDescriptor* descriptor) {
std::set<int> values;
for (int i = 0; i < descriptor->value_count(); ++i) {
values.insert(descriptor->value(i)->number());
}
return values.size();
}
} // namespace
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
const std::map<std::string, std::string>& vars,
const Options& options)
: descriptor_(descriptor),
classname_(ClassName(descriptor, false)),
options_(options),
generate_array_size_(ShouldGenerateArraySize(descriptor)),
variables_(vars) {
variables_["classname"] = classname_;
variables_["classtype"] = QualifiedClassName(descriptor_, options);
variables_["short_name"] = descriptor_->name();
variables_["nested_name"] = descriptor_->name();
variables_["resolved_name"] = ResolveKeyword(descriptor_->name());
variables_["prefix"] =
(descriptor_->containing_type() == NULL) ? "" : classname_ + "_";
}
EnumGenerator::~EnumGenerator() {}
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
Formatter format(printer, variables_);
format("enum ${1$$classname$$}$ : int {\n", descriptor_);
format.Indent();
const EnumValueDescriptor* min_value = descriptor_->value(0);
const EnumValueDescriptor* max_value = descriptor_->value(0);
for (int i = 0; i < descriptor_->value_count(); i++) {
auto format_value = format;
format_value.Set("name", EnumValueName(descriptor_->value(i)));
// In C++, an value of -2147483648 gets interpreted as the negative of
// 2147483648, and since 2147483648 can't fit in an integer, this produces a
// compiler warning. This works around that issue.
format_value.Set("number", Int32ToString(descriptor_->value(i)->number()));
format_value.Set("deprecation",
DeprecatedAttribute(options_, descriptor_->value(i)));
if (i > 0) format_value(",\n");
format_value("${1$$prefix$$name$$}$ $deprecation$= $number$",
descriptor_->value(i));
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);
}
}
if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
// For new enum semantics: generate min and max sentinel values equal to
// INT32_MIN and INT32_MAX
if (descriptor_->value_count() > 0) format(",\n");
format(
"$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = "
"std::numeric_limits<$int32$>::min(),\n"
"$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = "
"std::numeric_limits<$int32$>::max()");
}
format.Outdent();
format("\n};\n");
format(
"$dllexport_decl $bool $classname$_IsValid(int value);\n"
"constexpr $classname$ ${1$$prefix$$short_name$_MIN$}$ = "
"$prefix$$2$;\n"
"constexpr $classname$ ${1$$prefix$$short_name$_MAX$}$ = "
"$prefix$$3$;\n",
descriptor_, EnumValueName(min_value), EnumValueName(max_value));
if (generate_array_size_) {
format(
"constexpr int ${1$$prefix$$short_name$_ARRAYSIZE$}$ = "
"$prefix$$short_name$_MAX + 1;\n\n",
descriptor_);
}
if (HasDescriptorMethods(descriptor_->file(), options_)) {
format(
"$dllexport_decl $const ::$proto_ns$::EnumDescriptor* "
"$classname$_descriptor();\n");
}
// The _Name and _Parse functions. The lite implementation is table-based, so
// we make sure to keep the tables hidden in the .cc file.
if (!HasDescriptorMethods(descriptor_->file(), options_)) {
format("const std::string& $classname$_Name($classname$ value);\n");
}
// The _Name() function accepts the enum type itself but also any integral
// type.
format(
"template<typename T>\n"
"inline const std::string& $classname$_Name(T enum_t_value) {\n"
" static_assert(::std::is_same<T, $classname$>::value ||\n"
" ::std::is_integral<T>::value,\n"
" \"Incorrect type passed to function $classname$_Name.\");\n");
if (HasDescriptorMethods(descriptor_->file(), options_)) {
format(
" return ::$proto_ns$::internal::NameOfEnum(\n"
" $classname$_descriptor(), enum_t_value);\n");
} else {
format(
" return $classname$_Name(static_cast<$classname$>(enum_t_value));\n");
}
format("}\n");
if (HasDescriptorMethods(descriptor_->file(), options_)) {
format(
"inline bool $classname$_Parse(\n"
" ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
"value) "
"{\n"
" return ::$proto_ns$::internal::ParseNamedEnum<$classname$>(\n"
" $classname$_descriptor(), name, value);\n"
"}\n");
} else {
format(
"bool $classname$_Parse(\n"
" ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
"value);\n");
}
}
void EnumGenerator::GenerateGetEnumDescriptorSpecializations(
io::Printer* printer) {
Formatter format(printer, variables_);
format(
"template <> struct is_proto_enum< $classtype$> : ::std::true_type "
"{};\n");
if (HasDescriptorMethods(descriptor_->file(), options_)) {
format(
"template <>\n"
"inline const EnumDescriptor* GetEnumDescriptor< $classtype$>() {\n"
" return $classtype$_descriptor();\n"
"}\n");
}
}
void EnumGenerator::GenerateSymbolImports(io::Printer* printer) const {
Formatter format(printer, variables_);
format("typedef $classname$ $resolved_name$;\n");
for (int j = 0; j < descriptor_->value_count(); j++) {
std::string deprecated_attr =
DeprecatedAttribute(options_, descriptor_->value(j));
format(
"$1$static constexpr $resolved_name$ ${2$$3$$}$ =\n"
" $classname$_$3$;\n",
deprecated_attr, descriptor_->value(j),
EnumValueName(descriptor_->value(j)));
}
format(
"static inline bool $nested_name$_IsValid(int value) {\n"
" return $classname$_IsValid(value);\n"
"}\n"
"static constexpr $resolved_name$ ${1$$nested_name$_MIN$}$ =\n"
" $classname$_$nested_name$_MIN;\n"
"static constexpr $resolved_name$ ${1$$nested_name$_MAX$}$ =\n"
" $classname$_$nested_name$_MAX;\n",
descriptor_);
if (generate_array_size_) {
format(
"static constexpr int ${1$$nested_name$_ARRAYSIZE$}$ =\n"
" $classname$_$nested_name$_ARRAYSIZE;\n",
descriptor_);
}
if (HasDescriptorMethods(descriptor_->file(), options_)) {
format(
"static inline const ::$proto_ns$::EnumDescriptor*\n"
"$nested_name$_descriptor() {\n"
" return $classname$_descriptor();\n"
"}\n");
}
format(
"template<typename T>\n"
"static inline const std::string& $nested_name$_Name(T enum_t_value) {\n"
" static_assert(::std::is_same<T, $resolved_name$>::value ||\n"
" ::std::is_integral<T>::value,\n"
" \"Incorrect type passed to function $nested_name$_Name.\");\n"
" return $classname$_Name(enum_t_value);\n"
"}\n");
format(
"static inline bool "
"$nested_name$_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,\n"
" $resolved_name$* value) {\n"
" return $classname$_Parse(name, value);\n"
"}\n");
}
void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) {
Formatter format(printer, variables_);
if (HasDescriptorMethods(descriptor_->file(), options_)) {
format(
"const ::$proto_ns$::EnumDescriptor* $classname$_descriptor() {\n"
" ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n"
" return $file_level_enum_descriptors$[$1$];\n"
"}\n",
idx);
}
format(
"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.
std::set<int> numbers;
for (int j = 0; j < descriptor_->value_count(); j++) {
const EnumValueDescriptor* value = descriptor_->value(j);
numbers.insert(value->number());
}
for (std::set<int>::iterator iter = numbers.begin(); iter != numbers.end();
++iter) {
format(" case $1$:\n", Int32ToString(*iter));
}
format(
" return true;\n"
" default:\n"
" return false;\n"
" }\n"
"}\n"
"\n");
if (!HasDescriptorMethods(descriptor_->file(), options_)) {
// In lite mode (where descriptors are unavailable), we generate separate
// tables for mapping between enum names and numbers. The _entries table
// contains the bulk of the data and is sorted by name, while
// _entries_by_number is sorted by number and just contains pointers into
// _entries. The two tables allow mapping from name to number and number to
// name, both in time logarithmic in the number of enum entries. This could
// probably be made faster, but for now the tables are intended to be simple
// and compact.
//
// Enums with allow_alias = true support multiple entries with the same
// numerical value. In cases where there are multiple names for the same
// number, we treat the first name appearing in the .proto file as the
// canonical one.
std::map<std::string, int> name_to_number;
std::map<int, std::string> number_to_canonical_name;
for (int i = 0; i < descriptor_->value_count(); i++) {
const EnumValueDescriptor* value = descriptor_->value(i);
name_to_number.emplace(value->name(), value->number());
// The same number may appear with multiple names, so we use emplace() to
// let the first name win.
number_to_canonical_name.emplace(value->number(), value->name());
}
format(
"static ::$proto_ns$::internal::ExplicitlyConstructed<std::string> "
"$classname$_strings[$1$] = {};\n\n",
CountUniqueValues(descriptor_));
// We concatenate all the names for a given enum into one big string
// literal. If instead we store an array of string literals, the linker
// seems to put all enum strings for a given .proto file in the same
// section, which hinders its ability to strip out unused strings.
format("static const char $classname$_names[] =");
for (const auto& p : name_to_number) {
format("\n \"$1$\"", p.first);
}
format(";\n\n");
format(
"static const ::$proto_ns$::internal::EnumEntry $classname$_entries[] "
"= {\n");
int i = 0;
std::map<int, int> number_to_index;
int data_index = 0;
for (const auto& p : name_to_number) {
format(" { {$classname$_names + $1$, $2$}, $3$ },\n", data_index,
p.first.size(), p.second);
if (number_to_canonical_name[p.second] == p.first) {
number_to_index.emplace(p.second, i);
}
++i;
data_index += p.first.size();
}
format(
"};\n"
"\n"
"static const int $classname$_entries_by_number[] = {\n");
for (const auto& p : number_to_index) {
format(" $1$, // $2$ -> $3$\n", p.second, p.first,
number_to_canonical_name[p.first]);
}
format(
"};\n"
"\n");
format(
"const std::string& $classname$_Name(\n"
" $classname$ value) {\n"
" static const bool dummy =\n"
" ::$proto_ns$::internal::InitializeEnumStrings(\n"
" $classname$_entries,\n"
" $classname$_entries_by_number,\n"
" $1$, $classname$_strings);\n"
" (void) dummy;\n"
" int idx = ::$proto_ns$::internal::LookUpEnumName(\n"
" $classname$_entries,\n"
" $classname$_entries_by_number,\n"
" $1$, value);\n"
" return idx == -1 ? ::$proto_ns$::internal::GetEmptyString() :\n"
" $classname$_strings[idx].get();\n"
"}\n",
CountUniqueValues(descriptor_));
format(
"bool $classname$_Parse(\n"
" ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
"value) "
"{\n"
" int int_value;\n"
" bool success = ::$proto_ns$::internal::LookUpEnumValue(\n"
" $classname$_entries, $1$, name, &int_value);\n"
" if (success) {\n"
" *value = static_cast<$classname$>(int_value);\n"
" }\n"
" return success;\n"
"}\n",
descriptor_->value_count());
}
if (descriptor_->containing_type() != NULL) {
std::string parent = ClassName(descriptor_->containing_type(), false);
// Before C++17, we must define the static constants which were
// declared in the header, to give the linker a place to put them.
// But MSVC++ pre-2015 and post-2017 (version 15.5+) insists that we not.
format(
"#if (__cplusplus < 201703) && "
"(!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))\n");
for (int i = 0; i < descriptor_->value_count(); i++) {
format("constexpr $classname$ $1$::$2$;\n", parent,
EnumValueName(descriptor_->value(i)));
}
format(
"constexpr $classname$ $1$::$nested_name$_MIN;\n"
"constexpr $classname$ $1$::$nested_name$_MAX;\n",
parent);
if (generate_array_size_) {
format("constexpr int $1$::$nested_name$_ARRAYSIZE;\n", parent);
}
format(
"#endif // (__cplusplus < 201703) && "
"(!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))\n");
}
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,105 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
#include <map>
#include <set>
#include <string>
#include <thirdparty/protobuf/compiler/cpp/cpp_options.h>
#include <thirdparty/protobuf/descriptor.h>
namespace google {
namespace protobuf {
namespace io {
class Printer; // printer.h
}
} // namespace protobuf
} // namespace google
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class EnumGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
EnumGenerator(const EnumDescriptor* descriptor,
const std::map<std::string, std::string>& vars,
const Options& options);
~EnumGenerator();
// Generate header code defining the enum. This code should be placed
// within the enum's package namespace, but NOT within any class, even for
// nested enums.
void GenerateDefinition(io::Printer* printer);
// Generate specialization of GetEnumDescriptor<MyEnum>().
// Precondition: in ::google::protobuf namespace.
void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
// For enums nested within a message, generate code to import all the enum's
// symbols (e.g. the enum type name, all its values, etc.) into the class's
// namespace. This should be placed inside the class definition in the
// header.
void GenerateSymbolImports(io::Printer* printer) const;
// Source file stuff.
// Generate non-inline methods related to the enum, such as IsValidValue().
// Goes in the .cc file. EnumDescriptors are stored in an array, idx is
// the index in this array that corresponds with this enum.
void GenerateMethods(int idx, io::Printer* printer);
private:
const EnumDescriptor* descriptor_;
const std::string classname_;
const Options& options_;
// whether to generate the *_ARRAYSIZE constant.
const bool generate_array_size_;
std::map<std::string, std::string> variables_;
friend class FileGenerator;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__

View File

@ -0,0 +1,406 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <thirdparty/protobuf/compiler/cpp/cpp_enum_field.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/wire_format.h>
#include <thirdparty/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
void SetEnumVariables(const FieldDescriptor* descriptor,
std::map<std::string, std::string>* variables,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
(*variables)["type"] = QualifiedClassName(descriptor->enum_type(), options);
(*variables)["default"] = Int32ToString(default_value->number());
(*variables)["full_name"] = descriptor->full_name();
}
} // namespace
// ===================================================================
EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: FieldGenerator(descriptor, options) {
SetEnumVariables(descriptor, &variables_, options);
}
EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
Formatter format(printer, variables_);
format("int $name$_;\n");
}
void EnumFieldGenerator::GenerateAccessorDeclarations(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
"$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
"private:\n"
"$type$ ${1$_internal_$name$$}$() const;\n"
"void ${1$_internal_set_$name$$}$($type$ value);\n"
"public:\n",
descriptor_);
}
void EnumFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline $type$ $classname$::_internal_$name$() const {\n"
" return static_cast< $type$ >($name$_);\n"
"}\n"
"inline $type$ $classname$::$name$() const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$();\n"
"}\n"
"inline void $classname$::_internal_set_$name$($type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
format(" assert($type$_IsValid(value));\n");
}
format(
" $set_hasbit$\n"
" $name$_ = value;\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
" _internal_set_$name$(value);\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
}
void EnumFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_ = $default$;\n");
}
void EnumFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
format("_internal_set_$name$(from._internal_$name$());\n");
}
void EnumFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
format("swap($name$_, other->$name$_);\n");
}
void EnumFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_ = $default$;\n");
}
void EnumFieldGenerator::GenerateCopyConstructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_ = from.$name$_;\n");
}
void EnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"target = stream->EnsureSpace(target);\n"
"target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n"
" $number$, this->_internal_$name$(), target);\n");
}
void EnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"total_size += $tag_size$ +\n"
" "
"::$proto_ns$::internal::WireFormatLite::EnumSize(this->_internal_$name$("
"));\n");
}
void EnumFieldGenerator::GenerateConstinitInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_($default$)\n");
}
// ===================================================================
EnumOneofFieldGenerator::EnumOneofFieldGenerator(
const FieldDescriptor* descriptor, const Options& options)
: EnumFieldGenerator(descriptor, options) {
SetCommonOneofFieldVariables(descriptor, &variables_);
}
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
void EnumOneofFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline $type$ $classname$::_internal_$name$() const {\n"
" if (_internal_has_$name$()) {\n"
" return static_cast< $type$ >($field_member$);\n"
" }\n"
" return static_cast< $type$ >($default$);\n"
"}\n"
"inline $type$ $classname$::$name$() const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$();\n"
"}\n"
"inline void $classname$::_internal_set_$name$($type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
format(" assert($type$_IsValid(value));\n");
}
format(
" if (!_internal_has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" }\n"
" $field_member$ = value;\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
" _internal_set_$name$(value);\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
}
void EnumOneofFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
format("$field_member$ = $default$;\n");
}
void EnumOneofFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
// Don't print any swapping code. Swapping the union will swap this field.
}
void EnumOneofFieldGenerator::GenerateConstructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
}
// ===================================================================
RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
const FieldDescriptor* descriptor, const Options& options)
: FieldGenerator(descriptor, options) {
SetEnumVariables(descriptor, &variables_, options);
}
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
void RepeatedEnumFieldGenerator::GeneratePrivateMembers(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("::$proto_ns$::RepeatedField<int> $name$_;\n");
if (descriptor_->is_packed() &&
HasGeneratedMethods(descriptor_->file(), options_)) {
format("mutable std::atomic<int> _$name$_cached_byte_size_;\n");
}
}
void RepeatedEnumFieldGenerator::GenerateAccessorDeclarations(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"private:\n"
"$type$ ${1$_internal_$name$$}$(int index) const;\n"
"void ${1$_internal_add_$name$$}$($type$ value);\n"
"::$proto_ns$::RepeatedField<int>* "
"${1$_internal_mutable_$name$$}$();\n"
"public:\n"
"$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
"$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
"$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
"$deprecated_attr$const ::$proto_ns$::RepeatedField<int>& "
"${1$$name$$}$() const;\n"
"$deprecated_attr$::$proto_ns$::RepeatedField<int>* "
"${1$mutable_$name$$}$();\n",
descriptor_);
}
void RepeatedEnumFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline $type$ $classname$::_internal_$name$(int index) const {\n"
" return static_cast< $type$ >($name$_.Get(index));\n"
"}\n"
"inline $type$ $classname$::$name$(int index) const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$(index);\n"
"}\n"
"inline void $classname$::set_$name$(int index, $type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
format(" assert($type$_IsValid(value));\n");
}
format(
" $name$_.Set(index, value);\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::_internal_add_$name$($type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
format(" assert($type$_IsValid(value));\n");
}
format(
" $name$_.Add(value);\n"
"}\n"
"inline void $classname$::add_$name$($type$ value) {\n"
" _internal_add_$name$(value);\n"
"$annotate_add$"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n"
"inline const ::$proto_ns$::RepeatedField<int>&\n"
"$classname$::$name$() const {\n"
"$annotate_list$"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
"inline ::$proto_ns$::RepeatedField<int>*\n"
"$classname$::_internal_mutable_$name$() {\n"
" return &$name$_;\n"
"}\n"
"inline ::$proto_ns$::RepeatedField<int>*\n"
"$classname$::mutable_$name$() {\n"
"$annotate_mutable_list$"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return _internal_mutable_$name$();\n"
"}\n");
}
void RepeatedEnumFieldGenerator::GenerateClearingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.Clear();\n");
}
void RepeatedEnumFieldGenerator::GenerateMergingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.MergeFrom(from.$name$_);\n");
}
void RepeatedEnumFieldGenerator::GenerateSwappingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.InternalSwap(&other->$name$_);\n");
}
void RepeatedEnumFieldGenerator::GenerateConstructorCode(
io::Printer* printer) const {
// Not needed for repeated fields.
}
void RepeatedEnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (descriptor_->is_packed()) {
// Write the tag and the size.
format(
"{\n"
" int byte_size = "
"_$name$_cached_byte_size_.load(std::memory_order_relaxed);\n"
" if (byte_size > 0) {\n"
" target = stream->WriteEnumPacked(\n"
" $number$, $name$_, byte_size, target);\n"
" }\n"
"}\n");
} else {
format(
"for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
" target = stream->EnsureSpace(target);\n"
" target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n"
" $number$, this->_internal_$name$(i), target);\n"
"}\n");
}
}
void RepeatedEnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"{\n"
" size_t data_size = 0;\n"
" unsigned int count = static_cast<unsigned "
"int>(this->_internal_$name$_size());");
format.Indent();
format(
"for (unsigned int i = 0; i < count; i++) {\n"
" data_size += ::$proto_ns$::internal::WireFormatLite::EnumSize(\n"
" this->_internal_$name$(static_cast<int>(i)));\n"
"}\n");
if (descriptor_->is_packed()) {
format(
"if (data_size > 0) {\n"
" total_size += $tag_size$ +\n"
" ::$proto_ns$::internal::WireFormatLite::Int32Size(\n"
" static_cast<$int32$>(data_size));\n"
"}\n"
"int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
"_$name$_cached_byte_size_.store(cached_size,\n"
" std::memory_order_relaxed);\n"
"total_size += data_size;\n");
} else {
format("total_size += ($tag_size$UL * count) + data_size;\n");
}
format.Outdent();
format("}\n");
}
void RepeatedEnumFieldGenerator::GenerateConstinitInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_()");
if (descriptor_->is_packed() &&
HasGeneratedMethods(descriptor_->file(), options_)) {
format("\n, _$name$_cached_byte_size_(0)");
}
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,115 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
#include <map>
#include <string>
#include <thirdparty/protobuf/compiler/cpp/cpp_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class EnumFieldGenerator : public FieldGenerator {
public:
EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
~EnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const override;
void GenerateAccessorDeclarations(io::Printer* printer) const override;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
void GenerateCopyConstructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
void GenerateConstinitInitializer(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
};
class EnumOneofFieldGenerator : public EnumFieldGenerator {
public:
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~EnumOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator);
};
class RepeatedEnumFieldGenerator : public FieldGenerator {
public:
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~RepeatedEnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const override;
void GenerateAccessorDeclarations(io::Printer* printer) const override;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
void GenerateCopyConstructorCode(io::Printer* printer) const override {}
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
void GenerateConstinitInitializer(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__

View File

@ -0,0 +1,189 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <thirdparty/protobuf/compiler/cpp/cpp_extension.h>
#include <map>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
const Options& options,
MessageSCCAnalyzer* scc_analyzer)
: descriptor_(descriptor), options_(options), scc_analyzer_(scc_analyzer) {
// 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(options_, descriptor_->cpp_type()));
type_traits_.append(" >");
break;
}
SetCommonVars(options, &variables_);
variables_["extendee"] =
QualifiedClassName(descriptor_->containing_type(), options_);
variables_["type_traits"] = type_traits_;
std::string name = descriptor_->name();
variables_["name"] = ResolveKeyword(name);
variables_["constant_name"] = FieldConstantName(descriptor_);
variables_["field_type"] =
StrCat(static_cast<int>(descriptor_->type()));
variables_["packed"] = descriptor_->is_packed() ? "true" : "false";
std::string scope =
IsScoped() ? ClassName(descriptor_->extension_scope(), false) + "::" : "";
variables_["scope"] = scope;
variables_["scoped_name"] = ExtensionName(descriptor_);
variables_["number"] = StrCat(descriptor_->number());
}
ExtensionGenerator::~ExtensionGenerator() {}
bool ExtensionGenerator::IsScoped() const {
return descriptor_->extension_scope() != nullptr;
}
void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) const {
Formatter format(printer, variables_);
// 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.
std::string qualifier;
if (!IsScoped()) {
qualifier = "extern";
if (!options_.dllexport_decl.empty()) {
qualifier = options_.dllexport_decl + " " + qualifier;
}
} else {
qualifier = "static";
}
format(
"static const int $constant_name$ = $number$;\n"
"$1$ ::$proto_ns$::internal::ExtensionIdentifier< $extendee$,\n"
" ::$proto_ns$::internal::$type_traits$, $field_type$, $packed$ >\n"
" ${2$$name$$}$;\n",
qualifier, descriptor_);
}
void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
// If we are building for lite with implicit weak fields, we want to skip over
// any custom options (i.e. extensions of messages from descriptor.proto).
// This prevents the creation of any unnecessary linker references to the
// descriptor messages.
if (options_.lite_implicit_weak_fields &&
descriptor_->containing_type()->file()->name() ==
"net/proto2/proto/descriptor.proto") {
return;
}
Formatter format(printer, variables_);
std::string default_str;
// If this is a class member, it needs to be declared in its class 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.
default_str =
StringReplace(variables_["scoped_name"], "::", "_", true) + "_default";
format("const std::string $1$($2$);\n", default_str,
DefaultValue(options_, descriptor_));
} else if (descriptor_->message_type()) {
// We have to initialize the default instance for extensions at registration
// time.
default_str =
FieldMessageTypeName(descriptor_, options_) + "::default_instance()";
} else {
default_str = DefaultValue(options_, descriptor_);
}
// Likewise, class members need to declare the field constant variable.
if (IsScoped()) {
format(
"#if !defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)\n"
"const int $scope$$constant_name$;\n"
"#endif\n");
}
format(
"PROTOBUF_ATTRIBUTE_INIT_PRIORITY "
"::$proto_ns$::internal::ExtensionIdentifier< $extendee$,\n"
" ::$proto_ns$::internal::$type_traits$, $field_type$, $packed$ >\n"
" $scoped_name$($constant_name$, $1$);\n",
default_str);
// Register extension verify function if needed.
if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
ShouldVerify(descriptor_->message_type(), options_, scc_analyzer_) &&
ShouldVerify(descriptor_->containing_type(), options_, scc_analyzer_)) {
format(
"PROTOBUF_ATTRIBUTE_INIT_PRIORITY "
"::$proto_ns$::internal::RegisterExtensionVerify< $extendee$,\n"
" $1$, $number$> $2$_$name$_register;\n",
ClassName(descriptor_->message_type(), true),
IsScoped() ? ClassName(descriptor_->extension_scope(), false) : "");
}
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,95 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
#include <map>
#include <string>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_options.h>
namespace google {
namespace protobuf {
class FieldDescriptor; // descriptor.h
namespace io {
class Printer; // printer.h
}
} // namespace protobuf
} // namespace google
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class MessageSCCAnalyzer;
// Generates code for an extension, which may be within the scope of some
// message or may be at file scope. This is much simpler than FieldGenerator
// since extensions are just simple identifiers with interesting types.
class ExtensionGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
explicit ExtensionGenerator(const FieldDescriptor* descriptor,
const Options& options,
MessageSCCAnalyzer* scc_analyzer);
~ExtensionGenerator();
// Header stuff.
void GenerateDeclaration(io::Printer* printer) const;
// Source file stuff.
void GenerateDefinition(io::Printer* printer);
bool IsScoped() const;
private:
const FieldDescriptor* descriptor_;
std::string type_traits_;
Options options_;
MessageSCCAnalyzer* scc_analyzer_;
std::map<std::string, std::string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__

View File

@ -0,0 +1,391 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <thirdparty/protobuf/compiler/cpp/cpp_field.h>
#include <cstdint>
#include <memory>
#include <string>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_primitive_field.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_string_field.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/stubs/substitute.h>
#include <thirdparty/protobuf/stubs/logging.h>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_enum_field.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_map_field.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_message_field.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/wire_format.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
using internal::WireFormat;
namespace {
void MaySetAnnotationVariable(const Options& options,
StringPiece annotation_name,
StringPiece substitute_template_prefix,
StringPiece prepared_template,
int field_index, StringPiece access_type,
std::map<std::string, std::string>* variables) {
if (options.field_listener_options.forbidden_field_listener_events.count(
std::string(annotation_name)))
return;
(*variables)[StrCat("annotate_", annotation_name)] = strings::Substitute(
StrCat(substitute_template_prefix, prepared_template, ");\n"),
field_index, access_type);
}
std::string GenerateTemplateForOneofString(const FieldDescriptor* descriptor,
StringPiece proto_ns,
StringPiece field_member) {
std::string field_name = google::protobuf::compiler::cpp::FieldName(descriptor);
std::string field_pointer =
descriptor->options().ctype() == google::protobuf::FieldOptions::STRING
? "$0.GetPointer()"
: "$0";
if (descriptor->default_value_string().empty()) {
return strings::Substitute(StrCat("_internal_has_", field_name, "() ? ",
field_pointer, ": nullptr"),
field_member);
}
if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING_PIECE) {
return strings::Substitute(StrCat("_internal_has_", field_name, "() ? ",
field_pointer, ": nullptr"),
field_member);
}
std::string default_value_pointer =
descriptor->options().ctype() == google::protobuf::FieldOptions::STRING
? "&$1.get()"
: "&$1";
return strings::Substitute(
StrCat("_internal_has_", field_name, "() ? ", field_pointer, " : ",
default_value_pointer),
field_member, MakeDefaultName(descriptor));
}
std::string GenerateTemplateForSingleString(const FieldDescriptor* descriptor,
StringPiece field_member) {
if (descriptor->default_value_string().empty()) {
return StrCat("&", field_member);
}
if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING) {
return strings::Substitute(
"$0.IsDefault(nullptr) ? &$1.get() : $0.GetPointer()", field_member,
MakeDefaultName(descriptor));
}
return StrCat("&", field_member);
}
} // namespace
void AddAccessorAnnotations(const FieldDescriptor* descriptor,
const Options& options,
std::map<std::string, std::string>* variables) {
// Can be expanded to include more specific calls, for example, for arena or
// clear calls.
static constexpr const char* kAccessorsAnnotations[] = {
"annotate_add", "annotate_get", "annotate_has",
"annotate_list", "annotate_mutable", "annotate_mutable_list",
"annotate_release", "annotate_set", "annotate_size",
"annotate_clear", "annotate_add_mutable",
};
for (size_t i = 0; i < GOOGLE_ARRAYSIZE(kAccessorsAnnotations); ++i) {
(*variables)[kAccessorsAnnotations[i]] = "";
}
if (options.annotate_accessor) {
for (size_t i = 0; i < GOOGLE_ARRAYSIZE(kAccessorsAnnotations); ++i) {
(*variables)[kAccessorsAnnotations[i]] = StrCat(
" ", FieldName(descriptor), "_AccessedNoStrip = true;\n");
}
}
if (!options.field_listener_options.inject_field_listener_events) {
return;
}
if (descriptor->file()->options().optimize_for() ==
google::protobuf::FileOptions::LITE_RUNTIME) {
return;
}
std::string field_member = (*variables)["field_member"];
const google::protobuf::OneofDescriptor* oneof_member =
descriptor->real_containing_oneof();
if (oneof_member) {
field_member = StrCat(oneof_member->name(), "_.", field_member);
}
const std::string proto_ns = (*variables)["proto_ns"];
const std::string substitute_template_prefix = " _tracker_.$1<$0>(this, ";
std::string prepared_template;
// Flat template is needed if the prepared one is introspecting the values
// inside the returned values, for example, for repeated fields and maps.
std::string prepared_flat_template;
std::string prepared_add_template;
// TODO(b/190614678): Support fields with type Message or Map.
if (descriptor->is_repeated() && !descriptor->is_map()) {
if (descriptor->type() != FieldDescriptor::TYPE_MESSAGE &&
descriptor->type() != FieldDescriptor::TYPE_GROUP) {
prepared_template = strings::Substitute("&$0.Get(index)", field_member);
prepared_add_template =
strings::Substitute("&$0.Get($0.size() - 1)", field_member);
} else {
prepared_template = "nullptr";
prepared_add_template = "nullptr";
}
} else if (descriptor->is_map()) {
prepared_template = "nullptr";
} else if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
!descriptor->options().lazy()) {
prepared_template = "nullptr";
} else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
if (oneof_member) {
prepared_template = GenerateTemplateForOneofString(
descriptor, (*variables)["proto_ns"], field_member);
} else {
prepared_template =
GenerateTemplateForSingleString(descriptor, field_member);
}
} else {
prepared_template = StrCat("&", field_member);
}
if (descriptor->is_repeated() && !descriptor->is_map() &&
descriptor->type() != FieldDescriptor::TYPE_MESSAGE &&
descriptor->type() != FieldDescriptor::TYPE_GROUP) {
prepared_flat_template = StrCat("&", field_member);
} else {
prepared_flat_template = prepared_template;
}
MaySetAnnotationVariable(options, "get", substitute_template_prefix,
prepared_template, descriptor->index(), "OnGet",
variables);
MaySetAnnotationVariable(options, "set", substitute_template_prefix,
prepared_template, descriptor->index(), "OnSet",
variables);
MaySetAnnotationVariable(options, "has", substitute_template_prefix,
prepared_template, descriptor->index(), "OnHas",
variables);
MaySetAnnotationVariable(options, "mutable", substitute_template_prefix,
prepared_template, descriptor->index(), "OnMutable",
variables);
MaySetAnnotationVariable(options, "release", substitute_template_prefix,
prepared_template, descriptor->index(), "OnRelease",
variables);
MaySetAnnotationVariable(options, "clear", substitute_template_prefix,
prepared_flat_template, descriptor->index(),
"OnClear", variables);
MaySetAnnotationVariable(options, "size", substitute_template_prefix,
prepared_flat_template, descriptor->index(),
"OnSize", variables);
MaySetAnnotationVariable(options, "list", substitute_template_prefix,
prepared_flat_template, descriptor->index(),
"OnList", variables);
MaySetAnnotationVariable(options, "mutable_list", substitute_template_prefix,
prepared_flat_template, descriptor->index(),
"OnMutableList", variables);
MaySetAnnotationVariable(options, "add", substitute_template_prefix,
prepared_add_template, descriptor->index(), "OnAdd",
variables);
MaySetAnnotationVariable(options, "add_mutable", substitute_template_prefix,
prepared_add_template, descriptor->index(),
"OnAddMutable", variables);
}
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
std::map<std::string, std::string>* variables,
const Options& options) {
SetCommonVars(options, variables);
(*variables)["ns"] = Namespace(descriptor, options);
(*variables)["name"] = FieldName(descriptor);
(*variables)["index"] = StrCat(descriptor->index());
(*variables)["number"] = StrCat(descriptor->number());
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
(*variables)["field_member"] = FieldName(descriptor) + "_";
(*variables)["tag_size"] = StrCat(
WireFormat::TagSize(descriptor->number(), descriptor->type()));
(*variables)["deprecated_attr"] = DeprecatedAttribute(options, descriptor);
(*variables)["set_hasbit"] = "";
(*variables)["clear_hasbit"] = "";
if (HasHasbit(descriptor)) {
(*variables)["set_hasbit_io"] =
"_Internal::set_has_" + FieldName(descriptor) + "(&_has_bits_);";
} else {
(*variables)["set_hasbit_io"] = "";
}
AddAccessorAnnotations(descriptor, options, variables);
// These variables are placeholders to pick out the beginning and ends of
// identifiers for annotations (when doing so with existing variables would
// be ambiguous or impossible). They should never be set to anything but the
// empty string.
(*variables)["{"] = "";
(*variables)["}"] = "";
}
void FieldGenerator::SetHasBitIndex(int32_t has_bit_index) {
if (!HasHasbit(descriptor_)) {
GOOGLE_CHECK_EQ(has_bit_index, -1);
return;
}
variables_["set_hasbit"] = StrCat(
"_has_bits_[", has_bit_index / 32, "] |= 0x",
strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;");
variables_["clear_hasbit"] = StrCat(
"_has_bits_[", has_bit_index / 32, "] &= ~0x",
strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;");
}
void FieldGenerator::SetInlinedStringIndex(int32_t inlined_string_index) {
if (!IsStringInlined(descriptor_, options_)) {
GOOGLE_CHECK_EQ(inlined_string_index, -1);
return;
}
variables_["inlined_string_donated"] = StrCat(
"(_inlined_string_donated_[", inlined_string_index / 32, "] & 0x",
strings::Hex(1u << (inlined_string_index % 32), strings::ZERO_PAD_8),
"u) != 0;");
variables_["donating_states_word"] =
StrCat("_inlined_string_donated_[", inlined_string_index / 32, "]");
variables_["mask_for_undonate"] = StrCat(
"~0x", strings::Hex(1u << (inlined_string_index % 32), strings::ZERO_PAD_8),
"u");
}
void SetCommonOneofFieldVariables(
const FieldDescriptor* descriptor,
std::map<std::string, std::string>* variables) {
const std::string prefix = descriptor->containing_oneof()->name() + "_.";
(*variables)["oneof_name"] = descriptor->containing_oneof()->name();
(*variables)["field_member"] =
StrCat(prefix, (*variables)["name"], "_");
}
FieldGenerator::~FieldGenerator() {}
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
const Options& options,
MessageSCCAnalyzer* scc_analyzer)
: descriptor_(descriptor), field_generators_(descriptor->field_count()) {
// Construct all the FieldGenerators.
for (int i = 0; i < descriptor->field_count(); i++) {
field_generators_[i].reset(
MakeGenerator(descriptor->field(i), options, scc_analyzer));
}
}
FieldGenerator* FieldGeneratorMap::MakeGoogleInternalGenerator(
const FieldDescriptor* field, const Options& options,
MessageSCCAnalyzer* scc_analyzer) {
return nullptr;
}
FieldGenerator* FieldGeneratorMap::MakeGenerator(
const FieldDescriptor* field, const Options& options,
MessageSCCAnalyzer* scc_analyzer) {
FieldGenerator* generator =
MakeGoogleInternalGenerator(field, options, scc_analyzer);
if (generator) {
return generator;
}
if (field->is_repeated()) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
if (field->is_map()) {
return new MapFieldGenerator(field, options, scc_analyzer);
} else {
return new RepeatedMessageFieldGenerator(field, options,
scc_analyzer);
}
case FieldDescriptor::CPPTYPE_STRING:
return new RepeatedStringFieldGenerator(field, options);
case FieldDescriptor::CPPTYPE_ENUM:
return new RepeatedEnumFieldGenerator(field, options);
default:
return new RepeatedPrimitiveFieldGenerator(field, options);
}
} else if (field->real_containing_oneof()) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
return new MessageOneofFieldGenerator(field, options, scc_analyzer);
case FieldDescriptor::CPPTYPE_STRING:
return new StringOneofFieldGenerator(field, options);
case FieldDescriptor::CPPTYPE_ENUM:
return new EnumOneofFieldGenerator(field, options);
default:
return new PrimitiveOneofFieldGenerator(field, options);
}
} else {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
return new MessageFieldGenerator(field, options, scc_analyzer);
case FieldDescriptor::CPPTYPE_STRING:
return new StringFieldGenerator(field, options);
case FieldDescriptor::CPPTYPE_ENUM:
return new EnumFieldGenerator(field, options);
default:
return new PrimitiveFieldGenerator(field, options);
}
}
}
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

View File

@ -0,0 +1,242 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_options.h>
#include <thirdparty/protobuf/descriptor.h>
namespace google {
namespace protobuf {
namespace io {
class Printer; // printer.h
}
} // namespace protobuf
} // namespace google
namespace google {
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,
std::map<std::string, std::string>* variables,
const Options& options);
void SetCommonOneofFieldVariables(
const FieldDescriptor* descriptor,
std::map<std::string, std::string>* variables);
class FieldGenerator {
public:
explicit FieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: descriptor_(descriptor), options_(options) {}
virtual ~FieldGenerator();
virtual void GenerateSerializeWithCachedSizes(
io::Printer* printer) const final{};
// 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 static default variable for this field. These are placed inside
// the message class. Most field types don't need this, so the default
// implementation is empty.
virtual void GenerateStaticMembers(io::Printer* /*printer*/) const {}
// 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 declarations of accessors that are for internal purposes only.
// Most field types don't need this, so the default implementation is empty.
virtual void GenerateInternalAccessorDefinitions(
io::Printer* /*printer*/) const {}
// Generate definitions of accessors that are for internal purposes only.
// Most field types don't need this, so the default implementation is empty.
virtual void GenerateInternalAccessorDeclarations(
io::Printer* /*printer*/) const {}
// Generate lines of code (statements, not declarations) which clear the
// field. This is used to define the clear_$name$() method
virtual void GenerateClearingCode(io::Printer* printer) const = 0;
// Generate lines of code (statements, not declarations) which clear the
// field as part of the Clear() method for the whole message. For message
// types which have field presence bits, MessageGenerator::GenerateClear
// will have already checked the presence bits.
//
// Since most field types can re-use GenerateClearingCode, this method is
// not pure virtual.
virtual void GenerateMessageClearingCode(io::Printer* printer) const {
GenerateClearingCode(printer);
}
// 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;
// Generates a copy constructor
virtual void GenerateCopyConstructorCode(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 a manual destructor invocation for use when the message is on an
// arena. The code that this method generates will be executed inside a
// shared-for-the-whole-message-class method registered with
// OwnDestructor(). The method should return |true| if it generated any code
// that requires a call; this allows the message generator to eliminate the
// OwnDestructor() registration if no fields require it.
virtual bool GenerateArenaDestructorCode(io::Printer* printer) const {
return false;
}
// Generate initialization code for private members declared by
// GeneratePrivateMembers(), specifically for the constexpr constructor.
// These go into the constructor's initializer list and must follow that
// syntax (eg `field_(args)`). Does not include `:` or `,` separators.
virtual void GenerateConstinitInitializer(io::Printer* printer) const {}
// 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;
// Generates lines to call IsInitialized() for eligible message fields. Non
// message fields won't need to override this function.
virtual void GenerateIsInitialized(io::Printer* printer) const {}
virtual bool IsInlined() const { return false; }
void SetHasBitIndex(int32_t has_bit_index);
void SetInlinedStringIndex(int32_t inlined_string_index);
protected:
const FieldDescriptor* descriptor_;
const Options& options_;
std::map<std::string, std::string> variables_;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
};
// Convenience class which constructs FieldGenerators for a Descriptor.
class FieldGeneratorMap {
public:
FieldGeneratorMap(const Descriptor* descriptor, const Options& options,
MessageSCCAnalyzer* scc_analyzer);
~FieldGeneratorMap();
const FieldGenerator& get(const FieldDescriptor* field) const;
void SetHasBitIndices(const std::vector<int>& has_bit_indices_) {
for (int i = 0; i < descriptor_->field_count(); ++i) {
field_generators_[i]->SetHasBitIndex(has_bit_indices_[i]);
}
}
void SetInlinedStringIndices(const std::vector<int>& inlined_string_indices) {
for (int i = 0; i < descriptor_->field_count(); ++i) {
field_generators_[i]->SetInlinedStringIndex(inlined_string_indices[i]);
}
}
private:
const Descriptor* descriptor_;
std::vector<std::unique_ptr<FieldGenerator>> field_generators_;
static FieldGenerator* MakeGoogleInternalGenerator(
const FieldDescriptor* field, const Options& options,
MessageSCCAnalyzer* scc_analyzer);
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
const Options& options,
MessageSCCAnalyzer* scc_analyzer);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,208 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
#include <algorithm>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_field.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_options.h>
#include <thirdparty/protobuf/compiler/scc.h>
namespace google {
namespace protobuf {
class FileDescriptor; // descriptor.h
namespace io {
class Printer; // printer.h
}
} // namespace protobuf
} // namespace google
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class EnumGenerator; // enum.h
class MessageGenerator; // message.h
class ServiceGenerator; // service.h
class ExtensionGenerator; // extension.h
class FileGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
FileGenerator(const FileDescriptor* file, const Options& options);
~FileGenerator();
// Shared code between the two header generators below.
void GenerateHeader(io::Printer* printer);
// info_path, if non-empty, should be the path (relative to printer's
// output) to the metadata file describing this proto header.
void GenerateProtoHeader(io::Printer* printer, const std::string& info_path);
// info_path, if non-empty, should be the path (relative to printer's
// output) to the metadata file describing this PB header.
void GeneratePBHeader(io::Printer* printer, const std::string& info_path);
void GenerateSource(io::Printer* printer);
// The following member functions are used when the lite_implicit_weak_fields
// option is set. In this mode the code is organized a bit differently to
// promote better linker stripping of unused code. In particular, we generate
// one .cc file per message, one .cc file per extension, and a main pb.cc file
// containing everything else.
int NumMessages() const { return message_generators_.size(); }
int NumExtensions() const { return extension_generators_.size(); }
// Generates the source file for one message.
void GenerateSourceForMessage(int idx, io::Printer* printer);
// Generates the source file for one extension.
void GenerateSourceForExtension(int idx, io::Printer* printer);
// Generates a source file containing everything except messages and
// extensions.
void GenerateGlobalSource(io::Printer* printer);
private:
// Internal type used by GenerateForwardDeclarations (defined in file.cc).
class ForwardDeclarations;
struct CrossFileReferences;
void IncludeFile(const std::string& google3_name, io::Printer* printer) {
DoIncludeFile(google3_name, false, printer);
}
void IncludeFileAndExport(const std::string& google3_name,
io::Printer* printer) {
DoIncludeFile(google3_name, true, printer);
}
void DoIncludeFile(const std::string& google3_name, bool do_export,
io::Printer* printer);
std::string CreateHeaderInclude(const std::string& basename,
const FileDescriptor* file);
void GetCrossFileReferencesForField(const FieldDescriptor* field,
CrossFileReferences* refs);
void GetCrossFileReferencesForFile(const FileDescriptor* file,
CrossFileReferences* refs);
void GenerateInternalForwardDeclarations(const CrossFileReferences& refs,
io::Printer* printer);
void GenerateSourceIncludes(io::Printer* printer);
void GenerateSourceDefaultInstance(int idx, io::Printer* printer);
void GenerateInitForSCC(const SCC* scc, const CrossFileReferences& refs,
io::Printer* printer);
void GenerateTables(io::Printer* printer);
void GenerateReflectionInitializationCode(io::Printer* printer);
// For other imports, generates their forward-declarations.
void GenerateForwardDeclarations(io::Printer* printer);
// Generates top or bottom of a header file.
void GenerateTopHeaderGuard(io::Printer* printer, bool pb_h);
void GenerateBottomHeaderGuard(io::Printer* printer, bool pb_h);
// Generates #include directives.
void GenerateLibraryIncludes(io::Printer* printer);
void GenerateDependencyIncludes(io::Printer* printer);
// Generate a pragma to pull in metadata using the given info_path (if
// non-empty). info_path should be relative to printer's output.
void GenerateMetadataPragma(io::Printer* printer,
const std::string& info_path);
// Generates a couple of different pieces before definitions:
void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
// Generates types for classes.
void GenerateMessageDefinitions(io::Printer* printer);
void GenerateEnumDefinitions(io::Printer* printer);
// Generates generic service definitions.
void GenerateServiceDefinitions(io::Printer* printer);
// Generates extension identifiers.
void GenerateExtensionIdentifiers(io::Printer* printer);
// Generates inline function definitions.
void GenerateInlineFunctionDefinitions(io::Printer* printer);
void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer);
// Sometimes the names we use in a .proto file happen to be defined as
// macros on some platforms (e.g., macro/minor used in plugin.proto are
// defined as macros in sys/types.h on FreeBSD and a few other platforms).
// To make the generated code compile on these platforms, we either have to
// undef the macro for these few platforms, or rename the field name for all
// platforms. Since these names are part of protobuf public API, renaming is
// generally a breaking change so we prefer the #undef approach.
void GenerateMacroUndefs(io::Printer* printer);
bool IsDepWeak(const FileDescriptor* dep) const {
if (weak_deps_.count(dep) != 0) {
GOOGLE_CHECK(!options_.opensource_runtime);
return true;
}
return false;
}
std::set<const FileDescriptor*> weak_deps_;
const FileDescriptor* file_;
const Options options_;
MessageSCCAnalyzer scc_analyzer_;
std::map<std::string, std::string> variables_;
// Contains the post-order walk of all the messages (and child messages) in
// this file. If you need a pre-order walk just reverse iterate.
std::vector<std::unique_ptr<MessageGenerator>> message_generators_;
std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
std::vector<std::unique_ptr<ServiceGenerator>> service_generators_;
std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__

View File

@ -0,0 +1,271 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <thirdparty/protobuf/compiler/cpp/cpp_generator.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_file.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
CppGenerator::CppGenerator() {}
CppGenerator::~CppGenerator() {}
namespace {
std::string NumberedCcFileName(const std::string& basename, int number) {
return StrCat(basename, ".out/", number, ".cc");
}
} // namespace
bool CppGenerator::Generate(const FileDescriptor* file,
const std::string& parameter,
GeneratorContext* generator_context,
std::string* error) const {
std::vector<std::pair<std::string, std::string> > options;
ParseGeneratorParameter(parameter, &options);
// -----------------------------------------------------------------
// parse generator options
// 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.
//
Options file_options;
file_options.opensource_runtime = opensource_runtime_;
file_options.runtime_include_base = runtime_include_base_;
for (int i = 0; i < options.size(); i++) {
if (options[i].first == "dllexport_decl") {
file_options.dllexport_decl = options[i].second;
} else if (options[i].first == "safe_boundary_check") {
file_options.safe_boundary_check = true;
} else if (options[i].first == "annotate_headers") {
file_options.annotate_headers = true;
} else if (options[i].first == "annotation_pragma_name") {
file_options.annotation_pragma_name = options[i].second;
} else if (options[i].first == "annotation_guard_name") {
file_options.annotation_guard_name = options[i].second;
} else if (options[i].first == "speed") {
file_options.enforce_mode = EnforceOptimizeMode::kSpeed;
} else if (options[i].first == "code_size") {
file_options.enforce_mode = EnforceOptimizeMode::kCodeSize;
} else if (options[i].first == "lite") {
file_options.enforce_mode = EnforceOptimizeMode::kLiteRuntime;
} else if (options[i].first == "lite_implicit_weak_fields") {
file_options.enforce_mode = EnforceOptimizeMode::kLiteRuntime;
file_options.lite_implicit_weak_fields = true;
if (!options[i].second.empty()) {
file_options.num_cc_files =
strto32(options[i].second.c_str(), NULL, 10);
}
} else if (options[i].first == "annotate_accessor") {
file_options.annotate_accessor = true;
} else if (options[i].first == "inject_field_listener_events") {
file_options.field_listener_options.inject_field_listener_events = true;
} else if (options[i].first == "forbidden_field_listener_events") {
std::size_t pos = 0;
do {
std::size_t next_pos = options[i].second.find_first_of("+", pos);
if (next_pos == std::string::npos) {
next_pos = options[i].second.size();
}
if (next_pos > pos)
file_options.field_listener_options.forbidden_field_listener_events
.insert(options[i].second.substr(pos, next_pos - pos));
pos = next_pos + 1;
} while (pos < options[i].second.size());
} else if (options[i].first == "eagerly_verified_lazy") {
file_options.eagerly_verified_lazy = true;
} else if (options[i].first == "force_eagerly_verified_lazy") {
file_options.force_eagerly_verified_lazy = true;
} else if (options[i].first == "table_driven_parsing") {
file_options.table_driven_parsing = true;
} else if (options[i].first == "table_driven_serialization") {
file_options.table_driven_serialization = true;
} else if (options[i].first == "experimental_tail_call_table_mode") {
if (options[i].second == "never") {
file_options.tctable_mode = Options::kTCTableNever;
} else if (options[i].second == "guarded") {
file_options.tctable_mode = Options::kTCTableGuarded;
} else if (options[i].second == "always") {
file_options.tctable_mode = Options::kTCTableAlways;
} else {
*error = "Unknown value for experimental_tail_call_table_mode: " +
options[i].second;
return false;
}
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
}
}
// The safe_boundary_check option controls behavior for Google-internal
// protobuf APIs.
if (file_options.safe_boundary_check && file_options.opensource_runtime) {
*error =
"The safe_boundary_check option is not supported outside of Google.";
return false;
}
// -----------------------------------------------------------------
std::string basename = StripProto(file->name());
if (MaybeBootstrap(file_options, generator_context, file_options.bootstrap,
&basename)) {
return true;
}
FileGenerator file_generator(file, file_options);
// Generate header(s).
if (file_options.proto_h) {
std::unique_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + ".proto.h"));
GeneratedCodeInfo annotations;
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
&annotations);
std::string info_path = basename + ".proto.h.meta";
io::Printer printer(
output.get(), '$',
file_options.annotate_headers ? &annotation_collector : NULL);
file_generator.GenerateProtoHeader(
&printer, file_options.annotate_headers ? info_path : "");
if (file_options.annotate_headers) {
std::unique_ptr<io::ZeroCopyOutputStream> info_output(
generator_context->Open(info_path));
annotations.SerializeToZeroCopyStream(info_output.get());
}
}
{
std::unique_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + ".pb.h"));
GeneratedCodeInfo annotations;
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
&annotations);
std::string info_path = basename + ".pb.h.meta";
io::Printer printer(
output.get(), '$',
file_options.annotate_headers ? &annotation_collector : NULL);
file_generator.GeneratePBHeader(
&printer, file_options.annotate_headers ? info_path : "");
if (file_options.annotate_headers) {
std::unique_ptr<io::ZeroCopyOutputStream> info_output(
generator_context->Open(info_path));
annotations.SerializeToZeroCopyStream(info_output.get());
}
}
// Generate cc file(s).
if (UsingImplicitWeakFields(file, file_options)) {
{
// This is the global .cc file, containing
// enum/services/tables/reflection
std::unique_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + ".pb.cc"));
io::Printer printer(output.get(), '$');
file_generator.GenerateGlobalSource(&printer);
}
int num_cc_files =
file_generator.NumMessages() + file_generator.NumExtensions();
// If we're using implicit weak fields then we allow the user to
// optionally specify how many files to generate, not counting the global
// pb.cc file. If we have more files than messages, then some files will
// be generated as empty placeholders.
if (file_options.num_cc_files > 0) {
GOOGLE_CHECK_LE(num_cc_files, file_options.num_cc_files)
<< "There must be at least as many numbered .cc files as messages "
"and extensions.";
num_cc_files = file_options.num_cc_files;
}
int cc_file_number = 0;
for (int i = 0; i < file_generator.NumMessages(); i++) {
std::unique_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(
NumberedCcFileName(basename, cc_file_number++)));
io::Printer printer(output.get(), '$');
file_generator.GenerateSourceForMessage(i, &printer);
}
for (int i = 0; i < file_generator.NumExtensions(); i++) {
std::unique_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(
NumberedCcFileName(basename, cc_file_number++)));
io::Printer printer(output.get(), '$');
file_generator.GenerateSourceForExtension(i, &printer);
}
// Create empty placeholder files if necessary to match the expected number
// of files.
for (; cc_file_number < num_cc_files; ++cc_file_number) {
std::unique_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(
NumberedCcFileName(basename, cc_file_number)));
}
} else {
std::unique_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + ".pb.cc"));
io::Printer printer(output.get(), '$');
file_generator.GenerateSource(&printer);
}
return true;
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,106 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// Generates C++ code for a given .proto file.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
#include <string>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
// CodeGenerator implementation which generates a C++ source file and
// header. If you create your own protocol compiler binary and you want
// it to support C++ output, you can do so by registering an instance of this
// CodeGenerator with the CommandLineInterface in your main() function.
class PROTOC_EXPORT CppGenerator : public CodeGenerator {
public:
CppGenerator();
~CppGenerator();
enum class Runtime {
kGoogle3, // Use the internal google3 runtime.
kOpensource, // Use the open-source runtime.
// Use the open-source runtime with google3 #include paths. We make these
// absolute to avoid ambiguity, so the runtime will be #included like:
// #include "third_party/protobuf/.../google/protobuf/message.h"
kOpensourceGoogle3
};
void set_opensource_runtime(bool opensource) {
opensource_runtime_ = opensource;
}
// If set to a non-empty string, generated code will do:
// #include "<BASE>/google/protobuf/message.h"
// instead of:
// #include <thirdparty/protobuf/message.h>
// This has no effect if opensource_runtime = false.
void set_runtime_include_base(const std::string& base) {
runtime_include_base_ = base;
}
// implements CodeGenerator ----------------------------------------
bool Generate(const FileDescriptor* file, const std::string& parameter,
GeneratorContext* generator_context,
std::string* error) const override;
uint64_t GetSupportedFeatures() const override {
// We don't fully support this yet, but this is needed to unblock the tests,
// and we will have full support before the experimental flag is removed.
return FEATURE_PROTO3_OPTIONAL;
}
private:
bool opensource_runtime_ = true;
std::string runtime_include_base_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CppGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,971 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
#include <algorithm>
#include <cstdint>
#include <iterator>
#include <map>
#include <string>
#include <thirdparty/protobuf/compiler/cpp/cpp_options.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_names.h>
#include <thirdparty/protobuf/compiler/scc.h>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/port.h>
#include <thirdparty/protobuf/stubs/strutil.h>
// Must be included last.
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
inline std::string ProtobufNamespace(const Options& /* options */) {
return "PROTOBUF_NAMESPACE_ID";
}
inline std::string MacroPrefix(const Options& /* options */) {
return "GOOGLE_PROTOBUF";
}
inline std::string DeprecatedAttribute(const Options& /* options */,
const FieldDescriptor* d) {
return d->options().deprecated() ? "PROTOBUF_DEPRECATED " : "";
}
inline std::string DeprecatedAttribute(const Options& /* options */,
const EnumValueDescriptor* d) {
return d->options().deprecated() ? "PROTOBUF_DEPRECATED_ENUM " : "";
}
// Commonly-used separator comments. Thick is a line of '=', thin is a line
// of '-'.
extern const char kThickSeparator[];
extern const char kThinSeparator[];
void SetCommonVars(const Options& options,
std::map<std::string, std::string>* variables);
void SetUnknownFieldsVariable(const Descriptor* descriptor,
const Options& options,
std::map<std::string, std::string>* variables);
bool GetBootstrapBasename(const Options& options, const std::string& basename,
std::string* bootstrap_basename);
bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context,
bool bootstrap_flag, std::string* basename);
bool IsBootstrapProto(const Options& options, const FileDescriptor* file);
// Name space of the proto file. This namespace is such that the string
// "<namespace>::some_name" is the correct fully qualified namespace.
// This means if the package is empty the namespace is "", and otherwise
// the namespace is "::foo::bar::...::baz" without trailing semi-colons.
std::string Namespace(const FileDescriptor* d, const Options& options);
std::string Namespace(const Descriptor* d, const Options& options);
std::string Namespace(const FieldDescriptor* d, const Options& options);
std::string Namespace(const EnumDescriptor* d, const Options& options);
// Returns true if it's safe to reset "field" to zero.
bool CanInitializeByZeroing(const FieldDescriptor* field);
std::string ClassName(const Descriptor* descriptor);
std::string ClassName(const EnumDescriptor* enum_descriptor);
std::string QualifiedClassName(const Descriptor* d, const Options& options);
std::string QualifiedClassName(const EnumDescriptor* d, const Options& options);
std::string QualifiedClassName(const Descriptor* d);
std::string QualifiedClassName(const EnumDescriptor* d);
// DEPRECATED just use ClassName or QualifiedClassName, a boolean is very
// unreadable at the callsite.
// 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
inline std::string ClassName(const Descriptor* descriptor, bool qualified) {
return qualified ? QualifiedClassName(descriptor, Options())
: ClassName(descriptor);
}
inline std::string ClassName(const EnumDescriptor* descriptor, bool qualified) {
return qualified ? QualifiedClassName(descriptor, Options())
: ClassName(descriptor);
}
// Returns the extension name prefixed with the class name if nested but without
// the package name.
std::string ExtensionName(const FieldDescriptor* d);
std::string QualifiedExtensionName(const FieldDescriptor* d,
const Options& options);
std::string QualifiedExtensionName(const FieldDescriptor* d);
// Type name of default instance.
std::string DefaultInstanceType(const Descriptor* descriptor,
const Options& options);
// Non-qualified name of the default_instance of this message.
std::string DefaultInstanceName(const Descriptor* descriptor,
const Options& options);
// Non-qualified name of the default instance pointer. This is used only for
// implicit weak fields, where we need an extra indirection.
std::string DefaultInstancePtr(const Descriptor* descriptor,
const Options& options);
// Fully qualified name of the default_instance of this message.
std::string QualifiedDefaultInstanceName(const Descriptor* descriptor,
const Options& options);
// Fully qualified name of the default instance pointer.
std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor,
const Options& options);
// DescriptorTable variable name.
std::string DescriptorTableName(const FileDescriptor* file,
const Options& options);
// When declaring symbol externs from another file, this macro will supply the
// dllexport needed for the target file, if any.
std::string FileDllExport(const FileDescriptor* file, const Options& options);
// Name of the base class: google::protobuf::Message or google::protobuf::MessageLite.
std::string SuperClassName(const Descriptor* descriptor,
const Options& options);
// Adds an underscore if necessary to prevent conflicting with a keyword.
std::string ResolveKeyword(const std::string& name);
// 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().
std::string FieldName(const FieldDescriptor* field);
// Returns an estimate of the compiler's alignment for the field. This
// can't guarantee to be correct because the generated code could be compiled on
// different systems with different alignment rules. The estimates below assume
// 64-bit pointers.
int EstimateAlignmentSize(const FieldDescriptor* field);
// Get the unqualified name that should be used for a field's field
// number constant.
std::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);
std::string FieldMessageTypeName(const FieldDescriptor* field,
const Options& options);
// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
const char* PrimitiveTypeName(FieldDescriptor::CppType type);
std::string PrimitiveTypeName(const Options& options,
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);
// Return the code that evaluates to the number when compiled.
std::string Int32ToString(int number);
// Get code that evaluates to the field's default value.
std::string DefaultValue(const Options& options, const FieldDescriptor* field);
// Compatibility function for callers outside proto2.
std::string DefaultValue(const FieldDescriptor* field);
// Convert a file name into a valid identifier.
std::string FilenameIdentifier(const std::string& filename);
// For each .proto file generates a unique name. To prevent collisions of
// symbols in the global namespace
std::string UniqueName(const std::string& name, const std::string& filename,
const Options& options);
inline std::string UniqueName(const std::string& name, const FileDescriptor* d,
const Options& options) {
return UniqueName(name, d->name(), options);
}
inline std::string UniqueName(const std::string& name, const Descriptor* d,
const Options& options) {
return UniqueName(name, d->file(), options);
}
inline std::string UniqueName(const std::string& name, const EnumDescriptor* d,
const Options& options) {
return UniqueName(name, d->file(), options);
}
inline std::string UniqueName(const std::string& name,
const ServiceDescriptor* d,
const Options& options) {
return UniqueName(name, d->file(), options);
}
// Versions for call sites that only support the internal runtime (like proto1
// support).
inline Options InternalRuntimeOptions() {
Options options;
options.opensource_runtime = false;
return options;
}
inline std::string UniqueName(const std::string& name,
const std::string& filename) {
return UniqueName(name, filename, InternalRuntimeOptions());
}
inline std::string UniqueName(const std::string& name,
const FileDescriptor* d) {
return UniqueName(name, d->name(), InternalRuntimeOptions());
}
inline std::string UniqueName(const std::string& name, const Descriptor* d) {
return UniqueName(name, d->file(), InternalRuntimeOptions());
}
inline std::string UniqueName(const std::string& name,
const EnumDescriptor* d) {
return UniqueName(name, d->file(), InternalRuntimeOptions());
}
inline std::string UniqueName(const std::string& name,
const ServiceDescriptor* d) {
return UniqueName(name, d->file(), InternalRuntimeOptions());
}
// Return the qualified C++ name for a file level symbol.
std::string QualifiedFileLevelSymbol(const FileDescriptor* file,
const std::string& name,
const Options& options);
// Escape C++ trigraphs by escaping question marks to \?
std::string EscapeTrigraphs(const std::string& to_escape);
// Escaped function name to eliminate naming conflict.
std::string SafeFunctionName(const Descriptor* descriptor,
const FieldDescriptor* field,
const std::string& prefix);
// Returns true if generated messages have public unknown fields accessors
inline bool PublicUnknownFieldsAccessors(const Descriptor* message) {
return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
}
// Returns the optimize mode for <file>, respecting <options.enforce_lite>.
FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
const Options& options);
// Determines whether unknown fields will be stored in an UnknownFieldSet or
// a string.
inline bool UseUnknownFieldSet(const FileDescriptor* file,
const Options& options) {
return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
}
inline bool IsWeak(const FieldDescriptor* field, const Options& options) {
if (field->options().weak()) {
GOOGLE_CHECK(!options.opensource_runtime);
return true;
}
return false;
}
bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options);
// For a string field, returns the effective ctype. If the actual ctype is
// not supported, returns the default of STRING.
FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field,
const Options& options);
inline bool IsCord(const FieldDescriptor* field, const Options& options) {
return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
EffectiveStringCType(field, options) == FieldOptions::CORD;
}
inline bool IsString(const FieldDescriptor* field, const Options& options) {
return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
EffectiveStringCType(field, options) == FieldOptions::STRING;
}
inline bool IsStringPiece(const FieldDescriptor* field,
const Options& options) {
return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE;
}
class MessageSCCAnalyzer;
// Does the given FileDescriptor use lazy fields?
bool HasLazyFields(const FileDescriptor* file, const Options& options,
MessageSCCAnalyzer* scc_analyzer);
// Is the given field a supported lazy field?
bool IsLazy(const FieldDescriptor* field, const Options& options,
MessageSCCAnalyzer* scc_analyzer);
inline bool IsLazilyVerifiedLazy(const FieldDescriptor* field,
const Options& options) {
return field->options().lazy() && !field->is_repeated() &&
field->type() == FieldDescriptor::TYPE_MESSAGE &&
GetOptimizeFor(field->file(), options) != FileOptions::LITE_RUNTIME &&
!options.opensource_runtime;
}
inline bool IsEagerlyVerifiedLazy(const FieldDescriptor* field,
const Options& options,
MessageSCCAnalyzer* scc_analyzer) {
return IsLazy(field, options, scc_analyzer) && !field->options().lazy();
}
inline bool IsFieldUsed(const FieldDescriptor* /* field */,
const Options& /* options */) {
return true;
}
// Returns true if "field" is stripped.
inline bool IsFieldStripped(const FieldDescriptor* /*field*/,
const Options& /*options*/) {
return false;
}
// Does the file contain any definitions that need extension_set.h?
bool HasExtensionsOrExtendableMessage(const FileDescriptor* file);
// Does the file have any repeated fields, necessitating the file to include
// repeated_field.h? This does not include repeated extensions, since those are
// all stored internally in an ExtensionSet, not a separate RepeatedField*.
bool HasRepeatedFields(const FileDescriptor* file);
// Does the file have any string/bytes fields with ctype=STRING_PIECE? This
// does not include extensions, since ctype is ignored for extensions.
bool HasStringPieceFields(const FileDescriptor* file, const Options& options);
// Does the file have any string/bytes fields with ctype=CORD? This does not
// include extensions, since ctype is ignored for extensions.
bool HasCordFields(const FileDescriptor* file, const Options& options);
// Does the file have any map fields, necessitating the file to include
// map_field_inl.h and map.h.
bool HasMapFields(const FileDescriptor* file);
// Does this file have any enum type definitions?
bool HasEnumDefinitions(const FileDescriptor* file);
// Does this file have generated parsing, serialization, and other
// standard methods for which reflection-based fallback implementations exist?
inline bool HasGeneratedMethods(const FileDescriptor* file,
const Options& options) {
return GetOptimizeFor(file, options) != FileOptions::CODE_SIZE;
}
// Do message classes in this file have descriptor and reflection methods?
inline bool HasDescriptorMethods(const FileDescriptor* file,
const Options& options) {
return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
}
// Should we generate generic services for this file?
inline bool HasGenericServices(const FileDescriptor* file,
const Options& options) {
return file->service_count() > 0 &&
GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME &&
file->options().cc_generic_services();
}
inline bool IsProto2MessageSet(const Descriptor* descriptor,
const Options& options) {
return !options.opensource_runtime &&
options.enforce_mode != EnforceOptimizeMode::kLiteRuntime &&
!options.lite_implicit_weak_fields &&
descriptor->options().message_set_wire_format() &&
descriptor->full_name() == "google.protobuf.bridge.MessageSet";
}
inline bool IsMapEntryMessage(const Descriptor* descriptor) {
return descriptor->options().map_entry();
}
// Returns true if the field's CPPTYPE is string or message.
bool IsStringOrMessage(const FieldDescriptor* field);
std::string UnderscoresToCamelCase(const std::string& input,
bool cap_next_letter);
inline bool IsProto3(const FileDescriptor* file) {
return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
}
inline bool HasHasbit(const FieldDescriptor* field) {
// This predicate includes proto3 message fields only if they have "optional".
// Foo submsg1 = 1; // HasHasbit() == false
// optional Foo submsg2 = 2; // HasHasbit() == true
// This is slightly odd, as adding "optional" to a singular proto3 field does
// not change the semantics or API. However whenever any field in a message
// has a hasbit, it forces reflection to include hasbit offsets for *all*
// fields, even if almost all of them are set to -1 (no hasbit). So to avoid
// causing a sudden size regression for ~all proto3 messages, we give proto3
// message fields a hasbit only if "optional" is present. If the user is
// explicitly writing "optional", it is likely they are writing it on
// primitive fields also.
return (field->has_optional_keyword() || field->is_required()) &&
!field->options().weak();
}
// Returns true if 'enum' semantics are such that unknown values are preserved
// in the enum field itself, rather than going to the UnknownFieldSet.
inline bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) {
return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
}
inline bool IsCrossFileMessage(const FieldDescriptor* field) {
return field->type() == FieldDescriptor::TYPE_MESSAGE &&
field->message_type()->file() != field->file();
}
inline std::string MakeDefaultName(const FieldDescriptor* field) {
return "_i_give_permission_to_break_this_code_default_" + FieldName(field) +
"_";
}
bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options);
bool IsAnyMessage(const Descriptor* descriptor, const Options& options);
bool IsWellKnownMessage(const FileDescriptor* descriptor);
inline std::string IncludeGuard(const FileDescriptor* file, bool pb_h,
const Options& options) {
// If we are generating a .pb.h file and the proto_h option is enabled, then
// the .pb.h gets an extra suffix.
std::string filename_identifier = FilenameIdentifier(
file->name() + (pb_h && options.proto_h ? ".pb.h" : ""));
if (IsWellKnownMessage(file)) {
// For well-known messages we need third_party/protobuf and net/proto2 to
// have distinct include guards, because some source files include both and
// both need to be defined (the third_party copies will be in the
// google::protobuf_opensource namespace).
return MacroPrefix(options) + "_INCLUDED_" + filename_identifier;
} else {
// Ideally this case would use distinct include guards for opensource and
// google3 protos also. (The behavior of "first #included wins" is not
// ideal). But unfortunately some legacy code includes both and depends on
// the identical include guards to avoid compile errors.
//
// We should clean this up so that this case can be removed.
return "GOOGLE_PROTOBUF_INCLUDED_" + filename_identifier;
}
}
// Returns the OptimizeMode for this file, furthermore it updates a status
// bool if has_opt_codesize_extension is non-null. If this status bool is true
// it means this file contains an extension that itself is defined as
// optimized_for = CODE_SIZE.
FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
const Options& options,
bool* has_opt_codesize_extension);
inline FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
const Options& options) {
return GetOptimizeFor(file, options, nullptr);
}
inline bool NeedsEagerDescriptorAssignment(const FileDescriptor* file,
const Options& options) {
bool has_opt_codesize_extension;
if (GetOptimizeFor(file, options, &has_opt_codesize_extension) ==
FileOptions::CODE_SIZE &&
has_opt_codesize_extension) {
// If this filedescriptor contains an extension from another file which
// is optimized_for = CODE_SIZE. We need to be careful in the ordering so
// we eagerly build the descriptors in the dependencies before building
// the descriptors of this file.
return true;
} else {
// If we have a generated code based parser we never need eager
// initialization of descriptors of our deps.
return false;
}
}
// This orders the messages in a .pb.cc as it's outputted by file.cc
void FlattenMessagesInFile(const FileDescriptor* file,
std::vector<const Descriptor*>* result);
inline std::vector<const Descriptor*> FlattenMessagesInFile(
const FileDescriptor* file) {
std::vector<const Descriptor*> result;
FlattenMessagesInFile(file, &result);
return result;
}
template <typename F>
void ForEachMessage(const Descriptor* descriptor, F&& func) {
for (int i = 0; i < descriptor->nested_type_count(); i++)
ForEachMessage(descriptor->nested_type(i), std::forward<F&&>(func));
func(descriptor);
}
template <typename F>
void ForEachMessage(const FileDescriptor* descriptor, F&& func) {
for (int i = 0; i < descriptor->message_type_count(); i++)
ForEachMessage(descriptor->message_type(i), std::forward<F&&>(func));
}
bool HasWeakFields(const Descriptor* desc, const Options& options);
bool HasWeakFields(const FileDescriptor* desc, const Options& options);
// Returns true if the "required" restriction check should be ignored for the
// given field.
inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
const Options& options) {
// Do not check "required" for lazily verified lazy fields.
return IsLazilyVerifiedLazy(field, options);
}
struct MessageAnalysis {
bool is_recursive = false;
bool contains_cord = false;
bool contains_extension = false;
bool contains_required = false;
bool contains_weak = false; // Implicit weak as well.
};
// This class is used in FileGenerator, to ensure linear instead of
// quadratic performance, if we do this per message we would get O(V*(V+E)).
// Logically this is just only used in message.cc, but in the header for
// FileGenerator to help share it.
class PROTOC_EXPORT MessageSCCAnalyzer {
public:
explicit MessageSCCAnalyzer(const Options& options) : options_(options) {}
MessageAnalysis GetSCCAnalysis(const SCC* scc);
bool HasRequiredFields(const Descriptor* descriptor) {
MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
return result.contains_required || result.contains_extension;
}
bool HasWeakField(const Descriptor* descriptor) {
MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
return result.contains_weak;
}
const SCC* GetSCC(const Descriptor* descriptor) {
return analyzer_.GetSCC(descriptor);
}
private:
struct DepsGenerator {
std::vector<const Descriptor*> operator()(const Descriptor* desc) const {
std::vector<const Descriptor*> deps;
for (int i = 0; i < desc->field_count(); i++) {
if (desc->field(i)->message_type()) {
deps.push_back(desc->field(i)->message_type());
}
}
return deps;
}
};
SCCAnalyzer<DepsGenerator> analyzer_;
Options options_;
std::map<const SCC*, MessageAnalysis> analysis_cache_;
};
void ListAllFields(const Descriptor* d,
std::vector<const FieldDescriptor*>* fields);
void ListAllFields(const FileDescriptor* d,
std::vector<const FieldDescriptor*>* fields);
template <class T>
void ForEachField(const Descriptor* d, T&& func) {
for (int i = 0; i < d->nested_type_count(); i++) {
ForEachField(d->nested_type(i), std::forward<T&&>(func));
}
for (int i = 0; i < d->extension_count(); i++) {
func(d->extension(i));
}
for (int i = 0; i < d->field_count(); i++) {
func(d->field(i));
}
}
template <class T>
void ForEachField(const FileDescriptor* d, T&& func) {
for (int i = 0; i < d->message_type_count(); i++) {
ForEachField(d->message_type(i), std::forward<T&&>(func));
}
for (int i = 0; i < d->extension_count(); i++) {
func(d->extension(i));
}
}
void ListAllTypesForServices(const FileDescriptor* fd,
std::vector<const Descriptor*>* types);
// Indicates whether we should use implicit weak fields for this file.
bool UsingImplicitWeakFields(const FileDescriptor* file,
const Options& options);
// Indicates whether to treat this field as implicitly weak.
bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
MessageSCCAnalyzer* scc_analyzer);
inline bool HasSimpleBaseClass(const Descriptor* desc, const Options& options) {
if (!HasDescriptorMethods(desc->file(), options)) return false;
if (desc->extension_range_count() != 0) return false;
if (desc->field_count() == 0) return true;
// TODO(jorg): Support additional common message types with only one
// or two fields
return false;
}
inline bool HasSimpleBaseClasses(const FileDescriptor* file,
const Options& options) {
bool v = false;
ForEachMessage(file, [&v, &options](const Descriptor* desc) {
v |= HasSimpleBaseClass(desc, options);
});
return v;
}
inline std::string SimpleBaseClass(const Descriptor* desc,
const Options& options) {
if (!HasDescriptorMethods(desc->file(), options)) return "";
if (desc->extension_range_count() != 0) return "";
if (desc->field_count() == 0) {
return "ZeroFieldsBase";
}
// TODO(jorg): Support additional common message types with only one
// or two fields
return "";
}
// Formatter is a functor class which acts as a closure around printer and
// the variable map. It's much like printer->Print except it supports both named
// variables that are substituted using a key value map and direct arguments. In
// the format string $1$, $2$, etc... are substituted for the first, second, ...
// direct argument respectively in the format call, it accepts both strings and
// integers. The implementation verifies all arguments are used and are "first"
// used in order of appearance in the argument list. For example,
//
// Format("return array[$1$];", 3) -> "return array[3];"
// Format("array[$2$] = $1$;", "Bla", 3) -> FATAL error (wrong order)
// Format("array[$1$] = $2$;", 3, "Bla") -> "array[3] = Bla;"
//
// The arguments can be used more than once like
//
// Format("array[$1$] = $2$; // Index = $1$", 3, "Bla") ->
// "array[3] = Bla; // Index = 3"
//
// If you use more arguments use the following style to help the reader,
//
// Format("int $1$() {\n"
// " array[$2$] = $3$;\n"
// " return $4$;"
// "}\n",
// funname, // 1
// idx, // 2
// varname, // 3
// retval); // 4
//
// but consider using named variables. Named variables like $foo$, with some
// identifier foo, are looked up in the map. One additional feature is that
// spaces are accepted between the '$' delimiters, $ foo$ will
// substiture to " bar" if foo stands for "bar", but in case it's empty
// will substitute to "". Hence, for example,
//
// Format(vars, "$dllexport $void fun();") -> "void fun();"
// "__declspec(export) void fun();"
//
// which is convenient to prevent double, leading or trailing spaces.
class PROTOC_EXPORT Formatter {
public:
explicit Formatter(io::Printer* printer) : printer_(printer) {}
Formatter(io::Printer* printer,
const std::map<std::string, std::string>& vars)
: printer_(printer), vars_(vars) {}
template <typename T>
void Set(const std::string& key, const T& value) {
vars_[key] = ToString(value);
}
void AddMap(const std::map<std::string, std::string>& vars) {
for (const auto& keyval : vars) vars_[keyval.first] = keyval.second;
}
template <typename... Args>
void operator()(const char* format, const Args&... args) const {
printer_->FormatInternal({ToString(args)...}, vars_, format);
}
void Indent() const { printer_->Indent(); }
void Outdent() const { printer_->Outdent(); }
io::Printer* printer() const { return printer_; }
class PROTOC_EXPORT ScopedIndenter {
public:
explicit ScopedIndenter(Formatter* format) : format_(format) {
format_->Indent();
}
~ScopedIndenter() { format_->Outdent(); }
private:
Formatter* format_;
};
PROTOBUF_NODISCARD ScopedIndenter ScopedIndent() {
return ScopedIndenter(this);
}
template <typename... Args>
PROTOBUF_NODISCARD ScopedIndenter ScopedIndent(const char* format,
const Args&&... args) {
(*this)(format, static_cast<Args&&>(args)...);
return ScopedIndenter(this);
}
class PROTOC_EXPORT SaveState {
public:
explicit SaveState(Formatter* format)
: format_(format), vars_(format->vars_) {}
~SaveState() { format_->vars_.swap(vars_); }
private:
Formatter* format_;
std::map<std::string, std::string> vars_;
};
private:
io::Printer* printer_;
std::map<std::string, std::string> vars_;
// Convenience overloads to accept different types as arguments.
static std::string ToString(const std::string& s) { return s; }
template <typename I, typename = typename std::enable_if<
std::is_integral<I>::value>::type>
static std::string ToString(I x) {
return StrCat(x);
}
static std::string ToString(strings::Hex x) { return StrCat(x); }
static std::string ToString(const FieldDescriptor* d) { return Payload(d); }
static std::string ToString(const Descriptor* d) { return Payload(d); }
static std::string ToString(const EnumDescriptor* d) { return Payload(d); }
static std::string ToString(const EnumValueDescriptor* d) {
return Payload(d);
}
static std::string ToString(const OneofDescriptor* d) { return Payload(d); }
template <typename Descriptor>
static std::string Payload(const Descriptor* descriptor) {
std::vector<int> path;
descriptor->GetLocationPath(&path);
GeneratedCodeInfo::Annotation annotation;
for (int index : path) {
annotation.add_path(index);
}
annotation.set_source_file(descriptor->file()->name());
return annotation.SerializeAsString();
}
};
template <class T>
void PrintFieldComment(const Formatter& format, const T* field) {
// Print the field's (or oneof's) proto-syntax definition as a comment.
// We don't want to print group bodies so we cut off after the first
// line.
DebugStringOptions options;
options.elide_group_body = true;
options.elide_oneof_body = true;
std::string def = field->DebugStringWithOptions(options);
format("// $1$\n", def.substr(0, def.find_first_of('\n')));
}
class PROTOC_EXPORT NamespaceOpener {
public:
explicit NamespaceOpener(const Formatter& format)
: printer_(format.printer()) {}
NamespaceOpener(const std::string& name, const Formatter& format)
: NamespaceOpener(format) {
ChangeTo(name);
}
~NamespaceOpener() { ChangeTo(""); }
void ChangeTo(const std::string& name) {
std::vector<std::string> new_stack_ =
Split(name, "::", true);
size_t len = std::min(name_stack_.size(), new_stack_.size());
size_t common_idx = 0;
while (common_idx < len) {
if (name_stack_[common_idx] != new_stack_[common_idx]) break;
common_idx++;
}
for (auto it = name_stack_.crbegin();
it != name_stack_.crend() - common_idx; ++it) {
if (*it == "PROTOBUF_NAMESPACE_ID") {
printer_->Print("PROTOBUF_NAMESPACE_CLOSE\n");
} else {
printer_->Print("} // namespace $ns$\n", "ns", *it);
}
}
name_stack_.swap(new_stack_);
for (size_t i = common_idx; i < name_stack_.size(); ++i) {
if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") {
printer_->Print("PROTOBUF_NAMESPACE_OPEN\n");
} else {
printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]);
}
}
}
private:
io::Printer* printer_;
std::vector<std::string> name_stack_;
};
enum class Utf8CheckMode {
kStrict = 0, // Parsing will fail if non UTF-8 data is in string fields.
kVerify = 1, // Only log an error but parsing will succeed.
kNone = 2, // No UTF-8 check.
};
Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
const Options& options);
void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
const Options& options, bool for_parse,
const char* parameters,
const Formatter& format);
void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
const Options& options, bool for_parse,
const char* parameters,
const Formatter& format);
template <typename T>
struct FieldRangeImpl {
struct Iterator {
using iterator_category = std::forward_iterator_tag;
using value_type = const FieldDescriptor*;
using difference_type = int;
value_type operator*() { return descriptor->field(idx); }
friend bool operator==(const Iterator& a, const Iterator& b) {
GOOGLE_DCHECK(a.descriptor == b.descriptor);
return a.idx == b.idx;
}
friend bool operator!=(const Iterator& a, const Iterator& b) {
return !(a == b);
}
Iterator& operator++() {
idx++;
return *this;
}
int idx;
const T* descriptor;
};
Iterator begin() const { return {0, descriptor}; }
Iterator end() const { return {descriptor->field_count(), descriptor}; }
const T* descriptor;
};
template <typename T>
FieldRangeImpl<T> FieldRange(const T* desc) {
return {desc};
}
struct OneOfRangeImpl {
struct Iterator {
using iterator_category = std::forward_iterator_tag;
using value_type = const OneofDescriptor*;
using difference_type = int;
value_type operator*() { return descriptor->oneof_decl(idx); }
friend bool operator==(const Iterator& a, const Iterator& b) {
GOOGLE_DCHECK(a.descriptor == b.descriptor);
return a.idx == b.idx;
}
friend bool operator!=(const Iterator& a, const Iterator& b) {
return !(a == b);
}
Iterator& operator++() {
idx++;
return *this;
}
int idx;
const Descriptor* descriptor;
};
Iterator begin() const { return {0, descriptor}; }
Iterator end() const {
return {descriptor->real_oneof_decl_count(), descriptor};
}
const Descriptor* descriptor;
};
inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; }
PROTOC_EXPORT std::string StripProto(const std::string& filename);
bool EnableMessageOwnedArena(const Descriptor* desc);
bool ShouldVerify(const Descriptor* descriptor, const Options& options,
MessageSCCAnalyzer* scc_analyzer);
bool ShouldVerify(const FileDescriptor* file, const Options& options,
MessageSCCAnalyzer* scc_analyzer);
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__

View File

@ -0,0 +1,334 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <thirdparty/protobuf/compiler/cpp/cpp_map_field.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/wire_format.h>
#include <thirdparty/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
bool IsProto3Field(const FieldDescriptor* field_descriptor) {
const FileDescriptor* file_descriptor = field_descriptor->file();
return file_descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
}
void SetMessageVariables(const FieldDescriptor* descriptor,
std::map<std::string, std::string>* variables,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = ClassName(descriptor->message_type(), false);
(*variables)["full_name"] = descriptor->full_name();
const FieldDescriptor* key =
descriptor->message_type()->FindFieldByName("key");
const FieldDescriptor* val =
descriptor->message_type()->FindFieldByName("value");
(*variables)["key_cpp"] = PrimitiveTypeName(options, key->cpp_type());
switch (val->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
(*variables)["val_cpp"] = FieldMessageTypeName(val, options);
break;
case FieldDescriptor::CPPTYPE_ENUM:
(*variables)["val_cpp"] = ClassName(val->enum_type(), true);
break;
default:
(*variables)["val_cpp"] = PrimitiveTypeName(options, val->cpp_type());
}
(*variables)["key_wire_type"] =
"TYPE_" + ToUpper(DeclaredTypeMethodName(key->type()));
(*variables)["val_wire_type"] =
"TYPE_" + ToUpper(DeclaredTypeMethodName(val->type()));
(*variables)["map_classname"] = ClassName(descriptor->message_type(), false);
(*variables)["number"] = StrCat(descriptor->number());
(*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
if (HasDescriptorMethods(descriptor->file(), options)) {
(*variables)["lite"] = "";
} else {
(*variables)["lite"] = "Lite";
}
}
MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
const Options& options,
MessageSCCAnalyzer* scc_analyzer)
: FieldGenerator(descriptor, options),
has_required_fields_(
scc_analyzer->HasRequiredFields(descriptor->message_type())) {
SetMessageVariables(descriptor, &variables_, options);
}
MapFieldGenerator::~MapFieldGenerator() {}
void MapFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"::$proto_ns$::internal::MapField$lite$<\n"
" $map_classname$,\n"
" $key_cpp$, $val_cpp$,\n"
" ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
" ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> "
"$name$_;\n");
}
void MapFieldGenerator::GenerateAccessorDeclarations(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"private:\n"
"const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
" ${1$_internal_$name$$}$() const;\n"
"::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
" ${1$_internal_mutable_$name$$}$();\n"
"public:\n"
"$deprecated_attr$const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
" ${1$$name$$}$() const;\n"
"$deprecated_attr$::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
" ${1$mutable_$name$$}$();\n",
descriptor_);
}
void MapFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
"$classname$::_internal_$name$() const {\n"
" return $name$_.GetMap();\n"
"}\n"
"inline const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
"$classname$::$name$() const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_map:$full_name$)\n"
" return _internal_$name$();\n"
"}\n"
"inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
"$classname$::_internal_mutable_$name$() {\n"
" return $name$_.MutableMap();\n"
"}\n"
"inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
"$classname$::mutable_$name$() {\n"
"$annotate_mutable$"
" // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
" return _internal_mutable_$name$();\n"
"}\n");
}
void MapFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.Clear();\n");
}
void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.MergeFrom(from.$name$_);\n");
}
void MapFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.InternalSwap(&other->$name$_);\n");
}
void MapFieldGenerator::GenerateCopyConstructorCode(
io::Printer* printer) const {
GenerateConstructorCode(printer);
GenerateMergingCode(printer);
}
static void GenerateSerializationLoop(const Formatter& format, bool string_key,
bool string_value,
bool is_deterministic) {
std::string ptr;
if (is_deterministic) {
format("for (size_type i = 0; i < n; i++) {\n");
ptr = string_key ? "items[static_cast<ptrdiff_t>(i)]"
: "items[static_cast<ptrdiff_t>(i)].second";
} else {
format(
"for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
" it = this->_internal_$name$().begin();\n"
" it != this->_internal_$name$().end(); ++it) {\n");
ptr = "it";
}
format.Indent();
format(
"target = $map_classname$::Funcs::InternalSerialize($number$, "
"$1$->first, $1$->second, target, stream);\n",
ptr);
if (string_key || string_value) {
// ptr is either an actual pointer or an iterator, either way we can
// create a pointer by taking the address after de-referencing it.
format("Utf8Check::Check(&(*$1$));\n", ptr);
}
format.Outdent();
format("}\n");
}
void MapFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("if (!this->_internal_$name$().empty()) {\n");
format.Indent();
const FieldDescriptor* key_field =
descriptor_->message_type()->FindFieldByName("key");
const FieldDescriptor* value_field =
descriptor_->message_type()->FindFieldByName("value");
const bool string_key = key_field->type() == FieldDescriptor::TYPE_STRING;
const bool string_value = value_field->type() == FieldDescriptor::TYPE_STRING;
format(
"typedef ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_pointer\n"
" ConstPtr;\n");
if (string_key) {
format(
"typedef ConstPtr SortItem;\n"
"typedef ::$proto_ns$::internal::"
"CompareByDerefFirst<SortItem> Less;\n");
} else {
format(
"typedef ::$proto_ns$::internal::SortItem< $key_cpp$, ConstPtr > "
"SortItem;\n"
"typedef ::$proto_ns$::internal::CompareByFirstField<SortItem> "
"Less;\n");
}
bool utf8_check = string_key || string_value;
if (utf8_check) {
format(
"struct Utf8Check {\n"
" static void Check(ConstPtr p) {\n"
// p may be unused when GetUtf8CheckMode evaluates to kNone,
// thus disabling the validation.
" (void)p;\n");
format.Indent();
format.Indent();
if (string_key) {
GenerateUtf8CheckCodeForString(
key_field, options_, false,
"p->first.data(), static_cast<int>(p->first.length()),\n", format);
}
if (string_value) {
GenerateUtf8CheckCodeForString(
value_field, options_, false,
"p->second.data(), static_cast<int>(p->second.length()),\n", format);
}
format.Outdent();
format.Outdent();
format(
" }\n"
"};\n");
}
format(
"\n"
"if (stream->IsSerializationDeterministic() &&\n"
" this->_internal_$name$().size() > 1) {\n"
" ::std::unique_ptr<SortItem[]> items(\n"
" new SortItem[this->_internal_$name$().size()]);\n"
" typedef ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::size_type "
"size_type;\n"
" size_type n = 0;\n"
" for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
" it = this->_internal_$name$().begin();\n"
" it != this->_internal_$name$().end(); ++it, ++n) {\n"
" items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);\n"
" }\n"
" ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());\n");
format.Indent();
GenerateSerializationLoop(format, string_key, string_value, true);
format.Outdent();
format("} else {\n");
format.Indent();
GenerateSerializationLoop(format, string_key, string_value, false);
format.Outdent();
format("}\n");
format.Outdent();
format("}\n");
}
void MapFieldGenerator::GenerateByteSize(io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"total_size += $tag_size$ *\n"
" "
"::$proto_ns$::internal::FromIntSize(this->_internal_$name$_size());\n"
"for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
" it = this->_internal_$name$().begin();\n"
" it != this->_internal_$name$().end(); ++it) {\n"
" total_size += $map_classname$::Funcs::ByteSizeLong(it->first, "
"it->second);\n"
"}\n");
}
void MapFieldGenerator::GenerateIsInitialized(io::Printer* printer) const {
if (!has_required_fields_) return;
Formatter format(printer, variables_);
format(
"if (!::$proto_ns$::internal::AllAreInitialized($name$_)) return "
"false;\n");
}
void MapFieldGenerator::GenerateConstinitInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (HasDescriptorMethods(descriptor_->file(), options_)) {
format("$name$_(::$proto_ns$::internal::ConstantInitialized{})");
} else {
format("$name$_()");
}
}
bool MapFieldGenerator::GenerateArenaDestructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (HasDescriptorMethods(descriptor_->file(), options_)) {
// _this is the object being destructed (we are inside a static method
// here).
format("_this->$name$_. ~MapField();\n");
return true;
} else {
return false;
}
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,78 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
#include <map>
#include <string>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_message_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class MapFieldGenerator : public FieldGenerator {
public:
MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options,
MessageSCCAnalyzer* scc_analyzer);
~MapFieldGenerator() override;
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const override;
void GenerateAccessorDeclarations(io::Printer* printer) const override;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override {}
void GenerateCopyConstructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
void GenerateIsInitialized(io::Printer* printer) const override;
void GenerateConstinitInitializer(io::Printer* printer) const override;
bool GenerateArenaDestructorCode(io::Printer* printer) const override;
private:
const bool has_required_fields_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,231 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
#include <cstdint>
#include <memory>
#include <set>
#include <string>
#include <thirdparty/protobuf/compiler/cpp/cpp_field.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_message_layout_helper.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_options.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_parse_function_generator.h>
namespace google {
namespace protobuf {
namespace io {
class Printer; // printer.h
}
} // namespace protobuf
} // namespace google
namespace google {
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.
MessageGenerator(const Descriptor* descriptor,
const std::map<std::string, std::string>& vars,
int index_in_file_messages, const Options& options,
MessageSCCAnalyzer* scc_analyzer);
~MessageGenerator();
// Append the two types of nested generators to the corresponding vector.
void AddGenerators(
std::vector<std::unique_ptr<EnumGenerator>>* enum_generators,
std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators);
// 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 all non-inline methods for this class.
void GenerateClassMethods(io::Printer* printer);
// Generate source file code that should go outside any namespace.
void GenerateSourceInProto2Namespace(io::Printer* printer);
private:
// Generate declarations and definitions of accessors for fields.
void GenerateFieldAccessorDeclarations(io::Printer* printer);
void GenerateFieldAccessorDefinitions(io::Printer* printer);
// Generate the table-driven parsing array. Returns the number of entries
// generated.
size_t GenerateParseOffsets(io::Printer* printer);
size_t GenerateParseAuxTable(io::Printer* printer);
// Generates a ParseTable entry. Returns whether the proto uses
// table-driven parsing.
bool GenerateParseTable(io::Printer* printer, size_t offset,
size_t aux_offset);
// Generate the field offsets array. Returns the a pair of the total number
// of entries generated and the index of the first has_bit entry.
std::pair<size_t, size_t> GenerateOffsets(io::Printer* printer);
void GenerateSchema(io::Printer* printer, int offset, int has_offset);
// For each field generates a table entry describing the field for the
// table driven serializer.
int GenerateFieldMetadata(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 the arena-specific destructor code.
void GenerateArenaDestructorCode(io::Printer* printer);
// Generate the constexpr constructor for constant initialization of the
// default instance.
void GenerateConstexprConstructor(io::Printer* printer);
// Generate standard Message methods.
void GenerateClear(io::Printer* printer);
void GenerateOneofClear(io::Printer* printer);
void GenerateVerify(io::Printer* printer);
void GenerateSerializeWithCachedSizes(io::Printer* printer);
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer);
void GenerateSerializeWithCachedSizesBody(io::Printer* printer);
void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* printer);
void GenerateByteSize(io::Printer* printer);
void GenerateMergeFrom(io::Printer* printer);
void GenerateClassSpecificMergeFrom(io::Printer* printer);
void GenerateCopyFrom(io::Printer* printer);
void GenerateSwap(io::Printer* printer);
void GenerateIsInitialized(io::Printer* printer);
// Helpers for GenerateSerializeWithCachedSizes().
//
// cached_has_bit_index maintains that:
// cached_has_bits = _has_bits_[cached_has_bit_index]
// for cached_has_bit_index >= 0
void GenerateSerializeOneField(io::Printer* printer,
const FieldDescriptor* field,
int cached_has_bits_index);
// Generate a switch statement to serialize 2+ fields from the same oneof.
// Or, if fields.size() == 1, just call GenerateSerializeOneField().
void GenerateSerializeOneofFields(
io::Printer* printer, const std::vector<const FieldDescriptor*>& fields);
void GenerateSerializeOneExtensionRange(
io::Printer* printer, const Descriptor::ExtensionRange* range);
// Generates has_foo() functions and variables for singular field has-bits.
void GenerateSingularFieldHasBits(const FieldDescriptor* field,
Formatter format);
// Generates has_foo() functions and variables for oneof field has-bits.
void GenerateOneofHasBits(io::Printer* printer);
// Generates has_foo_bar() functions for oneof members.
void GenerateOneofMemberHasBits(const FieldDescriptor* field,
const Formatter& format);
// Generates the clear_foo() method for a field.
void GenerateFieldClear(const FieldDescriptor* field, bool is_inline,
Formatter format);
void GenerateConstructorBody(io::Printer* printer,
std::vector<bool> already_processed,
bool copy_constructor) const;
size_t HasBitsSize() const;
size_t InlinedStringDonatedSize() const;
int HasBitIndex(const FieldDescriptor* a) const;
int HasByteIndex(const FieldDescriptor* a) const;
int HasWordIndex(const FieldDescriptor* a) const;
bool SameHasByte(const FieldDescriptor* a, const FieldDescriptor* b) const;
std::vector<uint32_t> RequiredFieldsBitMask() const;
const Descriptor* descriptor_;
int index_in_file_messages_;
std::string classname_;
Options options_;
FieldGeneratorMap field_generators_;
// optimized_order_ is the order we layout the message's fields in the
// class. This is reused to initialize the fields in-order for cache
// efficiency.
//
// optimized_order_ excludes oneof fields and weak fields.
std::vector<const FieldDescriptor*> optimized_order_;
std::vector<int> has_bit_indices_;
int max_has_bit_index_;
// A map from field index to inlined_string index. For non-inlined-string
// fields, the element is -1.
std::vector<int> inlined_string_indices_;
// The count of inlined_string fields in the message.
int max_inlined_string_index_;
std::vector<const EnumGenerator*> enum_generators_;
std::vector<const ExtensionGenerator*> extension_generators_;
int num_required_fields_;
int num_weak_fields_;
// table_driven_ indicates the generated message uses table-driven parsing.
bool table_driven_;
std::unique_ptr<MessageLayoutHelper> message_layout_helper_;
std::unique_ptr<ParseFunctionGenerator> parse_function_generator_;
MessageSCCAnalyzer* scc_analyzer_;
std::map<std::string, std::string> variables_;
friend class FileGenerator;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__

View File

@ -0,0 +1,892 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <thirdparty/protobuf/compiler/cpp/cpp_message_field.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
std::string ReinterpretCast(const std::string& type,
const std::string& expression,
bool implicit_weak_field) {
if (implicit_weak_field) {
return "reinterpret_cast< " + type + " >(" + expression + ")";
} else {
return expression;
}
}
void SetMessageVariables(const FieldDescriptor* descriptor,
const Options& options, bool implicit_weak,
std::map<std::string, std::string>* variables) {
SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = FieldMessageTypeName(descriptor, options);
(*variables)["casted_member"] = ReinterpretCast(
(*variables)["type"] + "*", (*variables)["name"] + "_", implicit_weak);
(*variables)["type_default_instance"] =
QualifiedDefaultInstanceName(descriptor->message_type(), options);
(*variables)["type_default_instance_ptr"] =
QualifiedDefaultInstancePtr(descriptor->message_type(), options);
(*variables)["type_reference_function"] =
implicit_weak ? (" ::" + (*variables)["proto_ns"] +
"::internal::StrongReference(reinterpret_cast<const " +
(*variables)["type"] + "&>(\n" +
(*variables)["type_default_instance"] + "));\n")
: "";
// NOTE: Escaped here to unblock proto1->proto2 migration.
// TODO(liujisi): Extend this to apply for other conflicting methods.
(*variables)["release_name"] =
SafeFunctionName(descriptor->containing_type(), descriptor, "release_");
(*variables)["full_name"] = descriptor->full_name();
}
} // namespace
// ===================================================================
MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options,
MessageSCCAnalyzer* scc_analyzer)
: FieldGenerator(descriptor, options),
implicit_weak_field_(
IsImplicitWeakField(descriptor, options, scc_analyzer)),
has_required_fields_(
scc_analyzer->HasRequiredFields(descriptor->message_type())) {
SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
}
MessageFieldGenerator::~MessageFieldGenerator() {}
void MessageFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
Formatter format(printer, variables_);
if (implicit_weak_field_) {
format("::$proto_ns$::MessageLite* $name$_;\n");
} else {
format("$type$* $name$_;\n");
}
}
void MessageFieldGenerator::GenerateAccessorDeclarations(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (IsFieldStripped(descriptor_, options_)) {
format(
"$deprecated_attr$const $type$& ${1$$name$$}$() const { "
"__builtin_trap(); }\n"
"PROTOBUF_NODISCARD $deprecated_attr$$type$* "
"${1$$release_name$$}$() { "
"__builtin_trap(); }\n"
"$deprecated_attr$$type$* ${1$mutable_$name$$}$() { "
"__builtin_trap(); }\n"
"$deprecated_attr$void ${1$set_allocated_$name$$}$"
"($type$* $name$) { __builtin_trap(); }\n"
"$deprecated_attr$void "
"${1$unsafe_arena_set_allocated_$name$$}$(\n"
" $type$* $name$) { __builtin_trap(); }\n"
"$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$() { "
"__builtin_trap(); }\n",
descriptor_);
return;
}
format(
"$deprecated_attr$const $type$& ${1$$name$$}$() const;\n"
"PROTOBUF_NODISCARD $deprecated_attr$$type$* "
"${1$$release_name$$}$();\n"
"$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n"
"$deprecated_attr$void ${1$set_allocated_$name$$}$"
"($type$* $name$);\n",
descriptor_);
if (!IsFieldStripped(descriptor_, options_)) {
format(
"private:\n"
"const $type$& ${1$_internal_$name$$}$() const;\n"
"$type$* ${1$_internal_mutable_$name$$}$();\n"
"public:\n",
descriptor_);
}
format(
"$deprecated_attr$void "
"${1$unsafe_arena_set_allocated_$name$$}$(\n"
" $type$* $name$);\n"
"$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$();\n",
descriptor_);
}
void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
io::Printer* printer) const {
}
void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline const $type$& $classname$::_internal_$name$() const {\n"
"$type_reference_function$"
" const $type$* p = $casted_member$;\n"
" return p != nullptr ? *p : reinterpret_cast<const $type$&>(\n"
" $type_default_instance$);\n"
"}\n"
"inline const $type$& $classname$::$name$() const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$();\n"
"}\n");
format(
"inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
" $type$* $name$) {\n"
// If we're not on an arena, free whatever we were holding before.
// (If we are on arena, we can just forget the earlier pointer.)
" if (GetArenaForAllocation() == nullptr) {\n"
" delete reinterpret_cast<::$proto_ns$::MessageLite*>($name$_);\n"
" }\n");
if (implicit_weak_field_) {
format(
" $name$_ = "
"reinterpret_cast<::$proto_ns$::MessageLite*>($name$);\n");
} else {
format(" $name$_ = $name$;\n");
}
format(
" if ($name$) {\n"
" $set_hasbit$\n"
" } else {\n"
" $clear_hasbit$\n"
" }\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
":$full_name$)\n"
"}\n");
format(
"inline $type$* $classname$::$release_name$() {\n"
"$type_reference_function$"
"$annotate_release$"
" $clear_hasbit$\n"
" $type$* temp = $casted_member$;\n"
" $name$_ = nullptr;\n"
"#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE\n"
" auto* old = reinterpret_cast<::$proto_ns$::MessageLite*>(temp);\n"
" temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
" if (GetArenaForAllocation() == nullptr) { delete old; }\n"
"#else // PROTOBUF_FORCE_COPY_IN_RELEASE\n"
" if (GetArenaForAllocation() != nullptr) {\n"
" temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
" }\n"
"#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE\n"
" return temp;\n"
"}\n"
"inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
"$annotate_release$"
" // @@protoc_insertion_point(field_release:$full_name$)\n"
"$type_reference_function$"
" $clear_hasbit$\n"
" $type$* temp = $casted_member$;\n"
" $name$_ = nullptr;\n"
" return temp;\n"
"}\n");
format(
"inline $type$* $classname$::_internal_mutable_$name$() {\n"
"$type_reference_function$"
" $set_hasbit$\n"
" if ($name$_ == nullptr) {\n"
" auto* p = CreateMaybeMessage<$type$>(GetArenaForAllocation());\n");
if (implicit_weak_field_) {
format(" $name$_ = reinterpret_cast<::$proto_ns$::MessageLite*>(p);\n");
} else {
format(" $name$_ = p;\n");
}
format(
" }\n"
" return $casted_member$;\n"
"}\n"
"inline $type$* $classname$::mutable_$name$() {\n"
" $type$* _msg = _internal_mutable_$name$();\n"
"$annotate_mutable$"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return _msg;\n"
"}\n");
// We handle the most common case inline, and delegate less common cases to
// the slow fallback function.
format(
"inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
" ::$proto_ns$::Arena* message_arena = GetArenaForAllocation();\n");
format(" if (message_arena == nullptr) {\n");
if (IsCrossFileMessage(descriptor_)) {
format(
" delete reinterpret_cast< ::$proto_ns$::MessageLite*>($name$_);\n");
} else {
format(" delete $name$_;\n");
}
format(
" }\n"
" if ($name$) {\n");
if (IsCrossFileMessage(descriptor_)) {
// We have to read the arena through the virtual method, because the type
// isn't defined in this file.
format(
" ::$proto_ns$::Arena* submessage_arena =\n"
" ::$proto_ns$::Arena::InternalHelper<\n"
" ::$proto_ns$::MessageLite>::GetOwningArena(\n"
" reinterpret_cast<::$proto_ns$::MessageLite*>("
"$name$));\n");
} else {
format(
" ::$proto_ns$::Arena* submessage_arena =\n"
" ::$proto_ns$::Arena::InternalHelper<$type$>::GetOwningArena("
"$name$);\n");
}
format(
" if (message_arena != submessage_arena) {\n"
" $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n"
" message_arena, $name$, submessage_arena);\n"
" }\n"
" $set_hasbit$\n"
" } else {\n"
" $clear_hasbit$\n"
" }\n");
if (implicit_weak_field_) {
format(" $name$_ = reinterpret_cast<MessageLite*>($name$);\n");
} else {
format(" $name$_ = $name$;\n");
}
format(
"$annotate_set$"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
}
void MessageFieldGenerator::GenerateInternalAccessorDeclarations(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (implicit_weak_field_) {
format(
"static const ::$proto_ns$::MessageLite& $name$("
"const $classname$* msg);\n"
"static ::$proto_ns$::MessageLite* mutable_$name$("
"$classname$* msg);\n");
} else {
format("static const $type$& $name$(const $classname$* msg);\n");
}
}
void MessageFieldGenerator::GenerateInternalAccessorDefinitions(
io::Printer* printer) const {
// In theory, these accessors could be inline in _Internal. However, in
// practice, the linker is then not able to throw them out making implicit
// weak dependencies not work at all.
Formatter format(printer, variables_);
if (implicit_weak_field_) {
// These private accessors are used by MergeFrom and
// MergePartialFromCodedStream, and their purpose is to provide access to
// the field without creating a strong dependency on the message type.
format(
"const ::$proto_ns$::MessageLite& $classname$::_Internal::$name$(\n"
" const $classname$* msg) {\n"
" if (msg->$name$_ != nullptr) {\n"
" return *msg->$name$_;\n"
" } else if ($type_default_instance_ptr$ != nullptr) {\n"
" return *reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
" $type_default_instance_ptr$);\n"
" } else {\n"
" return "
"*::$proto_ns$::internal::ImplicitWeakMessage::default_instance();\n"
" }\n"
"}\n");
format(
"::$proto_ns$::MessageLite*\n"
"$classname$::_Internal::mutable_$name$($classname$* msg) {\n");
if (HasHasbit(descriptor_)) {
format(" msg->$set_hasbit$\n");
}
format(
" if (msg->$name$_ == nullptr) {\n"
" if ($type_default_instance_ptr$ == nullptr) {\n"
" msg->$name$_ = ::$proto_ns$::Arena::CreateMessage<\n"
" ::$proto_ns$::internal::ImplicitWeakMessage>(\n"
" msg->GetArenaForAllocation());\n"
" } else {\n"
" msg->$name$_ = \n"
" reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
" $type_default_instance_ptr$)->New(\n"
" msg->GetArenaForAllocation());\n"
" }\n"
" }\n"
" return msg->$name$_;\n"
"}\n");
} else {
// This inline accessor directly returns member field and is used in
// Serialize such that AFDO profile correctly captures access information to
// message fields under serialize.
format(
"const $type$&\n"
"$classname$::_Internal::$name$(const $classname$* msg) {\n"
" return *msg->$field_member$;\n"
"}\n");
}
}
void MessageFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
if (!HasHasbit(descriptor_)) {
// If we don't have has-bits, message presence is indicated only by ptr !=
// NULL. Thus on clear, we need to delete the object.
format(
"if (GetArenaForAllocation() == nullptr && $name$_ != nullptr) {\n"
" delete $name$_;\n"
"}\n"
"$name$_ = nullptr;\n");
} else {
format("if ($name$_ != nullptr) $name$_->Clear();\n");
}
}
void MessageFieldGenerator::GenerateMessageClearingCode(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
if (!HasHasbit(descriptor_)) {
// If we don't have has-bits, message presence is indicated only by ptr !=
// NULL. Thus on clear, we need to delete the object.
format(
"if (GetArenaForAllocation() == nullptr && $name$_ != nullptr) {\n"
" delete $name$_;\n"
"}\n"
"$name$_ = nullptr;\n");
} else {
format(
"$DCHK$($name$_ != nullptr);\n"
"$name$_->Clear();\n");
}
}
void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
if (implicit_weak_field_) {
format(
"_Internal::mutable_$name$(this)->CheckTypeAndMergeFrom(\n"
" _Internal::$name$(&from));\n");
} else {
format(
"_internal_mutable_$name$()->$type$::MergeFrom(from._internal_$name$())"
";\n");
}
}
void MessageFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
format("swap($name$_, other->$name$_);\n");
}
void MessageFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
if (options_.opensource_runtime) {
// TODO(gerbens) Remove this when we don't need to destruct default
// instances. In google3 a default instance will never get deleted so we
// don't need to worry about that but in opensource protobuf default
// instances are deleted in shutdown process and we need to take special
// care when handling them.
format("if (this != internal_default_instance()) ");
}
format("delete $name$_;\n");
}
void MessageFieldGenerator::GenerateConstructorCode(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
format("$name$_ = nullptr;\n");
}
void MessageFieldGenerator::GenerateCopyConstructorCode(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
format(
"if (from._internal_has_$name$()) {\n"
" $name$_ = new $type$(*from.$name$_);\n"
"} else {\n"
" $name$_ = nullptr;\n"
"}\n");
}
void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
format(
"target = stream->EnsureSpace(target);\n"
"target = ::$proto_ns$::internal::WireFormatLite::\n"
" InternalWrite$declared_type$(\n"
" $number$, _Internal::$name$(this), target, stream);\n");
}
void MessageFieldGenerator::GenerateByteSize(io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
format(
"total_size += $tag_size$ +\n"
" ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
" *$field_member$);\n");
}
void MessageFieldGenerator::GenerateIsInitialized(io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
if (!has_required_fields_) return;
Formatter format(printer, variables_);
format(
"if (_internal_has_$name$()) {\n"
" if (!$name$_->IsInitialized()) return false;\n"
"}\n");
}
void MessageFieldGenerator::GenerateConstinitInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_(nullptr)");
}
// ===================================================================
MessageOneofFieldGenerator::MessageOneofFieldGenerator(
const FieldDescriptor* descriptor, const Options& options,
MessageSCCAnalyzer* scc_analyzer)
: MessageFieldGenerator(descriptor, options, scc_analyzer) {
SetCommonOneofFieldVariables(descriptor, &variables_);
}
MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"void $classname$::set_allocated_$name$($type$* $name$) {\n"
" ::$proto_ns$::Arena* message_arena = GetArenaForAllocation();\n"
" clear_$oneof_name$();\n"
" if ($name$) {\n");
if (descriptor_->file() != descriptor_->message_type()->file()) {
// We have to read the arena through the virtual method, because the type
// isn't defined in this file.
format(
" ::$proto_ns$::Arena* submessage_arena =\n"
" ::$proto_ns$::Arena::InternalHelper<\n"
" ::$proto_ns$::MessageLite>::GetOwningArena(\n"
" reinterpret_cast<::$proto_ns$::MessageLite*>("
"$name$));\n");
} else {
format(
" ::$proto_ns$::Arena* submessage_arena =\n"
" ::$proto_ns$::Arena::InternalHelper<"
"$type$>::GetOwningArena($name$);\n");
}
format(
" if (message_arena != submessage_arena) {\n"
" $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n"
" message_arena, $name$, submessage_arena);\n"
" }\n"
" set_has_$name$();\n"
" $field_member$ = $name$;\n"
" }\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
}
void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline $type$* $classname$::$release_name$() {\n"
"$annotate_release$"
" // @@protoc_insertion_point(field_release:$full_name$)\n"
" if (_internal_has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" $type$* temp = $field_member$;\n"
" if (GetArenaForAllocation() != nullptr) {\n"
" temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
" }\n"
" $field_member$ = nullptr;\n"
" return temp;\n"
" } else {\n"
" return nullptr;\n"
" }\n"
"}\n");
format(
"inline const $type$& $classname$::_internal_$name$() const {\n"
" return _internal_has_$name$()\n"
" ? *$field_member$\n"
" : reinterpret_cast< $type$&>($type_default_instance$);\n"
"}\n"
"inline const $type$& $classname$::$name$() const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$();\n"
"}\n"
"inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
"$annotate_release$"
" // @@protoc_insertion_point(field_unsafe_arena_release"
":$full_name$)\n"
" if (_internal_has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" $type$* temp = $field_member$;\n"
" $field_member$ = nullptr;\n"
" return temp;\n"
" } else {\n"
" return nullptr;\n"
" }\n"
"}\n"
"inline void $classname$::unsafe_arena_set_allocated_$name$"
"($type$* $name$) {\n"
// We rely on the oneof clear method to free the earlier contents of
// this oneof. We can directly use the pointer we're given to set the
// new value.
" clear_$oneof_name$();\n"
" if ($name$) {\n"
" set_has_$name$();\n"
" $field_member$ = $name$;\n"
" }\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
"$full_name$)\n"
"}\n"
"inline $type$* $classname$::_internal_mutable_$name$() {\n"
" if (!_internal_has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $field_member$ = CreateMaybeMessage< $type$ "
">(GetArenaForAllocation());\n"
" }\n"
" return $field_member$;\n"
"}\n"
"inline $type$* $classname$::mutable_$name$() {\n"
" $type$* _msg = _internal_mutable_$name$();\n"
"$annotate_mutable$"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return _msg;\n"
"}\n");
}
void MessageOneofFieldGenerator::GenerateClearingCode(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
format(
"if (GetArenaForAllocation() == nullptr) {\n"
" delete $field_member$;\n"
"}\n");
}
void MessageOneofFieldGenerator::GenerateMessageClearingCode(
io::Printer* printer) const {
GenerateClearingCode(printer);
}
void MessageOneofFieldGenerator::GenerateSwappingCode(
io::Printer* printer) const {
// Don't print any swapping code. Swapping the union will swap this field.
}
void MessageOneofFieldGenerator::GenerateDestructorCode(
io::Printer* printer) const {
// We inherit from MessageFieldGenerator, so we need to override the default
// behavior.
}
void MessageOneofFieldGenerator::GenerateConstructorCode(
io::Printer* printer) const {
// Don't print any constructor code. The field is in a union. We allocate
// space only when this field is used.
}
void MessageOneofFieldGenerator::GenerateIsInitialized(
io::Printer* printer) const {
if (!has_required_fields_) return;
Formatter format(printer, variables_);
format(
"if (_internal_has_$name$()) {\n"
" if (!$field_member$->IsInitialized()) return false;\n"
"}\n");
}
// ===================================================================
RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
const FieldDescriptor* descriptor, const Options& options,
MessageSCCAnalyzer* scc_analyzer)
: FieldGenerator(descriptor, options),
implicit_weak_field_(
IsImplicitWeakField(descriptor, options, scc_analyzer)),
has_required_fields_(
scc_analyzer->HasRequiredFields(descriptor->message_type())) {
SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
}
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
void RepeatedMessageFieldGenerator::GeneratePrivateMembers(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (implicit_weak_field_) {
format("::$proto_ns$::WeakRepeatedPtrField< $type$ > $name$_;\n");
} else {
format("::$proto_ns$::RepeatedPtrField< $type$ > $name$_;\n");
}
}
void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (IsFieldStripped(descriptor_, options_)) {
format(
"$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index) { "
"__builtin_trap(); }\n"
"$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n"
" ${1$mutable_$name$$}$() { __builtin_trap(); }\n"
"$deprecated_attr$const $type$& ${1$$name$$}$(int index) const { "
"__builtin_trap(); }\n"
"$deprecated_attr$$type$* ${1$add_$name$$}$() { "
"__builtin_trap(); }\n"
"$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
" ${1$$name$$}$() const { __builtin_trap(); }\n",
descriptor_);
return;
}
format(
"$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index);\n"
"$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n"
" ${1$mutable_$name$$}$();\n",
descriptor_);
if (!IsFieldStripped(descriptor_, options_)) {
format(
"private:\n"
"const $type$& ${1$_internal_$name$$}$(int index) const;\n"
"$type$* ${1$_internal_add_$name$$}$();\n"
"public:\n",
descriptor_);
}
format(
"$deprecated_attr$const $type$& ${1$$name$$}$(int index) const;\n"
"$deprecated_attr$$type$* ${1$add_$name$$}$();\n"
"$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
" ${1$$name$$}$() const;\n",
descriptor_);
}
void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format.Set("weak", implicit_weak_field_ ? ".weak" : "");
format(
"inline $type$* $classname$::mutable_$name$(int index) {\n"
"$annotate_mutable$"
// TODO(dlj): move insertion points
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
"$type_reference_function$"
" return $name$_$weak$.Mutable(index);\n"
"}\n"
"inline ::$proto_ns$::RepeatedPtrField< $type$ >*\n"
"$classname$::mutable_$name$() {\n"
"$annotate_mutable_list$"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
"$type_reference_function$"
" return &$name$_$weak$;\n"
"}\n");
if (options_.safe_boundary_check) {
format(
"inline const $type$& $classname$::_internal_$name$(int index) const "
"{\n"
" return $name$_$weak$.InternalCheckedGet(index,\n"
" reinterpret_cast<const $type$&>($type_default_instance$));\n"
"}\n");
} else {
format(
"inline const $type$& $classname$::_internal_$name$(int index) const "
"{\n"
"$type_reference_function$"
" return $name$_$weak$.Get(index);\n"
"}\n");
}
format(
"inline const $type$& $classname$::$name$(int index) const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$(index);\n"
"}\n"
"inline $type$* $classname$::_internal_add_$name$() {\n"
" return $name$_$weak$.Add();\n"
"}\n"
"inline $type$* $classname$::add_$name$() {\n"
" $type$* _add = _internal_add_$name$();\n"
"$annotate_add_mutable$"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
" return _add;\n"
"}\n");
format(
"inline const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
"$classname$::$name$() const {\n"
"$annotate_list$"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
"$type_reference_function$"
" return $name$_$weak$;\n"
"}\n");
}
void RepeatedMessageFieldGenerator::GenerateClearingCode(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
format("$name$_.Clear();\n");
}
void RepeatedMessageFieldGenerator::GenerateMergingCode(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
format("$name$_.MergeFrom(from.$name$_);\n");
}
void RepeatedMessageFieldGenerator::GenerateSwappingCode(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
format("$name$_.InternalSwap(&other->$name$_);\n");
}
void RepeatedMessageFieldGenerator::GenerateConstructorCode(
io::Printer* printer) const {
// Not needed for repeated fields.
}
void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
if (implicit_weak_field_) {
format(
"for (auto it = this->$name$_.pointer_begin(),\n"
" end = this->$name$_.pointer_end(); it < end; ++it) {\n"
" target = stream->EnsureSpace(target);\n"
" target = ::$proto_ns$::internal::WireFormatLite::\n"
" InternalWrite$declared_type$($number$, **it, target, stream);\n"
"}\n");
} else {
format(
"for (unsigned int i = 0,\n"
" n = static_cast<unsigned int>(this->_internal_$name$_size()); i < "
"n; i++) "
"{\n"
" target = stream->EnsureSpace(target);\n"
" target = ::$proto_ns$::internal::WireFormatLite::\n"
" InternalWrite$declared_type$($number$, "
"this->_internal_$name$(i), target, stream);\n"
"}\n");
}
}
void RepeatedMessageFieldGenerator::GenerateByteSize(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
format(
"total_size += $tag_size$UL * this->_internal_$name$_size();\n"
"for (const auto& msg : this->$name$_) {\n"
" total_size +=\n"
" ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(msg);\n"
"}\n");
}
void RepeatedMessageFieldGenerator::GenerateIsInitialized(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
if (!has_required_fields_) return;
Formatter format(printer, variables_);
if (implicit_weak_field_) {
format(
"if (!::$proto_ns$::internal::AllAreInitializedWeak($name$_.weak))\n"
" return false;\n");
} else {
format(
"if (!::$proto_ns$::internal::AllAreInitialized($name$_))\n"
" return false;\n");
}
}
void RepeatedMessageFieldGenerator::GenerateConstinitInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_()");
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,144 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
#include <map>
#include <string>
#include <thirdparty/protobuf/compiler/cpp/cpp_field.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class MessageFieldGenerator : public FieldGenerator {
public:
MessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options,
MessageSCCAnalyzer* scc_analyzer);
~MessageFieldGenerator() override;
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const override;
void GenerateAccessorDeclarations(io::Printer* printer) const override;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateNonInlineAccessorDefinitions(
io::Printer* printer) const override;
void GenerateInternalAccessorDeclarations(
io::Printer* printer) const override;
void GenerateInternalAccessorDefinitions(io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateMessageClearingCode(io::Printer* printer) const override;
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateDestructorCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
void GenerateCopyConstructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
void GenerateIsInitialized(io::Printer* printer) const override;
void GenerateConstinitInitializer(io::Printer* printer) const override;
protected:
const bool implicit_weak_field_;
const bool has_required_fields_;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
};
class MessageOneofFieldGenerator : public MessageFieldGenerator {
public:
MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options,
MessageSCCAnalyzer* scc_analyzer);
~MessageOneofFieldGenerator() override;
// implements FieldGenerator ---------------------------------------
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateNonInlineAccessorDefinitions(
io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
// MessageFieldGenerator, from which we inherit, overrides this so we need to
// override it as well.
void GenerateMessageClearingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateDestructorCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
void GenerateIsInitialized(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
};
class RepeatedMessageFieldGenerator : public FieldGenerator {
public:
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options,
MessageSCCAnalyzer* scc_analyzer);
~RepeatedMessageFieldGenerator() override;
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const override;
void GenerateAccessorDeclarations(io::Printer* printer) const override;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
void GenerateCopyConstructorCode(io::Printer* printer) const override {}
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
void GenerateIsInitialized(io::Printer* printer) const override;
void GenerateConstinitInitializer(io::Printer* printer) const override;
private:
const bool implicit_weak_field_;
const bool has_required_fields_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__

View File

@ -0,0 +1,64 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: seongkim@google.com (Seong Beom Kim)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
#include <thirdparty/protobuf/compiler/cpp/cpp_options.h>
#include <thirdparty/protobuf/descriptor.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class MessageSCCAnalyzer;
// Provides an abstract interface to optimize message layout
// by rearranging the fields of a message.
class MessageLayoutHelper {
public:
virtual ~MessageLayoutHelper() {}
virtual void OptimizeLayout(std::vector<const FieldDescriptor*>* fields,
const Options& options,
MessageSCCAnalyzer* scc_analyzer) = 0;
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__

View File

@ -0,0 +1,169 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/test_util.h>
#include <thirdparty/protobuf/unittest.pb.h>
#include <gtest/gtest.h>
#if LANG_CXX11
#include <type_traits>
#endif
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
namespace cpp_unittest {
// Moves are enabled only when compiling with a C++11 compiler or newer.
#if LANG_CXX11
TEST(MovableMessageTest, MoveConstructor) {
protobuf_unittest::TestAllTypes message1;
TestUtil::SetAllFields(&message1);
const auto* nested = &message1.optional_nested_message();
protobuf_unittest::TestAllTypes message2(std::move(message1));
TestUtil::ExpectAllFieldsSet(message2);
// Check if the optional_nested_message was actually moved (and not just
// copied).
EXPECT_EQ(nested, &message2.optional_nested_message());
EXPECT_NE(nested, &message1.optional_nested_message());
}
TEST(MovableMessageTest, MoveAssignmentOperator) {
protobuf_unittest::TestAllTypes message1;
TestUtil::SetAllFields(&message1);
const auto* nested = &message1.optional_nested_message();
protobuf_unittest::TestAllTypes message2;
message2 = std::move(message1);
TestUtil::ExpectAllFieldsSet(message2);
// Check if the optional_nested_message was actually moved (and not just
// copied).
EXPECT_EQ(nested, &message2.optional_nested_message());
EXPECT_NE(nested, &message1.optional_nested_message());
}
TEST(MovableMessageTest, SelfMoveAssignment) {
// The `self` reference is necessary to defeat -Wself-move.
protobuf_unittest::TestAllTypes message, &self = message;
TestUtil::SetAllFields(&message);
message = std::move(self);
TestUtil::ExpectAllFieldsSet(message);
}
TEST(MovableMessageTest, MoveSameArena) {
Arena arena;
auto* message1_on_arena =
Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
TestUtil::SetAllFields(message1_on_arena);
const auto* nested = &message1_on_arena->optional_nested_message();
auto* message2_on_arena =
Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
// Moving messages on the same arena should lead to swapped pointers.
*message2_on_arena = std::move(*message1_on_arena);
EXPECT_EQ(nested, &message2_on_arena->optional_nested_message());
}
TEST(MovableMessageTest, MoveDifferentArenas) {
Arena arena1, arena2;
auto* message1_on_arena =
Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena1);
TestUtil::SetAllFields(message1_on_arena);
const auto* nested = &message1_on_arena->optional_nested_message();
auto* message2_on_arena =
Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena2);
// Moving messages on two different arenas should lead to a copy.
*message2_on_arena = std::move(*message1_on_arena);
EXPECT_NE(nested, &message2_on_arena->optional_nested_message());
TestUtil::ExpectAllFieldsSet(*message1_on_arena);
TestUtil::ExpectAllFieldsSet(*message2_on_arena);
}
TEST(MovableMessageTest, MoveFromArena) {
Arena arena;
auto* message1_on_arena =
Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
TestUtil::SetAllFields(message1_on_arena);
const auto* nested = &message1_on_arena->optional_nested_message();
protobuf_unittest::TestAllTypes message2;
// Moving from a message on the arena should lead to a copy.
message2 = std::move(*message1_on_arena);
EXPECT_NE(nested, &message2.optional_nested_message());
TestUtil::ExpectAllFieldsSet(*message1_on_arena);
TestUtil::ExpectAllFieldsSet(message2);
}
TEST(MovableMessageTest, MoveToArena) {
Arena arena;
protobuf_unittest::TestAllTypes message1;
TestUtil::SetAllFields(&message1);
const auto* nested = &message1.optional_nested_message();
auto* message2_on_arena =
Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
// Moving to a message on the arena should lead to a copy.
*message2_on_arena = std::move(message1);
EXPECT_NE(nested, &message2_on_arena->optional_nested_message());
TestUtil::ExpectAllFieldsSet(message1);
TestUtil::ExpectAllFieldsSet(*message2_on_arena);
}
TEST(MovableMessageTest, Noexcept) {
EXPECT_TRUE(
std::is_nothrow_move_constructible<protobuf_unittest::TestAllTypes>());
EXPECT_TRUE(std::is_nothrow_move_assignable<protobuf_unittest::TestAllTypes>());
}
#endif // LANG_CXX11
} // namespace cpp_unittest
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,96 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
#include <string>
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
class Descriptor;
class EnumDescriptor;
class EnumValueDescriptor;
class FieldDescriptor;
namespace compiler {
namespace cpp {
// Returns the unqualified C++ name.
//
// For example, if you had:
// package foo.bar;
// message Baz { message Qux {} }
// Then the non-qualified version would be:
// Baz_Qux
std::string ClassName(const Descriptor* descriptor);
std::string ClassName(const EnumDescriptor* enum_descriptor);
// Returns the fully qualified C++ name.
//
// For example, if you had:
// package foo.bar;
// message Baz { message Qux {} }
// Then the qualified ClassName for Qux would be:
// ::foo::bar::Baz_Qux
std::string QualifiedClassName(const Descriptor* d);
std::string QualifiedClassName(const EnumDescriptor* d);
std::string QualifiedExtensionName(const FieldDescriptor* d);
// 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().
std::string FieldName(const FieldDescriptor* field);
// Requires that this field is in a oneof. Returns the (unqualified) case
// constant for this field.
std::string OneofCaseConstantName(const FieldDescriptor* field);
// Returns the quafilied case constant for this field.
std::string QualifiedOneofCaseConstantName(const FieldDescriptor* field);
// Get the (unqualified) name that should be used for this enum value in C++
// code.
std::string EnumValueName(const EnumValueDescriptor* enum_value);
// Strips ".proto" or ".protodevel" from the end of a filename.
PROTOC_EXPORT std::string StripProto(const std::string& filename);
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__

View File

@ -0,0 +1,95 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: rennie@google.com (Jeffrey Rennie)
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
#include <set>
#include <string>
namespace google {
namespace protobuf {
namespace compiler {
class AccessInfoMap;
namespace cpp {
enum class EnforceOptimizeMode {
kNoEnforcement, // Use the runtime specified by the file specific options.
kSpeed, // Full runtime with a generated code implementation.
kCodeSize, // Full runtime with a reflective implementation.
kLiteRuntime,
};
struct FieldListenerOptions {
bool inject_field_listener_events = false;
std::set<std::string> forbidden_field_listener_events;
};
// Generator options (see generator.cc for a description of each):
struct Options {
std::string dllexport_decl;
bool safe_boundary_check = false;
bool proto_h = false;
bool transitive_pb_h = true;
bool annotate_headers = false;
EnforceOptimizeMode enforce_mode = EnforceOptimizeMode::kNoEnforcement;
bool table_driven_parsing = false;
bool table_driven_serialization = false;
bool lite_implicit_weak_fields = false;
bool bootstrap = false;
bool opensource_runtime = false;
bool annotate_accessor = false;
bool unused_field_stripping = false;
bool profile_driven_inline_string = true;
bool force_inline_string = false;
std::string runtime_include_base;
int num_cc_files = 0;
std::string annotation_pragma_name;
std::string annotation_guard_name;
const AccessInfoMap* access_info_map = nullptr;
enum {
kTCTableNever,
kTCTableGuarded,
kTCTableAlways
} tctable_mode = kTCTableNever;
FieldListenerOptions field_listener_options;
bool eagerly_verified_lazy = false;
bool force_eagerly_verified_lazy = false;
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__

View File

@ -0,0 +1,228 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <thirdparty/protobuf/compiler/cpp/cpp_padding_optimizer.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
// FieldGroup is just a helper for PaddingOptimizer below. It holds a vector of
// fields that are grouped together because they have compatible alignment, and
// a preferred location in the final field ordering.
class FieldGroup {
public:
FieldGroup() : preferred_location_(0) {}
// A group with a single field.
FieldGroup(float preferred_location, const FieldDescriptor* field)
: preferred_location_(preferred_location), fields_(1, field) {}
// Append the fields in 'other' to this group.
void Append(const FieldGroup& other) {
if (other.fields_.empty()) {
return;
}
// Preferred location is the average among all the fields, so we weight by
// the number of fields on each FieldGroup object.
preferred_location_ = (preferred_location_ * fields_.size() +
(other.preferred_location_ * other.fields_.size())) /
(fields_.size() + other.fields_.size());
fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end());
}
void SetPreferredLocation(float location) { preferred_location_ = location; }
const std::vector<const FieldDescriptor*>& fields() const { return fields_; }
// FieldGroup objects sort by their preferred location.
bool operator<(const FieldGroup& other) const {
return preferred_location_ < other.preferred_location_;
}
private:
// "preferred_location_" is an estimate of where this group should go in the
// final list of fields. We compute this by taking the average index of each
// field in this group in the original ordering of fields. This is very
// approximate, but should put this group close to where its member fields
// originally went.
float preferred_location_;
std::vector<const FieldDescriptor*> fields_;
// We rely on the default copy constructor and operator= so this type can be
// used in a vector.
};
} // namespace
// Reorder 'fields' so that if the fields are output into a c++ class in the new
// order, fields of similar family (see below) are together and within each
// family, alignment padding is minimized.
//
// We try to do this while keeping each field as close as possible to its field
// number order so that we don't reduce cache locality much for function that
// access each field in order. Originally, OptimizePadding used declaration
// order for its decisions, but generated code minus the serializer/parsers uses
// the output of OptimizePadding as well (stored in
// MessageGenerator::optimized_order_). Since the serializers use field number
// order, we use that as a tie-breaker.
//
// We classify each field into a particular "family" of fields, that we perform
// the same operation on in our generated functions.
//
// REPEATED is placed first, as the C++ compiler automatically initializes
// these fields in layout order.
//
// STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and
// calls ArenaStringPtr::Destroy on each.
//
// LAZY_MESSAGE is grouped next, as it interferes with the ability to memset
// non-repeated fields otherwise.
//
// MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls
// delete on each. We initialize these fields with a NULL pointer (see
// MessageFieldGenerator::GenerateConstructorCode), which allows them to be
// memset.
//
// ZERO_INITIALIZABLE is memset in Clear/SharedCtor
//
// OTHER these fields are initialized one-by-one.
void PaddingOptimizer::OptimizeLayout(
std::vector<const FieldDescriptor*>* fields, const Options& options,
MessageSCCAnalyzer* scc_analyzer) {
// The sorted numeric order of Family determines the declaration order in the
// memory layout.
enum Family {
REPEATED = 0,
STRING = 1,
// Laying out LAZY_MESSAGE before MESSAGE allows a single memset to zero
// MESSAGE and ZERO_INITIALIZABLE fields together.
LAZY_MESSAGE = 2,
MESSAGE = 3,
ZERO_INITIALIZABLE = 4,
OTHER = 5,
kMaxFamily
};
// First divide fields into those that align to 1 byte, 4 bytes or 8 bytes.
std::vector<FieldGroup> aligned_to_1[kMaxFamily];
std::vector<FieldGroup> aligned_to_4[kMaxFamily];
std::vector<FieldGroup> aligned_to_8[kMaxFamily];
for (int i = 0; i < fields->size(); ++i) {
const FieldDescriptor* field = (*fields)[i];
Family f = OTHER;
if (field->is_repeated()) {
f = REPEATED;
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
f = STRING;
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
f = MESSAGE;
if (IsLazy(field, options, scc_analyzer)) {
f = LAZY_MESSAGE;
}
} else if (CanInitializeByZeroing(field)) {
f = ZERO_INITIALIZABLE;
}
const int j = field->number();
switch (EstimateAlignmentSize(field)) {
case 1:
aligned_to_1[f].push_back(FieldGroup(j, field));
break;
case 4:
aligned_to_4[f].push_back(FieldGroup(j, field));
break;
case 8:
aligned_to_8[f].push_back(FieldGroup(j, field));
break;
default:
GOOGLE_LOG(FATAL) << "Unknown alignment size " << EstimateAlignmentSize(field)
<< "for a field " << field->full_name() << ".";
}
}
// For each family, group fields to optimize padding.
for (int f = 0; f < kMaxFamily; f++) {
// Now group fields aligned to 1 byte into sets of 4, and treat those like a
// single field aligned to 4 bytes.
for (int i = 0; i < aligned_to_1[f].size(); i += 4) {
FieldGroup field_group;
for (int j = i; j < aligned_to_1[f].size() && j < i + 4; ++j) {
field_group.Append(aligned_to_1[f][j]);
}
aligned_to_4[f].push_back(field_group);
}
// Sort by preferred location to keep fields as close to their field number
// order as possible. Using stable_sort ensures that the output is
// consistent across runs.
std::stable_sort(aligned_to_4[f].begin(), aligned_to_4[f].end());
// Now group fields aligned to 4 bytes (or the 4-field groups created above)
// into pairs, and treat those like a single field aligned to 8 bytes.
for (int i = 0; i < aligned_to_4[f].size(); i += 2) {
FieldGroup field_group;
for (int j = i; j < aligned_to_4[f].size() && j < i + 2; ++j) {
field_group.Append(aligned_to_4[f][j]);
}
if (i == aligned_to_4[f].size() - 1) {
if (f == OTHER) {
// Move incomplete 4-byte block to the beginning. This is done to
// pair with the (possible) leftover blocks from the
// ZERO_INITIALIZABLE family.
field_group.SetPreferredLocation(-1);
} else {
// Move incomplete 4-byte block to the end.
field_group.SetPreferredLocation(fields->size() + 1);
}
}
aligned_to_8[f].push_back(field_group);
}
// Sort by preferred location.
std::stable_sort(aligned_to_8[f].begin(), aligned_to_8[f].end());
}
// Now pull out all the FieldDescriptors in order.
fields->clear();
for (int f = 0; f < kMaxFamily; ++f) {
for (int i = 0; i < aligned_to_8[f].size(); ++i) {
fields->insert(fields->end(), aligned_to_8[f][i].fields().begin(),
aligned_to_8[f][i].fields().end());
}
}
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,65 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: seongkim@google.com (Seong Beom Kim)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
#include <thirdparty/protobuf/compiler/cpp/cpp_message_layout_helper.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
// Rearranges the fields of a message to minimize padding.
// Fields are grouped by the type and the size.
// For example, grouping four boolean fields and one int32
// field results in zero padding overhead. See OptimizeLayout's
// comment for details.
class PaddingOptimizer : public MessageLayoutHelper {
public:
PaddingOptimizer() {}
~PaddingOptimizer() override {}
void OptimizeLayout(std::vector<const FieldDescriptor*>* fields,
const Options& options,
MessageSCCAnalyzer* scc_analyzer) override;
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,199 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
#include <map>
#include <string>
#include <vector>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_options.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/generated_message_tctable_decl.h>
#include <thirdparty/protobuf/wire_format_lite.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
// Helper class for generating tailcall parsing functions.
struct TailCallTableInfo {
TailCallTableInfo(const Descriptor* descriptor, const Options& options,
const std::vector<int>& has_bit_indices,
MessageSCCAnalyzer* scc_analyzer);
// Information to generate field entries.
struct FieldInfo {
const FieldDescriptor* field;
google::protobuf::internal::TcFieldData bits;
std::string func_name;
};
// Fields parsed by the table fast-path.
std::vector<FieldInfo> fast_path_fields;
// Fields parsed by slow-path fallback.
std::vector<const FieldDescriptor*> fallback_fields;
// Table size.
int table_size_log2;
// Mask for has-bits of required fields.
uint32_t has_hasbits_required_mask;
// True if a generated fallback function is required instead of generic.
bool use_generated_fallback;
};
// ParseFunctionGenerator generates the _InternalParse function for a message
// (and any associated supporting members).
class ParseFunctionGenerator {
public:
ParseFunctionGenerator(const Descriptor* descriptor, int max_has_bit_index,
const std::vector<int>& has_bit_indices,
const std::vector<int>& inlined_string_indices,
const Options& options,
MessageSCCAnalyzer* scc_analyzer,
const std::map<std::string, std::string>& vars);
// Emits class-level method declarations to `printer`:
void GenerateMethodDecls(io::Printer* printer);
// Emits out-of-class method implementation definitions to `printer`:
void GenerateMethodImpls(io::Printer* printer);
// Emits class-level data member declarations to `printer`:
void GenerateDataDecls(io::Printer* printer);
// Emits out-of-class data member definitions to `printer`:
void GenerateDataDefinitions(io::Printer* printer);
private:
// Returns true if tailcall table code should be generated.
bool should_generate_tctable() const;
// Returns true if tailcall table code should be generated, but inside an
// #ifdef guard.
bool should_generate_guarded_tctable() const {
return should_generate_tctable() &&
options_.tctable_mode == Options::kTCTableGuarded;
}
// Generates a tail-calling `_InternalParse` function.
void GenerateTailcallParseFunction(Formatter& format);
// Generates a fallback function for tailcall table-based parsing.
void GenerateTailcallFallbackFunction(Formatter& format);
// Generates functions for parsing this message as a field.
void GenerateTailcallFieldParseFunctions(Formatter& format);
// Generates a looping `_InternalParse` function.
void GenerateLoopingParseFunction(Formatter& format);
// Generates the tail-call table definition.
void GenerateTailCallTable(Formatter& format);
void GenerateFastFieldEntries(Formatter& format, const std::string& fallback);
// Generates parsing code for an `ArenaString` field.
void GenerateArenaString(Formatter& format, const FieldDescriptor* field);
// Generates parsing code for a string-typed field.
void GenerateStrings(Formatter& format, const FieldDescriptor* field,
bool check_utf8);
// Generates parsing code for a length-delimited field (strings, messages,
// etc.).
void GenerateLengthDelim(Formatter& format, const FieldDescriptor* field);
// Generates the parsing code for a known field.
void GenerateFieldBody(Formatter& format,
google::protobuf::internal::WireFormatLite::WireType wiretype,
const FieldDescriptor* field);
// Generates code to parse the next field from the input stream.
void GenerateParseIterationBody(
Formatter& format, const Descriptor* descriptor,
const std::vector<const FieldDescriptor*>& ordered_fields);
// Generates a `switch` statement to parse each of `ordered_fields`.
void GenerateFieldSwitch(
Formatter& format,
const std::vector<const FieldDescriptor*>& ordered_fields);
const Descriptor* descriptor_;
MessageSCCAnalyzer* scc_analyzer_;
const Options& options_;
std::map<std::string, std::string> variables_;
std::unique_ptr<TailCallTableInfo> tc_table_info_;
std::vector<int> inlined_string_indices_;
int num_hasbits_;
};
enum class ParseCardinality {
kSingular,
kOneof,
kRepeated,
kPacked,
};
// TypeFormat defines parsing types, which encapsulates the expected wire
// format, conversion or validation, and the in-memory layout.
enum class TypeFormat {
// Fixed types:
kFixed64, // fixed64, sfixed64, double
kFixed32, // fixed32, sfixed32, float
// Varint types:
kVar64, // int64, uint64
kVar32, // int32, uint32
kSInt64, // sint64
kSInt32, // sint32
kBool, // bool
// Length-delimited types:
kBytes, // bytes
kString, // string (proto3/UTF-8 strict)
kStringValidateOnly, // string (proto2/UTF-8 validate only)
};
// Returns the name of a field parser function.
//
// These are out-of-line functions generated by
// parse_function_inc_generator_main.
std::string GetTailCallFieldHandlerName(ParseCardinality card,
TypeFormat type_format,
int tag_length_bytes,
const Options& options);
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__

View File

@ -0,0 +1,236 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
//
// TODO(kenton): Share code with the versions of this test in other languages?
// It seemed like parameterizing it would add more complexity than it is
// worth.
#include <memory>
#include <thirdparty/protobuf/testing/file.h>
#include <thirdparty/protobuf/testing/file.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_generator.h>
#include <thirdparty/protobuf/compiler/command_line_interface.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
class TestGenerator : public CodeGenerator {
public:
TestGenerator() {}
~TestGenerator() {}
virtual bool Generate(const FileDescriptor* file,
const std::string& parameter, GeneratorContext* context,
std::string* error) const {
TryInsert("test.pb.h", "includes", context);
TryInsert("test.pb.h", "namespace_scope", context);
TryInsert("test.pb.h", "global_scope", context);
TryInsert("test.pb.h", "class_scope:foo.Bar", context);
TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", context);
TryInsert("test.pb.cc", "includes", context);
TryInsert("test.pb.cc", "namespace_scope", context);
TryInsert("test.pb.cc", "global_scope", context);
// Check field accessors for an optional int32:
TryInsert("test.pb.h", "field_get:foo.Bar.optInt", context);
TryInsert("test.pb.h", "field_set:foo.Bar.optInt", context);
// Check field accessors for a repeated int32:
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedInt", context);
TryInsert("test.pb.h", "field_set:foo.Bar.repeatedInt", context);
// Check field accessors for a required string:
TryInsert("test.pb.h", "field_get:foo.Bar.requiredString", context);
TryInsert("test.pb.h", "field_set:foo.Bar.requiredString", context);
TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredString", context);
TryInsert("test.pb.h", "field_set_allocated:foo.Bar.requiredString",
context);
// Check field accessors for a repeated string:
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedString", context);
TryInsert("test.pb.h", "field_set:foo.Bar.repeatedString", context);
TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context);
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context);
TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedString", context);
TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context);
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context);
// Check field accessors for an int inside oneof{}:
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfInt", context);
TryInsert("test.pb.h", "field_set:foo.Bar.oneOfInt", context);
// Check field accessors for a string inside oneof{}:
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfString", context);
TryInsert("test.pb.h", "field_set:foo.Bar.oneOfString", context);
TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfString", context);
TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfString", context);
// Check field accessors for an optional message:
TryInsert("test.pb.h", "field_get:foo.Bar.optMessage", context);
TryInsert("test.pb.h", "field_mutable:foo.Bar.optMessage", context);
TryInsert("test.pb.h", "field_set_allocated:foo.Bar.optMessage", context);
// Check field accessors for a repeated message:
TryInsert("test.pb.h", "field_add:foo.Bar.repeatedMessage", context);
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedMessage", context);
TryInsert("test.pb.h", "field_list:foo.Bar.repeatedMessage", context);
TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedMessage", context);
TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedMessage",
context);
// Check field accessors for a message inside oneof{}:
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfMessage", context);
TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfMessage", context);
TryInsert("test.pb.cc", "field_set_allocated:foo.Bar.oneOfMessage",
context);
// Check field accessors for an optional enum:
TryInsert("test.pb.h", "field_get:foo.Bar.optEnum", context);
TryInsert("test.pb.h", "field_set:foo.Bar.optEnum", context);
// Check field accessors for a repeated enum:
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedEnum", context);
TryInsert("test.pb.h", "field_set:foo.Bar.repeatedEnum", context);
TryInsert("test.pb.h", "field_add:foo.Bar.repeatedEnum", context);
TryInsert("test.pb.h", "field_list:foo.Bar.repeatedEnum", context);
TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedEnum", context);
// Check field accessors for an enum inside oneof{}:
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfEnum", context);
TryInsert("test.pb.h", "field_set:foo.Bar.oneOfEnum", context);
// Check field accessors for a required cord:
TryInsert("test.pb.h", "field_get:foo.Bar.requiredCord", context);
TryInsert("test.pb.h", "field_set:foo.Bar.requiredCord", context);
TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredCord", context);
// Check field accessors for a repeated cord:
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedCord", context);
TryInsert("test.pb.h", "field_set:foo.Bar.repeatedCord", context);
TryInsert("test.pb.h", "field_add:foo.Bar.repeatedCord", context);
TryInsert("test.pb.h", "field_list:foo.Bar.repeatedCord", context);
TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedCord", context);
TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedCord", context);
// Check field accessors for a cord inside oneof{}:
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfCord", context);
TryInsert("test.pb.h", "field_set:foo.Bar.oneOfCord", context);
TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfCord", context);
return true;
}
void TryInsert(const std::string& filename,
const std::string& insertion_point,
GeneratorContext* context) const {
std::unique_ptr<io::ZeroCopyOutputStream> output(
context->OpenForInsert(filename, insertion_point));
io::Printer printer(output.get(), '$');
printer.Print("// inserted $name$\n", "name", insertion_point);
}
};
// This test verifies that all the expected insertion points exist. It does
// not verify that they are correctly-placed; that would require actually
// compiling the output which is a bit more than I care to do for this test.
TEST(CppPluginTest, PluginTest) {
GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto",
"syntax = \"proto2\";\n"
"package foo;\n"
"\n"
"enum Thud { VALUE = 0; }\n"
"\n"
"message Bar {\n"
" message Baz {}\n"
" optional int32 optInt = 1;\n"
" repeated int32 repeatedInt = 2;\n"
"\n"
" required string requiredString = 3;\n"
" repeated string repeatedString = 4;\n"
"\n"
" optional Baz optMessage = 6;\n"
" repeated Baz repeatedMessage = 7;\n"
"\n"
" optional Thud optEnum = 8;\n"
" repeated Thud repeatedEnum = 9;\n"
"\n"
" required string requiredCord = 10 [\n"
" ctype = CORD\n"
" ];\n"
" repeated string repeatedCord = 11 [\n"
" ctype = CORD\n"
" ];\n"
"\n"
" oneof Qux {\n"
" int64 oneOfInt = 20;\n"
" string oneOfString = 21;\n"
" Baz oneOfMessage = 22;\n"
" Thud oneOfEnum = 23;"
" string oneOfCord = 24 [\n"
" ctype = CORD\n"
" ];\n"
" }\n"
"}\n",
true));
CommandLineInterface cli;
cli.SetInputsAreProtoPathRelative(true);
CppGenerator cpp_generator;
TestGenerator test_generator;
cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
cli.RegisterGenerator("--test_out", &test_generator, "");
std::string proto_path = "-I" + TestTempDir();
std::string cpp_out = "--cpp_out=" + TestTempDir();
std::string test_out = "--test_out=" + TestTempDir();
const char* argv[] = {"protoc", proto_path.c_str(), cpp_out.c_str(),
test_out.c_str(), "test.proto"};
EXPECT_EQ(0, cli.Run(5, argv));
}
} // namespace
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,505 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <thirdparty/protobuf/compiler/cpp/cpp_primitive_field.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/wire_format.h>
#include <thirdparty/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,
std::map<std::string, std::string>* variables,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = PrimitiveTypeName(options, descriptor->cpp_type());
(*variables)["default"] = DefaultValue(options, descriptor);
(*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
int fixed_size = FixedSize(descriptor->type());
if (fixed_size != -1) {
(*variables)["fixed_size"] = StrCat(fixed_size);
}
(*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name(
static_cast<FieldDescriptorProto_Type>(descriptor->type()));
(*variables)["full_name"] = descriptor->full_name();
}
} // namespace
// ===================================================================
PrimitiveFieldGenerator::PrimitiveFieldGenerator(
const FieldDescriptor* descriptor, const Options& options)
: FieldGenerator(descriptor, options) {
SetPrimitiveVariables(descriptor, &variables_, options);
}
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
void PrimitiveFieldGenerator::GeneratePrivateMembers(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$type$ $name$_;\n");
}
void PrimitiveFieldGenerator::GenerateAccessorDeclarations(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
"$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
"private:\n"
"$type$ ${1$_internal_$name$$}$() const;\n"
"void ${1$_internal_set_$name$$}$($type$ value);\n"
"public:\n",
descriptor_);
}
void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline $type$ $classname$::_internal_$name$() const {\n"
" return $name$_;\n"
"}\n"
"inline $type$ $classname$::$name$() const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$();\n"
"}\n"
"inline void $classname$::_internal_set_$name$($type$ value) {\n"
" $set_hasbit$\n"
" $name$_ = value;\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
" _internal_set_$name$(value);\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
}
void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_ = $default$;\n");
}
void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
format("_internal_set_$name$(from._internal_$name$());\n");
}
void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
format("swap($name$_, other->$name$_);\n");
}
void PrimitiveFieldGenerator::GenerateConstructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_ = $default$;\n");
}
void PrimitiveFieldGenerator::GenerateCopyConstructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_ = from.$name$_;\n");
}
void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"target = stream->EnsureSpace(target);\n"
"target = "
"::$proto_ns$::internal::WireFormatLite::Write$declared_type$ToArray("
"$number$, this->_internal_$name$(), target);\n");
}
void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
Formatter format(printer, variables_);
int fixed_size = FixedSize(descriptor_->type());
if (fixed_size == -1) {
if (internal::WireFormat::TagSize(descriptor_->number(),
descriptor_->type()) == 1) {
// Adding one is very common and it turns out it can be done for
// free inside of WireFormatLite, so we can save an instruction here.
format(
"total_size += ::$proto_ns$::internal::WireFormatLite::"
"$declared_type$SizePlusOne(this->_internal_$name$());\n");
} else {
format(
"total_size += $tag_size$ +\n"
" ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
" this->_internal_$name$());\n");
}
} else {
format("total_size += $tag_size$ + $fixed_size$;\n");
}
}
void PrimitiveFieldGenerator::GenerateConstinitInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_($default$)");
}
// ===================================================================
PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
const FieldDescriptor* descriptor, const Options& options)
: PrimitiveFieldGenerator(descriptor, options) {
SetCommonOneofFieldVariables(descriptor, &variables_);
}
PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline $type$ $classname$::_internal_$name$() const {\n"
" if (_internal_has_$name$()) {\n"
" return $field_member$;\n"
" }\n"
" return $default$;\n"
"}\n"
"inline void $classname$::_internal_set_$name$($type$ value) {\n"
" if (!_internal_has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" }\n"
" $field_member$ = value;\n"
"}\n"
"inline $type$ $classname$::$name$() const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$();\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
" _internal_set_$name$(value);\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
}
void PrimitiveOneofFieldGenerator::GenerateClearingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$field_member$ = $default$;\n");
}
void PrimitiveOneofFieldGenerator::GenerateSwappingCode(
io::Printer* printer) const {
// Don't print any swapping code. Swapping the union will swap this field.
}
void PrimitiveOneofFieldGenerator::GenerateConstructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
}
// ===================================================================
RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
const FieldDescriptor* descriptor, const Options& options)
: FieldGenerator(descriptor, options) {
SetPrimitiveVariables(descriptor, &variables_, options);
if (descriptor->is_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 {
Formatter format(printer, variables_);
format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n");
if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
HasGeneratedMethods(descriptor_->file(), options_)) {
format("mutable std::atomic<int> _$name$_cached_byte_size_;\n");
}
}
void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"private:\n"
"$type$ ${1$_internal_$name$$}$(int index) const;\n"
"const ::$proto_ns$::RepeatedField< $type$ >&\n"
" ${1$_internal_$name$$}$() const;\n"
"void ${1$_internal_add_$name$$}$($type$ value);\n"
"::$proto_ns$::RepeatedField< $type$ >*\n"
" ${1$_internal_mutable_$name$$}$();\n"
"public:\n"
"$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
"$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
"$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
"$deprecated_attr$const ::$proto_ns$::RepeatedField< $type$ >&\n"
" ${1$$name$$}$() const;\n"
"$deprecated_attr$::$proto_ns$::RepeatedField< $type$ >*\n"
" ${1$mutable_$name$$}$();\n",
descriptor_);
}
void RepeatedPrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline $type$ $classname$::_internal_$name$(int index) const {\n"
" return $name$_.Get(index);\n"
"}\n"
"inline $type$ $classname$::$name$(int index) const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$(index);\n"
"}\n"
"inline void $classname$::set_$name$(int index, $type$ value) {\n"
"$annotate_set$"
" $name$_.Set(index, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::_internal_add_$name$($type$ value) {\n"
" $name$_.Add(value);\n"
"}\n"
"inline void $classname$::add_$name$($type$ value) {\n"
" _internal_add_$name$(value);\n"
"$annotate_add$"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n"
"inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
"$classname$::_internal_$name$() const {\n"
" return $name$_;\n"
"}\n"
"inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
"$classname$::$name$() const {\n"
"$annotate_list$"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return _internal_$name$();\n"
"}\n"
"inline ::$proto_ns$::RepeatedField< $type$ >*\n"
"$classname$::_internal_mutable_$name$() {\n"
" return &$name$_;\n"
"}\n"
"inline ::$proto_ns$::RepeatedField< $type$ >*\n"
"$classname$::mutable_$name$() {\n"
"$annotate_mutable_list$"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return _internal_mutable_$name$();\n"
"}\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateClearingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.Clear();\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.MergeFrom(from.$name$_);\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.InternalSwap(&other->$name$_);\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateConstructorCode(
io::Printer* printer) const {
// Not needed for repeated fields.
}
void RepeatedPrimitiveFieldGenerator::GenerateCopyConstructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.CopyFrom(from.$name$_);\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (descriptor_->is_packed()) {
if (FixedSize(descriptor_->type()) == -1) {
format(
"{\n"
" int byte_size = "
"_$name$_cached_byte_size_.load(std::memory_order_relaxed);\n"
" if (byte_size > 0) {\n"
" target = stream->Write$declared_type$Packed(\n"
" $number$, _internal_$name$(), byte_size, target);\n"
" }\n"
"}\n");
} else {
format(
"if (this->_internal_$name$_size() > 0) {\n"
" target = stream->WriteFixedPacked($number$, _internal_$name$(), "
"target);\n"
"}\n");
}
} else {
format(
"for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
" target = stream->EnsureSpace(target);\n"
" target = ::$proto_ns$::internal::WireFormatLite::"
"Write$declared_type$ToArray($number$, this->_internal_$name$(i), "
"target);\n"
"}\n");
}
}
void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("{\n");
format.Indent();
int fixed_size = FixedSize(descriptor_->type());
if (fixed_size == -1) {
format(
"size_t data_size = ::$proto_ns$::internal::WireFormatLite::\n"
" $declared_type$Size(this->$name$_);\n");
} else {
format(
"unsigned int count = static_cast<unsigned "
"int>(this->_internal_$name$_size());\n"
"size_t data_size = $fixed_size$UL * count;\n");
}
if (descriptor_->is_packed()) {
format(
"if (data_size > 0) {\n"
" total_size += $tag_size$ +\n"
" ::$proto_ns$::internal::WireFormatLite::Int32Size(\n"
" static_cast<$int32$>(data_size));\n"
"}\n");
if (FixedSize(descriptor_->type()) == -1) {
format(
"int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
"_$name$_cached_byte_size_.store(cached_size,\n"
" std::memory_order_relaxed);\n");
}
format("total_size += data_size;\n");
} else {
format(
"total_size += $tag_size$ *\n"
" "
"::$proto_ns$::internal::FromIntSize(this->_internal_$name$_size());\n"
"total_size += data_size;\n");
}
format.Outdent();
format("}\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateConstinitInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_()");
if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
HasGeneratedMethods(descriptor_->file(), options_)) {
format("\n, _$name$_cached_byte_size_(0)");
}
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,116 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
#include <map>
#include <string>
#include <thirdparty/protobuf/compiler/cpp/cpp_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class PrimitiveFieldGenerator : public FieldGenerator {
public:
PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~PrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const override;
void GenerateAccessorDeclarations(io::Printer* printer) const override;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
void GenerateCopyConstructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
void GenerateConstinitInitializer(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
};
class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
public:
PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~PrimitiveOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
};
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
public:
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~RepeatedPrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const override;
void GenerateAccessorDeclarations(io::Printer* printer) const override;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
void GenerateCopyConstructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
void GenerateConstinitInitializer(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__

View File

@ -0,0 +1,327 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <thirdparty/protobuf/compiler/cpp/cpp_service.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
void InitMethodVariables(const MethodDescriptor* method, const Options& options,
Formatter* format) {
format->Set("name", method->name());
format->Set("input_type", QualifiedClassName(method->input_type(), options));
format->Set("output_type",
QualifiedClassName(method->output_type(), options));
}
} // namespace
ServiceGenerator::ServiceGenerator(
const ServiceDescriptor* descriptor,
const std::map<std::string, std::string>& vars, const Options& options)
: descriptor_(descriptor), vars_(vars), options_(options) {
vars_["classname"] = descriptor_->name();
vars_["full_name"] = descriptor_->full_name();
}
ServiceGenerator::~ServiceGenerator() {}
void ServiceGenerator::GenerateDeclarations(io::Printer* printer) {
Formatter format(printer, vars_);
// Forward-declare the stub type.
format(
"class $classname$_Stub;\n"
"\n");
GenerateInterface(printer);
GenerateStubDefinition(printer);
}
void ServiceGenerator::GenerateInterface(io::Printer* printer) {
Formatter format(printer, vars_);
format(
"class $dllexport_decl $$classname$ : public ::$proto_ns$::Service {\n"
" protected:\n"
" // This class should be treated as an abstract interface.\n"
" inline $classname$() {};\n"
" public:\n"
" virtual ~$classname$();\n");
printer->Indent();
format(
"\n"
"typedef $classname$_Stub Stub;\n"
"\n"
"static const ::$proto_ns$::ServiceDescriptor* descriptor();\n"
"\n");
GenerateMethodSignatures(VIRTUAL, printer);
format(
"\n"
"// implements Service ----------------------------------------------\n"
"\n"
"const ::$proto_ns$::ServiceDescriptor* GetDescriptor();\n"
"void CallMethod(const ::$proto_ns$::MethodDescriptor* method,\n"
" ::$proto_ns$::RpcController* controller,\n"
" const ::$proto_ns$::Message* request,\n"
" ::$proto_ns$::Message* response,\n"
" ::google::protobuf::Closure* done);\n"
"const ::$proto_ns$::Message& GetRequestPrototype(\n"
" const ::$proto_ns$::MethodDescriptor* method) const;\n"
"const ::$proto_ns$::Message& GetResponsePrototype(\n"
" const ::$proto_ns$::MethodDescriptor* method) const;\n");
printer->Outdent();
format(
"\n"
" private:\n"
" GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n"
"};\n"
"\n");
}
void ServiceGenerator::GenerateStubDefinition(io::Printer* printer) {
Formatter format(printer, vars_);
format(
"class $dllexport_decl $$classname$_Stub : public $classname$ {\n"
" public:\n");
printer->Indent();
format(
"$classname$_Stub(::$proto_ns$::RpcChannel* channel);\n"
"$classname$_Stub(::$proto_ns$::RpcChannel* channel,\n"
" ::$proto_ns$::Service::ChannelOwnership ownership);\n"
"~$classname$_Stub();\n"
"\n"
"inline ::$proto_ns$::RpcChannel* channel() { return channel_; }\n"
"\n"
"// implements $classname$ ------------------------------------------\n"
"\n");
GenerateMethodSignatures(NON_VIRTUAL, printer);
printer->Outdent();
format(
" private:\n"
" ::$proto_ns$::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);
Formatter format(printer, vars_);
InitMethodVariables(method, options_, &format);
format.Set("virtual", virtual_or_non == VIRTUAL ? "virtual " : "");
format(
"$virtual$void $name$(::$proto_ns$::RpcController* controller,\n"
" const $input_type$* request,\n"
" $output_type$* response,\n"
" ::google::protobuf::Closure* done);\n");
}
}
// ===================================================================
void ServiceGenerator::GenerateImplementation(io::Printer* printer) {
Formatter format(printer, vars_);
format(
"$classname$::~$classname$() {}\n"
"\n"
"const ::$proto_ns$::ServiceDescriptor* $classname$::descriptor() {\n"
" "
"::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n"
" return $file_level_service_descriptors$[$1$];\n"
"}\n"
"\n"
"const ::$proto_ns$::ServiceDescriptor* $classname$::GetDescriptor() {\n"
" return descriptor();\n"
"}\n"
"\n",
index_in_metadata_);
// Generate methods of the interface.
GenerateNotImplementedMethods(printer);
GenerateCallMethod(printer);
GenerateGetPrototype(REQUEST, printer);
GenerateGetPrototype(RESPONSE, printer);
// Generate stub implementation.
format(
"$classname$_Stub::$classname$_Stub(::$proto_ns$::RpcChannel* channel)\n"
" : channel_(channel), owns_channel_(false) {}\n"
"$classname$_Stub::$classname$_Stub(\n"
" ::$proto_ns$::RpcChannel* channel,\n"
" ::$proto_ns$::Service::ChannelOwnership ownership)\n"
" : channel_(channel),\n"
" owns_channel_(ownership == "
"::$proto_ns$::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);
Formatter format(printer, vars_);
InitMethodVariables(method, options_, &format);
format(
"void $classname$::$name$(::$proto_ns$::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) {
Formatter format(printer, vars_);
format(
"void $classname$::CallMethod(const ::$proto_ns$::MethodDescriptor* "
"method,\n"
" ::$proto_ns$::RpcController* controller,\n"
" const ::$proto_ns$::Message* request,\n"
" ::$proto_ns$::Message* response,\n"
" ::google::protobuf::Closure* done) {\n"
" GOOGLE_DCHECK_EQ(method->service(), $file_level_service_descriptors$[$1$]);\n"
" switch(method->index()) {\n",
index_in_metadata_);
for (int i = 0; i < descriptor_->method_count(); i++) {
const MethodDescriptor* method = descriptor_->method(i);
Formatter format_method(printer, vars_);
InitMethodVariables(method, options_, &format_method);
// Note: down_cast does not work here because it only works on pointers,
// not references.
format_method(
" case $1$:\n"
" $name$(controller,\n"
" ::$proto_ns$::internal::DownCast<const $input_type$*>(\n"
" request),\n"
" ::$proto_ns$::internal::DownCast<$output_type$*>(\n"
" response),\n"
" done);\n"
" break;\n",
i);
}
format(
" 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) {
Formatter format(printer, vars_);
if (which == REQUEST) {
format("const ::$proto_ns$::Message& $classname$::GetRequestPrototype(\n");
} else {
format("const ::$proto_ns$::Message& $classname$::GetResponsePrototype(\n");
}
format(
" const ::$proto_ns$::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();
format(
" case $1$:\n"
" return $2$::default_instance();\n",
i, QualifiedClassName(type, options_));
}
format(
" default:\n"
" GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
" return *::$proto_ns$::MessageFactory::generated_factory()\n"
" ->GetPrototype(method->$1$_type());\n"
" }\n"
"}\n"
"\n",
which == REQUEST ? "input" : "output");
}
void ServiceGenerator::GenerateStubMethods(io::Printer* printer) {
for (int i = 0; i < descriptor_->method_count(); i++) {
const MethodDescriptor* method = descriptor_->method(i);
Formatter format(printer, vars_);
InitMethodVariables(method, options_, &format);
format(
"void $classname$_Stub::$name$(::$proto_ns$::RpcController* "
"controller,\n"
" const $input_type$* request,\n"
" $output_type$* response,\n"
" ::google::protobuf::Closure* done) {\n"
" channel_->CallMethod(descriptor()->method($1$),\n"
" controller, request, response, done);\n"
"}\n",
i);
}
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,122 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
#include <map>
#include <string>
#include <thirdparty/protobuf/compiler/cpp/cpp_options.h>
#include <thirdparty/protobuf/descriptor.h>
namespace google {
namespace protobuf {
namespace io {
class Printer; // printer.h
}
} // namespace protobuf
} // namespace google
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class ServiceGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
explicit ServiceGenerator(const ServiceDescriptor* descriptor,
const std::map<std::string, std::string>& vars,
const Options& options);
~ServiceGenerator();
// Header stuff.
// Generate the class definitions for the service's interface and the
// stub implementation.
void GenerateDeclarations(io::Printer* printer);
// Source file stuff.
// Generate implementations of everything declared by
// GenerateDeclarations().
void GenerateImplementation(io::Printer* printer);
private:
enum RequestOrResponse { REQUEST, RESPONSE };
enum VirtualOrNon { VIRTUAL, NON_VIRTUAL };
// Header stuff.
// Generate the service abstract interface.
void GenerateInterface(io::Printer* printer);
// Generate the stub class definition.
void GenerateStubDefinition(io::Printer* printer);
// Prints signatures for all methods in the
void GenerateMethodSignatures(VirtualOrNon virtual_or_non,
io::Printer* printer);
// Source file stuff.
// Generate the default implementations of the service methods, which
// produce a "not implemented" error.
void GenerateNotImplementedMethods(io::Printer* printer);
// Generate the CallMethod() method of the service.
void GenerateCallMethod(io::Printer* printer);
// Generate the Get{Request,Response}Prototype() methods.
void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer);
// Generate the stub's implementations of the service methods.
void GenerateStubMethods(io::Printer* printer);
const ServiceDescriptor* descriptor_;
std::map<std::string, std::string> vars_;
const Options& options_;
int index_in_metadata_;
friend class FileGenerator;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__

View File

@ -0,0 +1,915 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <thirdparty/protobuf/compiler/cpp/cpp_string_field.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
void SetStringVariables(const FieldDescriptor* descriptor,
std::map<std::string, std::string>* variables,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
(*variables)["default"] = DefaultValue(options, descriptor);
(*variables)["default_length"] =
StrCat(descriptor->default_value_string().length());
std::string default_variable_string = MakeDefaultName(descriptor);
(*variables)["default_variable_name"] = default_variable_string;
if (!descriptor->default_value_string().empty()) {
(*variables)["lazy_variable"] =
QualifiedClassName(descriptor->containing_type(), options) +
"::" + default_variable_string;
}
(*variables)["default_string"] =
descriptor->default_value_string().empty()
? "::" + (*variables)["proto_ns"] +
"::internal::GetEmptyStringAlreadyInited()"
: (*variables)["lazy_variable"] + ".get()";
(*variables)["init_value"] =
descriptor->default_value_string().empty()
? "&::" + (*variables)["proto_ns"] +
"::internal::GetEmptyStringAlreadyInited()"
: "nullptr";
(*variables)["default_value_tag"] =
"::" + (*variables)["proto_ns"] + "::internal::ArenaStringPtr::" +
(descriptor->default_value_string().empty() ? "Empty" : "NonEmpty") +
"Default{}";
(*variables)["default_variable_or_tag"] =
(*variables)[descriptor->default_value_string().empty()
? "default_value_tag"
: "lazy_variable"];
(*variables)["pointer_type"] =
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
(*variables)["setter"] =
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "SetBytes" : "Set";
(*variables)["null_check"] = (*variables)["DCHK"] + "(value != nullptr);\n";
// NOTE: Escaped here to unblock proto1->proto2 migration.
// TODO(liujisi): Extend this to apply for other conflicting methods.
(*variables)["release_name"] =
SafeFunctionName(descriptor->containing_type(), descriptor, "release_");
(*variables)["full_name"] = descriptor->full_name();
if (options.opensource_runtime) {
(*variables)["string_piece"] = "::std::string";
} else {
(*variables)["string_piece"] = "::StringPiece";
}
}
} // namespace
// ===================================================================
StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: FieldGenerator(descriptor, options),
inlined_(IsStringInlined(descriptor, options)) {
SetStringVariables(descriptor, &variables_, options);
}
StringFieldGenerator::~StringFieldGenerator() {}
void StringFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
Formatter format(printer, variables_);
if (!inlined_) {
format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n");
} else {
// `_init_inline_xxx` is used for initializing default instances.
format(
"::$proto_ns$::internal::InlinedStringField $name$_;\n"
"static std::true_type _init_inline_$name$_;\n");
}
}
void StringFieldGenerator::GenerateStaticMembers(io::Printer* printer) const {
Formatter format(printer, variables_);
if (!descriptor_->default_value_string().empty()) {
format(
"static const ::$proto_ns$::internal::LazyString"
" $default_variable_name$;\n");
}
}
void StringFieldGenerator::GenerateAccessorDeclarations(
io::Printer* printer) const {
Formatter format(printer, variables_);
// 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.
bool unknown_ctype = descriptor_->options().ctype() !=
EffectiveStringCType(descriptor_, options_);
if (unknown_ctype) {
format.Outdent();
format(
" private:\n"
" // Hidden due to unknown ctype option.\n");
format.Indent();
}
format(
"$deprecated_attr$const std::string& ${1$$name$$}$() const;\n"
"template <typename ArgT0 = const std::string&, typename... ArgT>\n"
"$deprecated_attr$void ${1$set_$name$$}$(ArgT0&& arg0, ArgT... args);\n",
descriptor_);
format(
"$deprecated_attr$std::string* ${1$mutable_$name$$}$();\n"
"PROTOBUF_NODISCARD $deprecated_attr$std::string* "
"${1$$release_name$$}$();\n"
"$deprecated_attr$void ${1$set_allocated_$name$$}$(std::string* "
"$name$);\n",
descriptor_);
format(
"private:\n"
"const std::string& _internal_$name$() const;\n"
"inline PROTOBUF_ALWAYS_INLINE void "
"_internal_set_$name$(const std::string& value);\n"
"std::string* _internal_mutable_$name$();\n");
if (inlined_) {
format(
"inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() "
"const;\n");
}
format("public:\n");
if (unknown_ctype) {
format.Outdent();
format(" public:\n");
format.Indent();
}
}
void StringFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline const std::string& $classname$::$name$() const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n");
if (!descriptor_->default_value_string().empty()) {
format(
" if ($name$_.IsDefault(nullptr)) return "
"$default_variable_name$.get();\n");
}
format(
" return _internal_$name$();\n"
"}\n");
if (!inlined_) {
format(
"template <typename ArgT0, typename... ArgT>\n"
"inline PROTOBUF_ALWAYS_INLINE\n"
"void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
" $set_hasbit$\n"
" $name$_.$setter$($default_value_tag$, static_cast<ArgT0 &&>(arg0),"
" args..., GetArenaForAllocation());\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
} else {
format(
"template <typename ArgT0, typename... ArgT>\n"
"inline PROTOBUF_ALWAYS_INLINE\n"
"void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
" $set_hasbit$\n"
" $name$_.$setter$(nullptr, static_cast<ArgT0 &&>(arg0),"
" args..., GetArenaForAllocation(), _internal_$name$_donated(), "
"&$donating_states_word$, $mask_for_undonate$);\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline bool $classname$::_internal_$name$_donated() const {\n"
" bool value = $inlined_string_donated$\n"
" return value;\n"
"}\n");
}
format(
"inline std::string* $classname$::mutable_$name$() {\n"
" std::string* _s = _internal_mutable_$name$();\n"
"$annotate_mutable$"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return _s;\n"
"}\n"
"inline const std::string& $classname$::_internal_$name$() const {\n"
" return $name$_.Get();\n"
"}\n"
"inline void $classname$::_internal_set_$name$(const std::string& "
"value) {\n"
" $set_hasbit$\n");
if (!inlined_) {
format(
" $name$_.Set($default_value_tag$, value, GetArenaForAllocation());\n"
"}\n");
} else {
format(
" $name$_.Set(nullptr, value, GetArenaForAllocation(),\n"
" _internal_$name$_donated(), &$donating_states_word$, "
"$mask_for_undonate$);\n"
"}\n");
}
format(
"inline std::string* $classname$::_internal_mutable_$name$() {\n"
" $set_hasbit$\n");
if (!inlined_) {
format(
" return $name$_.Mutable($default_variable_or_tag$, "
"GetArenaForAllocation());\n"
"}\n");
} else {
format(
" return $name$_.Mutable($default_variable_or_tag$, "
"GetArenaForAllocation(), _internal_$name$_donated(), "
"&$donating_states_word$, $mask_for_undonate$);\n"
"}\n");
}
format(
"inline std::string* $classname$::$release_name$() {\n"
"$annotate_release$"
" // @@protoc_insertion_point(field_release:$full_name$)\n");
if (HasHasbit(descriptor_)) {
format(
" if (!_internal_has_$name$()) {\n"
" return nullptr;\n"
" }\n"
" $clear_hasbit$\n");
if (!inlined_) {
format(
" auto* p = $name$_.ReleaseNonDefault($init_value$, "
"GetArenaForAllocation());\n");
if (descriptor_->default_value_string().empty()) {
format(
"#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
" if ($name$_.IsDefault($init_value$)) {\n"
" $name$_.Set($init_value$, \"\", GetArenaForAllocation());\n"
" }\n"
"#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
}
format(" return p;\n");
} else {
format(
" return $name$_.Release(nullptr, GetArenaForAllocation(), "
"_internal_$name$_donated());\n");
}
} else {
format(
" return $name$_.Release($init_value$, GetArenaForAllocation());\n");
}
format(
"}\n"
"inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
" if ($name$ != nullptr) {\n"
" $set_hasbit$\n"
" } else {\n"
" $clear_hasbit$\n"
" }\n");
if (!inlined_) {
format(
" $name$_.SetAllocated($init_value$, $name$,\n"
" GetArenaForAllocation());\n");
if (descriptor_->default_value_string().empty()) {
format(
"#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
" if ($name$_.IsDefault($init_value$)) {\n"
" $name$_.Set($init_value$, \"\", GetArenaForAllocation());\n"
" }\n"
"#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
}
} else {
// Currently, string fields with default value can't be inlined.
format(
" $name$_.SetAllocated(nullptr, $name$, GetArenaForAllocation(), "
"_internal_$name$_donated(), &$donating_states_word$, "
"$mask_for_undonate$);\n");
}
format(
"$annotate_set$"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
}
void StringFieldGenerator::GenerateNonInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (!descriptor_->default_value_string().empty()) {
format(
"const ::$proto_ns$::internal::LazyString "
"$classname$::$default_variable_name$"
"{{{$default$, $default_length$}}, {nullptr}};\n");
}
}
void StringFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
if (descriptor_->default_value_string().empty()) {
format("$name$_.ClearToEmpty();\n");
} else {
GOOGLE_DCHECK(!inlined_);
format(
"$name$_.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n");
}
}
void StringFieldGenerator::GenerateMessageClearingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
// Two-dimension specialization here: supporting arenas, field presence, or
// not, and default value is the empty string or not. Complexity here ensures
// the minimal number of branches / amount of extraneous code at runtime
// (given that the below methods are inlined one-liners)!
// If we have a hasbit, then the Clear() method of the protocol buffer
// will have checked that this field is set. If so, we can avoid redundant
// checks against the default variable.
const bool must_be_present = HasHasbit(descriptor_);
if (inlined_ && must_be_present) {
// Calling mutable_$name$() gives us a string reference and sets the has bit
// for $name$ (in proto2). We may get here when the string field is inlined
// but the string's contents have not been changed by the user, so we cannot
// make an assertion about the contents of the string and could never make
// an assertion about the string instance.
//
// For non-inlined strings, we distinguish from non-default by comparing
// instances, rather than contents.
format("$DCHK$(!$name$_.IsDefault(nullptr));\n");
}
if (descriptor_->default_value_string().empty()) {
if (must_be_present) {
format("$name$_.ClearNonDefaultToEmpty();\n");
} else {
format("$name$_.ClearToEmpty();\n");
}
} else {
// Clear to a non-empty default is more involved, as we try to use the
// Arena if one is present and may need to reallocate the string.
format(
"$name$_.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n ");
}
}
void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
// TODO(gpike): improve this
format("_internal_set_$name$(from._internal_$name$());\n");
}
void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
if (!inlined_) {
format(
"::$proto_ns$::internal::ArenaStringPtr::InternalSwap(\n"
" $init_value$,\n"
" &$name$_, lhs_arena,\n"
" &other->$name$_, rhs_arena\n"
");\n");
} else {
// At this point, it's guaranteed that the two fields being swapped are on
// the same arena.
format(
"$name$_.Swap(&other->$name$_, nullptr, GetArenaForAllocation(), "
"_internal_$name$_donated(), other->_internal_$name$_donated(), "
"&$donating_states_word$, &(other->$donating_states_word$), "
"$mask_for_undonate$);\n");
}
}
void StringFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
Formatter format(printer, variables_);
if (inlined_ && descriptor_->default_value_string().empty()) {
// Automatic initialization will construct the string.
return;
}
GOOGLE_DCHECK(!inlined_);
format("$name$_.UnsafeSetDefault($init_value$);\n");
if (IsString(descriptor_, options_) &&
descriptor_->default_value_string().empty()) {
format(
"#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
" $name$_.Set($init_value$, \"\", GetArenaForAllocation());\n"
"#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
}
}
void StringFieldGenerator::GenerateCopyConstructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
GenerateConstructorCode(printer);
if (HasHasbit(descriptor_)) {
format("if (from._internal_has_$name$()) {\n");
} else {
format("if (!from._internal_$name$().empty()) {\n");
}
format.Indent();
if (!inlined_) {
format(
"$name$_.Set($default_value_tag$, from._internal_$name$(), \n"
" GetArenaForAllocation());\n");
} else {
format(
"$name$_.Set(nullptr, from._internal_$name$(),\n"
" GetArenaForAllocation(), _internal_$name$_donated(), "
"&$donating_states_word$, $mask_for_undonate$);\n");
}
format.Outdent();
format("}\n");
}
void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
Formatter format(printer, variables_);
if (inlined_) {
// The destructor is automatically invoked.
return;
}
format("$name$_.DestroyNoArena($init_value$);\n");
}
void StringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
descriptor_, options_, false,
"this->_internal_$name$().data(), "
"static_cast<int>(this->_internal_$name$().length()),\n",
format);
}
format(
"target = stream->Write$declared_type$MaybeAliased(\n"
" $number$, this->_internal_$name$(), target);\n");
}
void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"total_size += $tag_size$ +\n"
" ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
" this->_internal_$name$());\n");
}
void StringFieldGenerator::GenerateConstinitInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (inlined_) {
format("$name$_(nullptr, false)");
return;
}
if (descriptor_->default_value_string().empty()) {
format("$name$_(&::$proto_ns$::internal::fixed_address_empty_string)");
} else {
format("$name$_(nullptr)");
}
}
// ===================================================================
StringOneofFieldGenerator::StringOneofFieldGenerator(
const FieldDescriptor* descriptor, const Options& options)
: StringFieldGenerator(descriptor, options) {
SetCommonOneofFieldVariables(descriptor, &variables_);
variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true);
variables_["oneof_index"] =
StrCat(descriptor->containing_oneof()->index());
}
StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline const std::string& $classname$::$name$() const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$();\n"
"}\n"
"template <typename ArgT0, typename... ArgT>\n"
"inline void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
" if (!_internal_has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $field_member$.UnsafeSetDefault($init_value$);\n"
" }\n"
" $field_member$.$setter$($default_value_tag$,"
" static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline std::string* $classname$::mutable_$name$() {\n"
" std::string* _s = _internal_mutable_$name$();\n"
"$annotate_mutable$"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return _s;\n"
"}\n"
"inline const std::string& $classname$::_internal_$name$() const {\n"
" if (_internal_has_$name$()) {\n"
" return $field_member$.Get();\n"
" }\n"
" return $default_string$;\n"
"}\n"
"inline void $classname$::_internal_set_$name$(const std::string& "
"value) {\n"
" if (!_internal_has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $field_member$.UnsafeSetDefault($init_value$);\n"
" }\n"
" $field_member$.Set($default_value_tag$, value, "
"GetArenaForAllocation());\n"
"}\n");
format(
"inline std::string* $classname$::_internal_mutable_$name$() {\n"
" if (!_internal_has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $field_member$.UnsafeSetDefault($init_value$);\n"
" }\n"
" return $field_member$.Mutable(\n"
" $default_variable_or_tag$, GetArenaForAllocation());\n"
"}\n"
"inline std::string* $classname$::$release_name$() {\n"
"$annotate_release$"
" // @@protoc_insertion_point(field_release:$full_name$)\n"
" if (_internal_has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" return $field_member$.ReleaseNonDefault($init_value$, "
"GetArenaForAllocation());\n"
" } else {\n"
" return nullptr;\n"
" }\n"
"}\n"
"inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
" if (has_$oneof_name$()) {\n"
" clear_$oneof_name$();\n"
" }\n"
" if ($name$ != nullptr) {\n"
" set_has_$name$();\n"
" $field_member$.UnsafeSetDefault($name$);\n"
" ::$proto_ns$::Arena* arena = GetArenaForAllocation();\n"
" if (arena != nullptr) {\n"
" arena->Own($name$);\n"
" }\n"
" }\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
}
void StringOneofFieldGenerator::GenerateClearingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"$field_member$.Destroy($default_value_tag$, "
"GetArenaForAllocation());\n");
}
void StringOneofFieldGenerator::GenerateMessageClearingCode(
io::Printer* printer) const {
return GenerateClearingCode(printer);
}
void StringOneofFieldGenerator::GenerateSwappingCode(
io::Printer* printer) const {
// Don't print any swapping code. Swapping the union will swap this field.
}
void StringOneofFieldGenerator::GenerateConstructorCode(
io::Printer* printer) const {
// Nothing required here.
}
// ===================================================================
RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
const FieldDescriptor* descriptor, const Options& options)
: FieldGenerator(descriptor, options) {
SetStringVariables(descriptor, &variables_, options);
}
RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
void RepeatedStringFieldGenerator::GeneratePrivateMembers(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("::$proto_ns$::RepeatedPtrField<std::string> $name$_;\n");
}
void RepeatedStringFieldGenerator::GenerateAccessorDeclarations(
io::Printer* printer) const {
Formatter format(printer, variables_);
// See comment above about unknown ctypes.
bool unknown_ctype = descriptor_->options().ctype() !=
EffectiveStringCType(descriptor_, options_);
if (unknown_ctype) {
format.Outdent();
format(
" private:\n"
" // Hidden due to unknown ctype option.\n");
format.Indent();
}
format(
"$deprecated_attr$const std::string& ${1$$name$$}$(int index) const;\n"
"$deprecated_attr$std::string* ${1$mutable_$name$$}$(int index);\n"
"$deprecated_attr$void ${1$set_$name$$}$(int index, const "
"std::string& value);\n"
"$deprecated_attr$void ${1$set_$name$$}$(int index, std::string&& "
"value);\n"
"$deprecated_attr$void ${1$set_$name$$}$(int index, const "
"char* value);\n",
descriptor_);
if (!options_.opensource_runtime) {
format(
"$deprecated_attr$void ${1$set_$name$$}$(int index, "
"StringPiece value);\n",
descriptor_);
}
format(
"$deprecated_attr$void ${1$set_$name$$}$("
"int index, const $pointer_type$* value, size_t size);\n"
"$deprecated_attr$std::string* ${1$add_$name$$}$();\n"
"$deprecated_attr$void ${1$add_$name$$}$(const std::string& value);\n"
"$deprecated_attr$void ${1$add_$name$$}$(std::string&& value);\n"
"$deprecated_attr$void ${1$add_$name$$}$(const char* value);\n",
descriptor_);
if (!options_.opensource_runtime) {
format(
"$deprecated_attr$void ${1$add_$name$$}$(StringPiece value);\n",
descriptor_);
}
format(
"$deprecated_attr$void ${1$add_$name$$}$(const $pointer_type$* "
"value, size_t size)"
";\n"
"$deprecated_attr$const ::$proto_ns$::RepeatedPtrField<std::string>& "
"${1$$name$$}$() "
"const;\n"
"$deprecated_attr$::$proto_ns$::RepeatedPtrField<std::string>* "
"${1$mutable_$name$$}$()"
";\n"
"private:\n"
"const std::string& ${1$_internal_$name$$}$(int index) const;\n"
"std::string* _internal_add_$name$();\n"
"public:\n",
descriptor_);
if (unknown_ctype) {
format.Outdent();
format(" public:\n");
format.Indent();
}
}
void RepeatedStringFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline std::string* $classname$::add_$name$() {\n"
" std::string* _s = _internal_add_$name$();\n"
"$annotate_add_mutable$"
" // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
" return _s;\n"
"}\n");
if (options_.safe_boundary_check) {
format(
"inline const std::string& $classname$::_internal_$name$(int index) "
"const {\n"
" return $name$_.InternalCheckedGet(\n"
" index, ::$proto_ns$::internal::GetEmptyStringAlreadyInited());\n"
"}\n");
} else {
format(
"inline const std::string& $classname$::_internal_$name$(int index) "
"const {\n"
" return $name$_.Get(index);\n"
"}\n");
}
format(
"inline const std::string& $classname$::$name$(int index) const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$(index);\n"
"}\n"
"inline std::string* $classname$::mutable_$name$(int index) {\n"
"$annotate_mutable$"
" // @@protoc_insertion_point(field_mutable:$full_name$)\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"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::set_$name$(int index, std::string&& value) {\n"
" $name$_.Mutable(index)->assign(std::move(value));\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::set_$name$(int index, const char* value) {\n"
" $null_check$"
" $name$_.Mutable(index)->assign(value);\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n");
if (!options_.opensource_runtime) {
format(
"inline void "
"$classname$::set_$name$(int index, StringPiece value) {\n"
" $name$_.Mutable(index)->assign(value.data(), value.size());\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
"}\n");
}
format(
"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"
"$annotate_set$"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
"inline std::string* $classname$::_internal_add_$name$() {\n"
" return $name$_.Add();\n"
"}\n"
"inline void $classname$::add_$name$(const std::string& value) {\n"
" $name$_.Add()->assign(value);\n"
"$annotate_add$"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n"
"inline void $classname$::add_$name$(std::string&& value) {\n"
" $name$_.Add(std::move(value));\n"
"$annotate_add$"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n"
"inline void $classname$::add_$name$(const char* value) {\n"
" $null_check$"
" $name$_.Add()->assign(value);\n"
"$annotate_add$"
" // @@protoc_insertion_point(field_add_char:$full_name$)\n"
"}\n");
if (!options_.opensource_runtime) {
format(
"inline void $classname$::add_$name$(StringPiece value) {\n"
" $name$_.Add()->assign(value.data(), value.size());\n"
"$annotate_add$"
" // @@protoc_insertion_point(field_add_string_piece:$full_name$)\n"
"}\n");
}
format(
"inline void "
"$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
" $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
"$annotate_add$"
" // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
"}\n"
"inline const ::$proto_ns$::RepeatedPtrField<std::string>&\n"
"$classname$::$name$() const {\n"
"$annotate_list$"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
"inline ::$proto_ns$::RepeatedPtrField<std::string>*\n"
"$classname$::mutable_$name$() {\n"
"$annotate_mutable_list$"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
"}\n");
}
void RepeatedStringFieldGenerator::GenerateClearingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.Clear();\n");
}
void RepeatedStringFieldGenerator::GenerateMergingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.MergeFrom(from.$name$_);\n");
}
void RepeatedStringFieldGenerator::GenerateSwappingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.InternalSwap(&other->$name$_);\n");
}
void RepeatedStringFieldGenerator::GenerateConstructorCode(
io::Printer* printer) const {
// Not needed for repeated fields.
}
void RepeatedStringFieldGenerator::GenerateCopyConstructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.CopyFrom(from.$name$_);");
}
void RepeatedStringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
" const auto& s = this->_internal_$name$(i);\n");
// format("for (const std::string& s : this->$name$()) {\n");
format.Indent();
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(descriptor_, options_, false,
"s.data(), static_cast<int>(s.length()),\n",
format);
}
format.Outdent();
format(
" target = stream->Write$declared_type$($number$, s, target);\n"
"}\n");
}
void RepeatedStringFieldGenerator::GenerateByteSize(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"total_size += $tag_size$ *\n"
" ::$proto_ns$::internal::FromIntSize($name$_.size());\n"
"for (int i = 0, n = $name$_.size(); i < n; i++) {\n"
" total_size += "
"::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
" $name$_.Get(i));\n"
"}\n");
}
void RepeatedStringFieldGenerator::GenerateConstinitInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_()");
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,127 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
#include <map>
#include <string>
#include <thirdparty/protobuf/compiler/cpp/cpp_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class StringFieldGenerator : public FieldGenerator {
public:
StringFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~StringFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const override;
void GenerateStaticMembers(io::Printer* printer) const override;
void GenerateAccessorDeclarations(io::Printer* printer) const override;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateNonInlineAccessorDefinitions(
io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateMessageClearingCode(io::Printer* printer) const override;
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
void GenerateCopyConstructorCode(io::Printer* printer) const override;
void GenerateDestructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
void GenerateConstinitInitializer(io::Printer* printer) const override;
bool IsInlined() const override { return inlined_; }
private:
bool inlined_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
};
class StringOneofFieldGenerator : public StringFieldGenerator {
public:
StringOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~StringOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
// StringFieldGenerator, from which we inherit, overrides this so we need to
// override it as well.
void GenerateMessageClearingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
};
class RepeatedStringFieldGenerator : public FieldGenerator {
public:
RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
~RepeatedStringFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const override;
void GenerateAccessorDeclarations(io::Printer* printer) const override;
void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
void GenerateCopyConstructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
void GenerateConstinitInitializer(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__

View File

@ -0,0 +1,184 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// This file tests that various identifiers work as field and type names even
// though the same identifiers are used internally by the C++ code generator.
// LINT: LEGACY_NAMES
syntax = "proto2";
// Some generic_services option(s) added automatically.
// See: http://go/proto2-generic-services-default
option cc_generic_services = true; // auto-added
// We don't put this in a package within proto2 because we need to make sure
// that the generated code doesn't depend on being in the proto2 namespace.
package protobuf_unittest;
// Test that fields can have names like "input" and "i" which are also used
// internally by the code generator for local variables.
message TestConflictingSymbolNames {
message BuildDescriptors {}
message TypeTraits {}
optional int32 input = 1;
optional int32 output = 2;
optional string length = 3;
repeated int32 i = 4;
repeated string new_element = 5 [ctype = STRING_PIECE];
optional int32 total_size = 6;
optional int32 tag = 7;
enum TestEnum { FOO = 0; }
message Data1 {
repeated int32 data = 1;
}
message Data2 {
repeated TestEnum data = 1;
}
message Data3 {
repeated string data = 1;
}
message Data4 {
repeated Data4 data = 1;
}
message Data5 {
repeated string data = 1 [ctype = STRING_PIECE];
}
message Data6 {
repeated string data = 1 [ctype = CORD];
}
optional int32 source = 8;
optional int32 value = 9;
optional int32 file = 10;
optional int32 from = 11;
optional int32 handle_uninterpreted = 12;
repeated int32 index = 13;
optional int32 controller = 14;
optional int32 already_here = 15;
optional uint32 uint32 = 16;
optional uint64 uint64 = 17;
optional string string = 18;
optional int32 memset = 19;
optional int32 int32 = 20;
optional int64 int64 = 21;
optional uint32 cached_size = 22;
optional uint32 extensions = 23;
optional uint32 bit = 24;
optional uint32 bits = 25;
optional uint32 offsets = 26;
optional uint32 reflection = 27;
message Cord {}
optional string some_cord = 28 [ctype = CORD];
message StringPiece {}
optional string some_string_piece = 29 [ctype = STRING_PIECE];
// Some keywords.
optional uint32 int = 30;
optional uint32 friend = 31;
optional uint32 class = 37;
optional uint32 typedecl = 39;
optional uint32 auto = 40;
// The generator used to #define a macro called "DO" inside the .cc file.
message DO {}
optional DO do = 32;
// Some template parameter names for extensions.
optional int32 field_type = 33;
optional bool is_packed = 34;
// test conflicting release_$name$. "length" and "do" field in this message
// must remain string or message fields to make the test valid.
optional string release_length = 35;
// A more extreme case, the field name "do" here is a keyword, which will be
// escaped to "do_" already. Test there is no conflict even with escaped field
// names.
optional DO release_do = 36;
// For clashing local variables in Serialize and ByteSize calculation.
optional string target = 38;
extensions 1000 to max; // NO_PROTO3
}
message TestConflictingSymbolNamesExtension { // NO_PROTO3
extend TestConflictingSymbolNames { // NO_PROTO3
repeated int32 repeated_int32_ext = 20423638 [packed = true]; // NO_PROTO3
} // NO_PROTO3
} // NO_PROTO3
message TestConflictingEnumNames { // NO_PROTO3
enum while { // NO_PROTO3
default = 0; // NO_PROTO3
and = 1; // NO_PROTO3
class = 2; // NO_PROTO3
int = 3; // NO_PROTO3
typedef = 4; // NO_PROTO3
XOR = 5; // NO_PROTO3
} // NO_PROTO3
optional while conflicting_enum = 1; // NO_PROTO3
} // NO_PROTO3
enum bool { // NO_PROTO3
default = 0; // NO_PROTO3
NOT_EQ = 1; // NO_PROTO3
volatile = 2; // NO_PROTO3
return = 3; // NO_PROTO3
} // NO_PROTO3
message DummyMessage {}
message NULL {
optional int32 int = 1;
}
extend TestConflictingSymbolNames { // NO_PROTO3
optional int32 void = 314253; // NO_PROTO3
} // NO_PROTO3
// Message names that could conflict.
message Shutdown {}
message TableStruct {}
service TestConflictingMethodNames {
rpc Closure(DummyMessage) returns (DummyMessage);
}

View File

@ -0,0 +1,43 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Test that proto2 compiler can generate valid code when the enum value
// is INT_MAX. Note that this is a compile-only test and this proto is not
// referenced in any C++ code.
syntax = "proto2";
package protobuf_unittest;
message TestLargeEnumValue {
enum EnumWithLargeValue {
VALUE_1 = 1;
VALUE_MAX = 0x7fffffff;
}
}

View File

@ -0,0 +1,134 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// To test the code generator, we actually use it to generate code for
// net/proto2/internal/unittest.proto, then test that. This means that we
// are actually testing the parser and other parts of the system at the same
// time, and that problems in the generator may show up as compile-time errors
// rather than unittest failures, which may be surprising. However, testing
// the output of the C++ generator directly would be very hard. We can't very
// well just check it against golden files since those files would have to be
// updated for any small change; such a test would be very brittle and probably
// not very helpful. What we really want to test is that the code compiles
// correctly and produces the interfaces we expect, which is why this test
// is written this way.
#include <thirdparty/protobuf/compiler/cpp/cpp_unittest.h>
#include <thirdparty/protobuf/unittest.pb.h>
#include <thirdparty/protobuf/unittest_embed_optimize_for.pb.h>
#include <thirdparty/protobuf/unittest_optimize_for.pb.h>
#include <thirdparty/protobuf/test_util.h>
#define MESSAGE_TEST_NAME MessageTest
#define GENERATED_DESCRIPTOR_TEST_NAME GeneratedDescriptorTest
#define GENERATED_MESSAGE_TEST_NAME GeneratedMessageTest
#define GENERATED_ENUM_TEST_NAME GeneratedEnumTest
#define GENERATED_SERVICE_TEST_NAME GeneratedServiceTest
#define HELPERS_TEST_NAME HelpersTest
#define DESCRIPTOR_INIT_TEST_NAME DescriptorInitializationTest
#define UNITTEST_PROTO_PATH "net/proto2/internal/unittest.proto"
#define UNITTEST ::protobuf_unittest
#define UNITTEST_IMPORT ::protobuf_unittest_import
// Must include after the above macros.
#include <thirdparty/protobuf/compiler/cpp/cpp_unittest.inc>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
namespace cpp_unittest {
namespace protobuf_unittest = ::protobuf_unittest;
TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingSymbolNames) {
// test_bad_identifiers.proto successfully compiled, then it works. The
// following is just a token usage to insure that the code is, in fact,
// being compiled and linked.
protobuf_unittest::TestConflictingSymbolNames message;
message.set_uint32(1);
EXPECT_EQ(3, message.ByteSizeLong());
message.set_friend_(5);
EXPECT_EQ(5, message.friend_());
message.set_class_(6);
EXPECT_EQ(6, message.class_());
// Instantiate extension template functions to test conflicting template
// parameter names.
typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage;
message.AddExtension(ExtensionMessage::repeated_int32_ext, 123);
EXPECT_EQ(123, message.GetExtension(ExtensionMessage::repeated_int32_ext, 0));
}
TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingEnumNames) {
protobuf_unittest::TestConflictingEnumNames message;
message.set_conflicting_enum(
protobuf_unittest::TestConflictingEnumNames_while_and_);
EXPECT_EQ(1, message.conflicting_enum());
message.set_conflicting_enum(
protobuf_unittest::TestConflictingEnumNames_while_XOR);
EXPECT_EQ(5, message.conflicting_enum());
protobuf_unittest::bool_ conflicting_enum;
conflicting_enum = protobuf_unittest::NOT_EQ;
EXPECT_EQ(1, conflicting_enum);
conflicting_enum = protobuf_unittest::return_;
EXPECT_EQ(3, conflicting_enum);
}
TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingMessageNames) {
protobuf_unittest::NULL_ message;
message.set_int_(123);
EXPECT_EQ(message.int_(), 123);
}
TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingExtension) {
protobuf_unittest::TestConflictingSymbolNames message;
message.SetExtension(protobuf_unittest::void_, 123);
EXPECT_EQ(123, message.GetExtension(protobuf_unittest::void_));
}
} // namespace cpp_unittest
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,51 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This header declares the namespace google::protobuf::protobuf_unittest in order to expose
// any problems with the generated class names. We use this header to ensure
// unittest.cc will declare the namespace prior to other includes, while obeying
// normal include ordering.
//
// When generating a class name of "foo.Bar" we must ensure we prefix the class
// name with "::", in case the namespace google::protobuf::foo exists. We intentionally
// trigger that case here by declaring google::protobuf::protobuf_unittest.
//
// See ClassName in helpers.h for more details.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
namespace google {
namespace protobuf {
namespace protobuf_unittest {}
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,161 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include <thirdparty/protobuf/testing/file.h>
#include <thirdparty/protobuf/testing/file.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_helpers.h>
#include <thirdparty/protobuf/compiler/cpp/cpp_generator.h>
#include <thirdparty/protobuf/compiler/annotation_test_util.h>
#include <thirdparty/protobuf/compiler/command_line_interface.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace atu = annotation_test_util;
namespace {
class CppMetadataTest : public ::testing::Test {
public:
// Tries to capture a FileDescriptorProto, GeneratedCodeInfo, and output
// code from the previously added file with name `filename`. Returns true on
// success. If pb_h is non-null, expects a .pb.h and a .pb.h.meta (copied to
// pb_h and pb_h_info respecfively); similarly for proto_h and proto_h_info.
bool CaptureMetadata(const std::string& filename, FileDescriptorProto* file,
std::string* pb_h, GeneratedCodeInfo* pb_h_info,
std::string* proto_h, GeneratedCodeInfo* proto_h_info,
std::string* pb_cc) {
CommandLineInterface cli;
CppGenerator cpp_generator;
cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
std::string cpp_out =
"--cpp_out=annotate_headers=true,"
"annotation_pragma_name=pragma_name,"
"annotation_guard_name=guard_name:" +
TestTempDir();
const bool result = atu::RunProtoCompiler(filename, cpp_out, &cli, file);
if (!result) {
return result;
}
std::string output_base = TestTempDir() + "/" + StripProto(filename);
if (pb_cc != NULL) {
GOOGLE_CHECK_OK(
File::GetContents(output_base + ".pb.cc", pb_cc, true));
}
if (pb_h != NULL && pb_h_info != NULL) {
GOOGLE_CHECK_OK(
File::GetContents(output_base + ".pb.h", pb_h, true));
if (!atu::DecodeMetadata(output_base + ".pb.h.meta", pb_h_info)) {
return false;
}
}
if (proto_h != NULL && proto_h_info != NULL) {
GOOGLE_CHECK_OK(File::GetContents(output_base + ".proto.h", proto_h,
true));
if (!atu::DecodeMetadata(output_base + ".proto.h.meta", proto_h_info)) {
return false;
}
}
return true;
}
};
const char kSmallTestFile[] =
"syntax = \"proto2\";\n"
"package foo;\n"
"enum Enum { VALUE = 0; }\n"
"message Message { }\n";
TEST_F(CppMetadataTest, CapturesEnumNames) {
FileDescriptorProto file;
GeneratedCodeInfo info;
std::string pb_h;
atu::AddFile("test.proto", kSmallTestFile);
EXPECT_TRUE(
CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
EXPECT_EQ("Enum", file.enum_type(0).name());
std::vector<int> enum_path;
enum_path.push_back(FileDescriptorProto::kEnumTypeFieldNumber);
enum_path.push_back(0);
const GeneratedCodeInfo::Annotation* enum_annotation =
atu::FindAnnotationOnPath(info, "test.proto", enum_path);
EXPECT_TRUE(NULL != enum_annotation);
EXPECT_TRUE(atu::AnnotationMatchesSubstring(pb_h, enum_annotation, "Enum"));
}
TEST_F(CppMetadataTest, AddsPragma) {
FileDescriptorProto file;
GeneratedCodeInfo info;
std::string pb_h;
atu::AddFile("test.proto", kSmallTestFile);
EXPECT_TRUE(
CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
EXPECT_TRUE(pb_h.find("#ifdef guard_name") != std::string::npos);
EXPECT_TRUE(pb_h.find("#pragma pragma_name \"test.pb.h.meta\"") !=
std::string::npos);
}
TEST_F(CppMetadataTest, CapturesMessageNames) {
FileDescriptorProto file;
GeneratedCodeInfo info;
std::string pb_h;
atu::AddFile("test.proto", kSmallTestFile);
EXPECT_TRUE(
CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
EXPECT_EQ("Message", file.message_type(0).name());
std::vector<int> message_path;
message_path.push_back(FileDescriptorProto::kMessageTypeFieldNumber);
message_path.push_back(0);
const GeneratedCodeInfo::Annotation* message_annotation =
atu::FindAnnotationOnPath(info, "test.proto", message_path);
EXPECT_TRUE(NULL != message_annotation);
EXPECT_TRUE(
atu::AnnotationMatchesSubstring(pb_h, message_annotation, "Message"));
}
} // namespace
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,194 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This test insures that
// csharp/src/Google.Protobuf/Reflection/Descriptor.cs match exactly
// what would be generated by the protocol compiler. The file is not
// generated automatically at build time.
//
// If this test fails, run the script
// "generate_descriptor_proto.sh" and add the changed files under
// csharp/src/ to your changelist.
#include <map>
#include <thirdparty/protobuf/compiler/csharp/csharp_generator.h>
#include <thirdparty/protobuf/compiler/importer.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/io/zero_copy_stream_impl.h>
#include <thirdparty/protobuf/stubs/map_util.h>
#include <thirdparty/protobuf/stubs/stl_util.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/stubs/substitute.h>
#include <thirdparty/protobuf/testing/file.h>
#include <thirdparty/protobuf/testing/file.h>
#include <thirdparty/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
namespace {
class MockErrorCollector : public MultiFileErrorCollector {
public:
MockErrorCollector() {}
~MockErrorCollector() {}
std::string text_;
// implements ErrorCollector ---------------------------------------
void AddError(const std::string& filename, int line, int column,
const std::string& message) {
strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n",
filename, line, column, message);
}
};
class MockGeneratorContext : public GeneratorContext {
public:
void ExpectFileMatches(const std::string& virtual_filename,
const std::string& physical_filename) {
auto it = files_.find(virtual_filename);
ASSERT_TRUE(it != files_.end())
<< "Generator failed to generate file: " << virtual_filename;
std::string expected_contents = *it->second;
std::string actual_contents;
GOOGLE_CHECK_OK(
File::GetContentsAsText(TestSourceDir() + "/" + physical_filename,
&actual_contents, true))
<< "Unable to get " << physical_filename;
EXPECT_TRUE(actual_contents == expected_contents)
<< physical_filename << " needs to be regenerated. Please run "
"generate_descriptor_proto.sh. Then add this file "
"to your CL.";
}
// implements GeneratorContext --------------------------------------
virtual io::ZeroCopyOutputStream* Open(const std::string& filename) {
auto& map_slot = files_[filename];
map_slot.reset(new std::string);
return new io::StringOutputStream(map_slot.get());
}
private:
std::map<std::string, std::unique_ptr<std::string>> files_;
};
class GenerateAndTest {
public:
GenerateAndTest() {}
void Run(const FileDescriptor* proto_file, std::string file1, std::string file2) {
ASSERT_TRUE(proto_file != NULL) << TestSourceDir();
ASSERT_TRUE(generator_.Generate(proto_file, parameter_,
&context_, &error_));
context_.ExpectFileMatches(file1, file2);
}
void SetParameter(string parameter) {
parameter_ = parameter;
}
private:
Generator generator_;
MockGeneratorContext context_;
std::string error_;
std::string parameter_;
};
TEST(CsharpBootstrapTest, GeneratedCsharpDescriptorMatches) {
// Skip this whole test if the csharp directory doesn't exist (i.e., a C++11
// only distribution).
std::string descriptor_file_name =
"../csharp/src/Google.Protobuf/Reflection/Descriptor.cs";
if (!File::Exists(TestSourceDir() + "/" + descriptor_file_name)) {
return;
}
MockErrorCollector error_collector;
DiskSourceTree source_tree;
Importer importer(&source_tree, &error_collector);
GenerateAndTest generate_test;
generate_test.SetParameter("base_namespace=Google.Protobuf");
source_tree.MapPath("", TestSourceDir());
generate_test.Run(importer.Import("google/protobuf/descriptor.proto"),
"Reflection/Descriptor.cs",
"../csharp/src/Google.Protobuf/Reflection/Descriptor.cs");
generate_test.Run(importer.Import("google/protobuf/any.proto"),
"WellKnownTypes/Any.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Any.cs");
generate_test.Run(importer.Import("google/protobuf/api.proto"),
"WellKnownTypes/Api.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Api.cs");
generate_test.Run(importer.Import("google/protobuf/duration.proto"),
"WellKnownTypes/Duration.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs");
generate_test.Run(importer.Import("google/protobuf/empty.proto"),
"WellKnownTypes/Empty.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs");
generate_test.Run(importer.Import("google/protobuf/field_mask.proto"),
"WellKnownTypes/FieldMask.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs");
generate_test.Run(importer.Import("google/protobuf/source_context.proto"),
"WellKnownTypes/SourceContext.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs");
generate_test.Run(importer.Import("google/protobuf/struct.proto"),
"WellKnownTypes/Struct.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs");
generate_test.Run(importer.Import("google/protobuf/timestamp.proto"),
"WellKnownTypes/Timestamp.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs");
generate_test.Run(importer.Import("google/protobuf/type.proto"),
"WellKnownTypes/Type.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Type.cs");
generate_test.Run(importer.Import("google/protobuf/wrappers.proto"),
"WellKnownTypes/Wrappers.cs",
"../csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs");
generate_test.SetParameter("");
source_tree.MapPath("", TestSourceDir() + "/../conformance");
generate_test.Run(importer.Import("conformance.proto"),
"Conformance.cs",
"../csharp/src/Google.Protobuf.Conformance/Conformance.cs");
EXPECT_EQ("", error_collector.text_);
}
} // namespace
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,116 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <thirdparty/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
// Functions to create C# XML documentation comments.
// Currently this only includes documentation comments containing text specified as comments
// in the .proto file; documentation comments generated just from field/message/enum/proto names
// is inlined in the relevant code. If more control is required, that code can be moved here.
void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) {
std::string comments = location.leading_comments.empty() ?
location.trailing_comments : location.leading_comments;
if (comments.empty()) {
return;
}
// XML escaping... no need for apostrophes etc as the whole text is going to be a child
// node of a summary element, not part of an attribute.
comments = StringReplace(comments, "&", "&amp;", true);
comments = StringReplace(comments, "<", "&lt;", true);
std::vector<std::string> lines;
lines = Split(comments, "\n", false);
// TODO: We really should work out which part to put in the summary and which to put in the remarks...
// but that needs to be part of a bigger effort to understand the markdown better anyway.
printer->Print("/// <summary>\n");
bool last_was_empty = false;
// We squash multiple blank lines down to one, and remove any trailing blank lines. We need
// to preserve the blank lines themselves, as this is relevant in the markdown.
// Note that we can't remove leading or trailing whitespace as *that's* relevant in markdown too.
// (We don't skip "just whitespace" lines, either.)
for (std::vector<std::string>::iterator it = lines.begin();
it != lines.end(); ++it) {
std::string line = *it;
if (line.empty()) {
last_was_empty = true;
} else {
if (last_was_empty) {
printer->Print("///\n");
}
last_was_empty = false;
printer->Print("///$line$\n", "line", *it);
}
}
printer->Print("/// </summary>\n");
}
template <typename DescriptorType>
static void WriteDocCommentBody(
io::Printer* printer, const DescriptorType* descriptor) {
SourceLocation location;
if (descriptor->GetSourceLocation(&location)) {
WriteDocCommentBodyImpl(printer, location);
}
}
void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
WriteDocCommentBody(printer, message);
}
void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field) {
WriteDocCommentBody(printer, field);
}
void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor) {
WriteDocCommentBody(printer, enumDescriptor);
}
void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value) {
WriteDocCommentBody(printer, value);
}
void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method) {
WriteDocCommentBody(printer, method);
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,51 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/descriptor.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);
void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field);
void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor);
void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value);
void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method);
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__

View File

@ -0,0 +1,99 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_enum.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_options.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Options* options) :
SourceGeneratorBase(options),
descriptor_(descriptor) {
}
EnumGenerator::~EnumGenerator() {
}
void EnumGenerator::Generate(io::Printer* printer) {
WriteEnumDocComment(printer, descriptor_);
printer->Print("$access_level$ enum $name$ {\n",
"access_level", class_access_level(),
"name", descriptor_->name());
printer->Indent();
std::set<std::string> used_names;
std::set<int> used_number;
for (int i = 0; i < descriptor_->value_count(); i++) {
WriteEnumValueDocComment(printer, descriptor_->value(i));
std::string original_name = descriptor_->value(i)->name();
std::string name =
GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
// Make sure we don't get any duplicate names due to prefix removal.
while (!used_names.insert(name).second) {
// It's possible we'll end up giving this warning multiple times, but that's better than not at all.
GOOGLE_LOG(WARNING) << "Duplicate enum value " << name << " (originally " << original_name
<< ") in " << descriptor_->name() << "; adding underscore to distinguish";
name += "_";
}
int number = descriptor_->value(i)->number();
if (!used_number.insert(number).second) {
printer->Print("[pbr::OriginalName(\"$original_name$\", PreferredAlias = false)] $name$ = $number$,\n",
"original_name", original_name,
"name", name,
"number", StrCat(number));
} else {
printer->Print("[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n",
"original_name", original_name,
"name", name,
"number", StrCat(number));
}
}
printer->Outdent();
printer->Print("}\n");
printer->Print("\n");
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,66 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
#include <string>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_source_generator_base.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/io/printer.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
class EnumGenerator : public SourceGeneratorBase {
public:
EnumGenerator(const EnumDescriptor* descriptor, const Options* options);
~EnumGenerator();
EnumGenerator(const EnumGenerator&) = delete;
EnumGenerator& operator=(const EnumGenerator&) = delete;
void Generate(io::Printer* printer);
private:
const EnumDescriptor* descriptor_;
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__

View File

@ -0,0 +1,135 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_options.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_enum_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex, const Options *options)
: PrimitiveFieldGenerator(descriptor, presenceIndex, options) {
}
EnumFieldGenerator::~EnumFieldGenerator() {
}
void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(variables_,
"$property_name$ = ($type_name$) input.ReadEnum();\n");
}
void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(variables_,
"if ($has_property_check$) {\n"
" output.WriteRawTag($tag_bytes$);\n"
" output.WriteEnum((int) $property_name$);\n"
"}\n");
}
void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
"}\n");
}
void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) {
printer->Print(
variables_,
"pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x, $default_value$)");
}
void EnumFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
" new pb::Extension<$extended_type$, $type_name$>($number$, ");
GenerateCodecCode(printer);
printer->Print(");\n");
}
EnumOneofFieldGenerator::EnumOneofFieldGenerator(
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options) {
}
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {
}
void EnumOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(variables_, "$property_name$ = other.$property_name$;\n");
}
void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
// TODO(jonskeet): What about if we read the default value?
printer->Print(
variables_,
"$oneof_name$_ = input.ReadEnum();\n"
"$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n");
}
void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" output.WriteRawTag($tag_bytes$);\n"
" output.WriteEnum((int) $property_name$);\n"
"}\n");
}
void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
"}\n");
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,83 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
#include <string>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_primitive_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
class EnumFieldGenerator : public PrimitiveFieldGenerator {
public:
EnumFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~EnumFieldGenerator();
EnumFieldGenerator(const EnumFieldGenerator&) = delete;
EnumFieldGenerator& operator=(const EnumFieldGenerator&) = delete;
virtual void GenerateCodecCode(io::Printer* printer) override;
virtual void GenerateParsingCode(io::Printer* printer) override;
virtual void GenerateSerializationCode(io::Printer* printer) override;
virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
virtual void GenerateExtensionCode(io::Printer* printer) override;
};
class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
public:
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~EnumOneofFieldGenerator();
EnumOneofFieldGenerator(const EnumOneofFieldGenerator&) = delete;
EnumOneofFieldGenerator& operator=(const EnumOneofFieldGenerator&) = delete;
virtual void GenerateMergingCode(io::Printer* printer) override;
virtual void GenerateParsingCode(io::Printer* printer) override;
virtual void GenerateSerializationCode(io::Printer* printer) override;
virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__

View File

@ -0,0 +1,459 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cmath>
#include <limits>
#include <sstream>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/coded_stream.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/wire_format.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_field_base.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_names.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
void FieldGeneratorBase::SetCommonFieldVariables(
std::map<std::string, std::string>* variables) {
// Note: this will be valid even though the tag emitted for packed and unpacked versions of
// repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
// never effects the tag size.
int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
int part_tag_size = tag_size;
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
part_tag_size /= 2;
}
uint tag = internal::WireFormat::MakeTag(descriptor_);
uint8 tag_array[5];
io::CodedOutputStream::WriteTagToArray(tag, tag_array);
std::string tag_bytes = StrCat(tag_array[0]);
for (int i = 1; i < part_tag_size; i++) {
tag_bytes += ", " + StrCat(tag_array[i]);
}
(*variables)["tag"] = StrCat(tag);
(*variables)["tag_size"] = StrCat(tag_size);
(*variables)["tag_bytes"] = tag_bytes;
if (descriptor_->type() == FieldDescriptor::Type::TYPE_GROUP) {
tag = internal::WireFormatLite::MakeTag(
descriptor_->number(),
internal::WireFormatLite::WIRETYPE_END_GROUP);
io::CodedOutputStream::WriteTagToArray(tag, tag_array);
tag_bytes = StrCat(tag_array[0]);
for (int i = 1; i < part_tag_size; i++) {
tag_bytes += ", " + StrCat(tag_array[i]);
}
variables_["end_tag"] = StrCat(tag);
variables_["end_tag_bytes"] = tag_bytes;
}
(*variables)["access_level"] = "public";
(*variables)["property_name"] = property_name();
(*variables)["type_name"] = type_name();
(*variables)["extended_type"] = GetClassName(descriptor_->containing_type());
(*variables)["name"] = name();
(*variables)["descriptor_name"] = descriptor_->name();
(*variables)["default_value"] = default_value();
(*variables)["capitalized_type_name"] = capitalized_type_name();
(*variables)["number"] = number();
if (has_default_value() && !SupportsPresenceApi(descriptor_)) {
(*variables)["name_def_message"] =
(*variables)["name"] + "_ = " + (*variables)["default_value"];
} else {
(*variables)["name_def_message"] = (*variables)["name"] + "_";
}
if (SupportsPresenceApi(descriptor_)) {
(*variables)["has_property_check"] = "Has" + (*variables)["property_name"];
(*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"];
(*variables)["has_not_property_check"] = "!" + (*variables)["has_property_check"];
(*variables)["other_has_not_property_check"] = "!" + (*variables)["other_has_property_check"];
if (presenceIndex_ != -1) {
std::string hasBitsNumber = StrCat(presenceIndex_ / 32);
std::string hasBitsMask = StrCat(1 << (presenceIndex_ % 32));
(*variables)["has_field_check"] = "(_hasBits" + hasBitsNumber + " & " + hasBitsMask + ") != 0";
(*variables)["set_has_field"] = "_hasBits" + hasBitsNumber + " |= " + hasBitsMask;
(*variables)["clear_has_field"] = "_hasBits" + hasBitsNumber + " &= ~" + hasBitsMask;
}
} else {
(*variables)["has_property_check"] =
(*variables)["property_name"] + " != " + (*variables)["default_value"];
(*variables)["other_has_property_check"] = "other." +
(*variables)["property_name"] + " != " + (*variables)["default_value"];
}
}
void FieldGeneratorBase::SetCommonOneofFieldVariables(
std::map<std::string, std::string>* variables) {
(*variables)["oneof_name"] = oneof_name();
if (SupportsPresenceApi(descriptor_)) {
(*variables)["has_property_check"] = "Has" + property_name();
} else {
(*variables)["has_property_check"] =
oneof_name() + "Case_ == " + oneof_property_name() +
"OneofCase." + property_name();
}
(*variables)["oneof_property_name"] = oneof_property_name();
}
FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
int presenceIndex, const Options* options)
: SourceGeneratorBase(options),
descriptor_(descriptor),
presenceIndex_(presenceIndex) {
SetCommonFieldVariables(&variables_);
}
FieldGeneratorBase::~FieldGeneratorBase() {
}
void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) {
// No-op: only message fields and repeated fields need
// special handling for freezing, so default to not generating any code.
}
void FieldGeneratorBase::GenerateCodecCode(io::Printer* printer) {
// No-op: expect this to be overridden by appropriate types.
// Could fail if we get called here though...
}
void FieldGeneratorBase::GenerateExtensionCode(io::Printer* printer) {
// No-op: only message fields, enum fields, primitives,
// and repeated fields need this default is to not generate any code
}
void FieldGeneratorBase::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
// for some field types the value of "use_parse_context" doesn't matter,
// so we fallback to the default implementation.
GenerateParsingCode(printer);
}
void FieldGeneratorBase::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
// for some field types the value of "use_write_context" doesn't matter,
// so we fallback to the default implementation.
GenerateSerializationCode(printer);
}
void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
if (descriptor_->options().deprecated()) {
printer->Print("[global::System.ObsoleteAttribute]\n");
} else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE &&
descriptor_->message_type()->options().deprecated()) {
printer->Print("[global::System.ObsoleteAttribute]\n");
}
}
void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) {
AddDeprecatedFlag(printer);
WriteGeneratedCodeAttributes(printer);
}
std::string FieldGeneratorBase::oneof_property_name() {
return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), true);
}
std::string FieldGeneratorBase::oneof_name() {
return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), false);
}
std::string FieldGeneratorBase::property_name() {
return GetPropertyName(descriptor_);
}
std::string FieldGeneratorBase::name() {
return UnderscoresToCamelCase(GetFieldName(descriptor_), false);
}
std::string FieldGeneratorBase::type_name() {
return type_name(descriptor_);
}
std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
switch (descriptor->type()) {
case FieldDescriptor::TYPE_ENUM:
return GetClassName(descriptor->enum_type());
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
if (IsWrapperType(descriptor)) {
const FieldDescriptor* wrapped_field =
descriptor->message_type()->field(0);
std::string wrapped_field_type_name = type_name(wrapped_field);
// String and ByteString go to the same type; other wrapped types
// go to the nullable equivalent.
if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
wrapped_field->type() == FieldDescriptor::TYPE_BYTES) {
return wrapped_field_type_name;
} else {
return wrapped_field_type_name + "?";
}
}
return GetClassName(descriptor->message_type());
case FieldDescriptor::TYPE_DOUBLE:
return "double";
case FieldDescriptor::TYPE_FLOAT:
return "float";
case FieldDescriptor::TYPE_INT64:
return "long";
case FieldDescriptor::TYPE_UINT64:
return "ulong";
case FieldDescriptor::TYPE_INT32:
return "int";
case FieldDescriptor::TYPE_FIXED64:
return "ulong";
case FieldDescriptor::TYPE_FIXED32:
return "uint";
case FieldDescriptor::TYPE_BOOL:
return "bool";
case FieldDescriptor::TYPE_STRING:
return "string";
case FieldDescriptor::TYPE_BYTES:
return "pb::ByteString";
case FieldDescriptor::TYPE_UINT32:
return "uint";
case FieldDescriptor::TYPE_SFIXED32:
return "int";
case FieldDescriptor::TYPE_SFIXED64:
return "long";
case FieldDescriptor::TYPE_SINT32:
return "int";
case FieldDescriptor::TYPE_SINT64:
return "long";
default:
GOOGLE_LOG(FATAL)<< "Unknown field type.";
return "";
}
}
bool FieldGeneratorBase::has_default_value() {
switch (descriptor_->type()) {
case FieldDescriptor::TYPE_ENUM:
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
return true;
case FieldDescriptor::TYPE_DOUBLE:
return descriptor_->default_value_double() != 0.0;
case FieldDescriptor::TYPE_FLOAT:
return descriptor_->default_value_float() != 0.0;
case FieldDescriptor::TYPE_INT64:
return descriptor_->default_value_int64() != 0L;
case FieldDescriptor::TYPE_UINT64:
return descriptor_->default_value_uint64() != 0L;
case FieldDescriptor::TYPE_INT32:
return descriptor_->default_value_int32() != 0;
case FieldDescriptor::TYPE_FIXED64:
return descriptor_->default_value_uint64() != 0L;
case FieldDescriptor::TYPE_FIXED32:
return descriptor_->default_value_uint32() != 0;
case FieldDescriptor::TYPE_BOOL:
return descriptor_->default_value_bool();
case FieldDescriptor::TYPE_STRING:
return true;
case FieldDescriptor::TYPE_BYTES:
return true;
case FieldDescriptor::TYPE_UINT32:
return descriptor_->default_value_uint32() != 0;
case FieldDescriptor::TYPE_SFIXED32:
return descriptor_->default_value_int32() != 0;
case FieldDescriptor::TYPE_SFIXED64:
return descriptor_->default_value_int64() != 0L;
case FieldDescriptor::TYPE_SINT32:
return descriptor_->default_value_int32() != 0;
case FieldDescriptor::TYPE_SINT64:
return descriptor_->default_value_int64() != 0L;
default:
GOOGLE_LOG(FATAL)<< "Unknown field type.";
return true;
}
}
bool AllPrintableAscii(const std::string& text) {
for(int i = 0; i < text.size(); i++) {
if (text[i] < 0x20 || text[i] > 0x7e) {
return false;
}
}
return true;
}
std::string FieldGeneratorBase::GetStringDefaultValueInternal(const FieldDescriptor* descriptor) {
if (descriptor->default_value_string().empty())
return "\"\"";
else
return "global::System.Text.Encoding.UTF8.GetString(global::System."
"Convert.FromBase64String(\"" +
StringToBase64(descriptor->default_value_string()) + "\"), 0, " + StrCat(descriptor->default_value_string().length()) + ")";
}
std::string FieldGeneratorBase::GetBytesDefaultValueInternal(const FieldDescriptor* descriptor) {
if (descriptor->default_value_string().empty())
return "pb::ByteString.Empty";
else
return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor->default_value_string()) + "\")";
}
std::string FieldGeneratorBase::default_value() {
return default_value(descriptor_);
}
std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
switch (descriptor->type()) {
case FieldDescriptor::TYPE_ENUM:
return GetClassName(descriptor->default_value_enum()->type()) + "." +
GetEnumValueName(descriptor->default_value_enum()->type()->name(), descriptor->default_value_enum()->name());
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
if (IsWrapperType(descriptor)) {
const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
return default_value(wrapped_field);
} else {
return "null";
}
case FieldDescriptor::TYPE_DOUBLE: {
double value = descriptor->default_value_double();
if (value == std::numeric_limits<double>::infinity()) {
return "double.PositiveInfinity";
} else if (value == -std::numeric_limits<double>::infinity()) {
return "double.NegativeInfinity";
} else if (std::isnan(value)) {
return "double.NaN";
}
return StrCat(value) + "D";
}
case FieldDescriptor::TYPE_FLOAT: {
float value = descriptor->default_value_float();
if (value == std::numeric_limits<float>::infinity()) {
return "float.PositiveInfinity";
} else if (value == -std::numeric_limits<float>::infinity()) {
return "float.NegativeInfinity";
} else if (std::isnan(value)) {
return "float.NaN";
}
return StrCat(value) + "F";
}
case FieldDescriptor::TYPE_INT64:
return StrCat(descriptor->default_value_int64()) + "L";
case FieldDescriptor::TYPE_UINT64:
return StrCat(descriptor->default_value_uint64()) + "UL";
case FieldDescriptor::TYPE_INT32:
return StrCat(descriptor->default_value_int32());
case FieldDescriptor::TYPE_FIXED64:
return StrCat(descriptor->default_value_uint64()) + "UL";
case FieldDescriptor::TYPE_FIXED32:
return StrCat(descriptor->default_value_uint32());
case FieldDescriptor::TYPE_BOOL:
if (descriptor->default_value_bool()) {
return "true";
} else {
return "false";
}
case FieldDescriptor::TYPE_STRING:
return GetStringDefaultValueInternal(descriptor);
case FieldDescriptor::TYPE_BYTES:
return GetBytesDefaultValueInternal(descriptor);
case FieldDescriptor::TYPE_UINT32:
return StrCat(descriptor->default_value_uint32());
case FieldDescriptor::TYPE_SFIXED32:
return StrCat(descriptor->default_value_int32());
case FieldDescriptor::TYPE_SFIXED64:
return StrCat(descriptor->default_value_int64()) + "L";
case FieldDescriptor::TYPE_SINT32:
return StrCat(descriptor->default_value_int32());
case FieldDescriptor::TYPE_SINT64:
return StrCat(descriptor->default_value_int64()) + "L";
default:
GOOGLE_LOG(FATAL)<< "Unknown field type.";
return "";
}
}
std::string FieldGeneratorBase::number() {
return StrCat(descriptor_->number());
}
std::string FieldGeneratorBase::capitalized_type_name() {
switch (descriptor_->type()) {
case FieldDescriptor::TYPE_ENUM:
return "Enum";
case FieldDescriptor::TYPE_MESSAGE:
return "Message";
case FieldDescriptor::TYPE_GROUP:
return "Group";
case FieldDescriptor::TYPE_DOUBLE:
return "Double";
case FieldDescriptor::TYPE_FLOAT:
return "Float";
case FieldDescriptor::TYPE_INT64:
return "Int64";
case FieldDescriptor::TYPE_UINT64:
return "UInt64";
case FieldDescriptor::TYPE_INT32:
return "Int32";
case FieldDescriptor::TYPE_FIXED64:
return "Fixed64";
case FieldDescriptor::TYPE_FIXED32:
return "Fixed32";
case FieldDescriptor::TYPE_BOOL:
return "Bool";
case FieldDescriptor::TYPE_STRING:
return "String";
case FieldDescriptor::TYPE_BYTES:
return "Bytes";
case FieldDescriptor::TYPE_UINT32:
return "UInt32";
case FieldDescriptor::TYPE_SFIXED32:
return "SFixed32";
case FieldDescriptor::TYPE_SFIXED64:
return "SFixed64";
case FieldDescriptor::TYPE_SINT32:
return "SInt32";
case FieldDescriptor::TYPE_SINT64:
return "SInt64";
default:
GOOGLE_LOG(FATAL)<< "Unknown field type.";
return "";
}
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,111 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
#include <string>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_source_generator_base.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/io/printer.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
class FieldGeneratorBase : public SourceGeneratorBase {
public:
FieldGeneratorBase(const FieldDescriptor* descriptor,
int presenceIndex,
const Options* options);
~FieldGeneratorBase();
FieldGeneratorBase(const FieldGeneratorBase&) = delete;
FieldGeneratorBase& operator=(const FieldGeneratorBase&) = delete;
virtual void GenerateCloningCode(io::Printer* printer) = 0;
virtual void GenerateFreezingCode(io::Printer* printer);
virtual void GenerateCodecCode(io::Printer* printer);
virtual void GenerateExtensionCode(io::Printer* printer);
virtual void GenerateMembers(io::Printer* printer) = 0;
virtual void GenerateMergingCode(io::Printer* printer) = 0;
virtual void GenerateParsingCode(io::Printer* printer) = 0;
virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context);
virtual void GenerateSerializationCode(io::Printer* printer) = 0;
virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0;
virtual void WriteHash(io::Printer* printer) = 0;
virtual void WriteEquals(io::Printer* printer) = 0;
// Currently unused, as we use reflection to generate JSON
virtual void WriteToString(io::Printer* printer) = 0;
protected:
const FieldDescriptor* descriptor_;
const int presenceIndex_;
std::map<std::string, std::string> variables_;
void AddDeprecatedFlag(io::Printer* printer);
void AddNullCheck(io::Printer* printer);
void AddNullCheck(io::Printer* printer, const std::string& name);
void AddPublicMemberAttributes(io::Printer* printer);
void SetCommonOneofFieldVariables(
std::map<std::string, std::string>* variables);
std::string oneof_property_name();
std::string oneof_name();
std::string property_name();
std::string name();
std::string type_name();
std::string type_name(const FieldDescriptor* descriptor);
bool has_default_value();
std::string default_value();
std::string default_value(const FieldDescriptor* descriptor);
std::string number();
std::string capitalized_type_name();
private:
void SetCommonFieldVariables(std::map<std::string, std::string>* variables);
std::string GetStringDefaultValueInternal(const FieldDescriptor* descriptor);
std::string GetBytesDefaultValueInternal(const FieldDescriptor* descriptor);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__

View File

@ -0,0 +1,112 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_generator.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_names.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_options.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_reflection_class.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
Generator::Generator() {}
Generator::~Generator() {}
uint64_t Generator::GetSupportedFeatures() const {
return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
}
void GenerateFile(const FileDescriptor* file, io::Printer* printer,
const Options* options) {
ReflectionClassGenerator reflectionClassGenerator(file, options);
reflectionClassGenerator.Generate(printer);
}
bool Generator::Generate(const FileDescriptor* file,
const std::string& parameter,
GeneratorContext* generator_context,
std::string* error) const {
std::vector<std::pair<std::string, std::string> > options;
ParseGeneratorParameter(parameter, &options);
struct Options cli_options;
for (int i = 0; i < options.size(); i++) {
if (options[i].first == "file_extension") {
cli_options.file_extension = options[i].second;
} else if (options[i].first == "base_namespace") {
cli_options.base_namespace = options[i].second;
cli_options.base_namespace_specified = true;
} else if (options[i].first == "internal_access") {
cli_options.internal_access = true;
} else if (options[i].first == "serializable") {
cli_options.serializable = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
}
}
std::string filename_error = "";
std::string filename = GetOutputFile(file,
cli_options.file_extension,
cli_options.base_namespace_specified,
cli_options.base_namespace,
&filename_error);
if (filename.empty()) {
*error = filename_error;
return false;
}
std::unique_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(filename));
io::Printer printer(output.get(), '$');
GenerateFile(file, &printer, &cli_options);
return true;
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,70 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Generates C# code for a given .proto file.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
#include <string>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
// CodeGenerator implementation which generates a C# source file and
// header. If you create your own protocol compiler binary and you want
// it to support C# output, you can do so by registering an instance of this
// CodeGenerator with the CommandLineInterface in your main() function.
class PROTOC_EXPORT Generator : public CodeGenerator {
public:
Generator();
~Generator();
bool Generate(
const FileDescriptor* file,
const std::string& parameter,
GeneratorContext* generator_context,
std::string* error) const override;
uint64_t GetSupportedFeatures() const override;
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__

View File

@ -0,0 +1,70 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2014 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include <thirdparty/protobuf/compiler/command_line_interface.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <thirdparty/protobuf/testing/file.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
namespace {
TEST(CSharpEnumValue, PascalCasedPrefixStripping) {
EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR"));
EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ"));
EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO_BAR"));
EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO__BAR"));
EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "FOO_BAR_BAZ"));
EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "Foo_BarBaz"));
EXPECT_EQ("Bar", GetEnumValueName("FO_O", "FOO_BAR"));
EXPECT_EQ("Bar", GetEnumValueName("FOO", "F_O_O_BAR"));
EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR"));
EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ"));
EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO"));
EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO___"));
// Identifiers can't start with digits
EXPECT_EQ("_2Bar", GetEnumValueName("Foo", "FOO_2_BAR"));
EXPECT_EQ("_2", GetEnumValueName("Foo", "FOO___2"));
}
} // namespace
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,592 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <algorithm>
#include <limits>
#include <vector>
#include <sstream>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_names.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/wire_format.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_field_base.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_enum_field.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_map_field.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_message_field.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_options.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_primitive_field.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_repeated_message_field.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_repeated_primitive_field.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_wrapper_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
CSharpType GetCSharpType(FieldDescriptor::Type type) {
switch (type) {
case FieldDescriptor::TYPE_INT32:
return CSHARPTYPE_INT32;
case FieldDescriptor::TYPE_INT64:
return CSHARPTYPE_INT64;
case FieldDescriptor::TYPE_UINT32:
return CSHARPTYPE_UINT32;
case FieldDescriptor::TYPE_UINT64:
return CSHARPTYPE_UINT32;
case FieldDescriptor::TYPE_SINT32:
return CSHARPTYPE_INT32;
case FieldDescriptor::TYPE_SINT64:
return CSHARPTYPE_INT64;
case FieldDescriptor::TYPE_FIXED32:
return CSHARPTYPE_UINT32;
case FieldDescriptor::TYPE_FIXED64:
return CSHARPTYPE_UINT64;
case FieldDescriptor::TYPE_SFIXED32:
return CSHARPTYPE_INT32;
case FieldDescriptor::TYPE_SFIXED64:
return CSHARPTYPE_INT64;
case FieldDescriptor::TYPE_FLOAT:
return CSHARPTYPE_FLOAT;
case FieldDescriptor::TYPE_DOUBLE:
return CSHARPTYPE_DOUBLE;
case FieldDescriptor::TYPE_BOOL:
return CSHARPTYPE_BOOL;
case FieldDescriptor::TYPE_ENUM:
return CSHARPTYPE_ENUM;
case FieldDescriptor::TYPE_STRING:
return CSHARPTYPE_STRING;
case FieldDescriptor::TYPE_BYTES:
return CSHARPTYPE_BYTESTRING;
case FieldDescriptor::TYPE_GROUP:
return CSHARPTYPE_MESSAGE;
case FieldDescriptor::TYPE_MESSAGE:
return CSHARPTYPE_MESSAGE;
// No default because we want the compiler to complain if any new
// types are added.
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
return (CSharpType) -1;
}
std::string StripDotProto(const std::string& proto_file) {
int lastindex = proto_file.find_last_of(".");
return proto_file.substr(0, lastindex);
}
std::string GetFileNamespace(const FileDescriptor* descriptor) {
if (descriptor->options().has_csharp_namespace()) {
return descriptor->options().csharp_namespace();
}
return UnderscoresToCamelCase(descriptor->package(), true, true);
}
// Returns the Pascal-cased last part of the proto file. For example,
// input of "google/protobuf/foo_bar.proto" would result in "FooBar".
std::string GetFileNameBase(const FileDescriptor* descriptor) {
std::string proto_file = descriptor->name();
int lastslash = proto_file.find_last_of("/");
std::string base = proto_file.substr(lastslash + 1);
return UnderscoresToPascalCase(StripDotProto(base));
}
std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) {
// TODO: Detect collisions with existing messages,
// and append an underscore if necessary.
return GetFileNameBase(descriptor) + "Reflection";
}
std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor) {
// TODO: Detect collisions with existing messages,
// and append an underscore if necessary.
return GetFileNameBase(descriptor) + "Extensions";
}
// TODO(jtattermusch): can we reuse a utility function?
std::string UnderscoresToCamelCase(const std::string& input,
bool cap_next_letter,
bool preserve_period) {
std::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') {
if (i == 0 && !cap_next_letter) {
// Force first letter to lower-case unless explicitly told to
// capitalize it.
result += input[i] + ('a' - 'A');
} else {
// Capital letters after the first 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;
if (input[i] == '.' && preserve_period) {
result += '.';
}
}
}
// Add a trailing "_" if the name should be altered.
if (input.size() > 0 && input[input.size() - 1] == '#') {
result += '_';
}
return result;
}
std::string UnderscoresToPascalCase(const std::string& input) {
return UnderscoresToCamelCase(input, true);
}
// Convert a string which is expected to be SHOUTY_CASE (but may not be *precisely* shouty)
// into a PascalCase string. Precise rules implemented:
// Previous input character Current character Case
// Any Non-alphanumeric Skipped
// None - first char of input Alphanumeric Upper
// Non-letter (e.g. _ or 1) Alphanumeric Upper
// Numeric Alphanumeric Upper
// Lower letter Alphanumeric Same as current
// Upper letter Alphanumeric Lower
std::string ShoutyToPascalCase(const std::string& input) {
std::string result;
// Simple way of implementing "always start with upper"
char previous = '_';
for (int i = 0; i < input.size(); i++) {
char current = input[i];
if (!ascii_isalnum(current)) {
previous = current;
continue;
}
if (!ascii_isalnum(previous)) {
result += ascii_toupper(current);
} else if (ascii_isdigit(previous)) {
result += ascii_toupper(current);
} else if (ascii_islower(previous)) {
result += current;
} else {
result += ascii_tolower(current);
}
previous = current;
}
return result;
}
// Attempt to remove a prefix from a value, ignoring casing and skipping underscores.
// (foo, foo_bar) => bar - underscore after prefix is skipped
// (FOO, foo_bar) => bar - casing is ignored
// (foo_bar, foobarbaz) => baz - underscore in prefix is ignored
// (foobar, foo_barbaz) => baz - underscore in value is ignored
// (foo, bar) => bar - prefix isn't matched; return original value
std::string TryRemovePrefix(const std::string& prefix, const std::string& value) {
// First normalize to a lower-case no-underscores prefix to match against
std::string prefix_to_match = "";
for (size_t i = 0; i < prefix.size(); i++) {
if (prefix[i] != '_') {
prefix_to_match += ascii_tolower(prefix[i]);
}
}
// This keeps track of how much of value we've consumed
size_t prefix_index, value_index;
for (prefix_index = 0, value_index = 0;
prefix_index < prefix_to_match.size() && value_index < value.size();
value_index++) {
// Skip over underscores in the value
if (value[value_index] == '_') {
continue;
}
if (ascii_tolower(value[value_index]) != prefix_to_match[prefix_index++]) {
// Failed to match the prefix - bail out early.
return value;
}
}
// If we didn't finish looking through the prefix, we can't strip it.
if (prefix_index < prefix_to_match.size()) {
return value;
}
// Step over any underscores after the prefix
while (value_index < value.size() && value[value_index] == '_') {
value_index++;
}
// If there's nothing left (e.g. it was a prefix with only underscores afterwards), don't strip.
if (value_index == value.size()) {
return value;
}
return value.substr(value_index);
}
// Format the enum value name in a pleasant way for C#:
// - Strip the enum name as a prefix if possible
// - Convert to PascalCase.
// For example, an enum called Color with a value of COLOR_BLUE should
// result in an enum value in C# called just Blue
std::string GetEnumValueName(const std::string& enum_name, const std::string& enum_value_name) {
std::string stripped = TryRemovePrefix(enum_name, enum_value_name);
std::string result = ShoutyToPascalCase(stripped);
// Just in case we have an enum name of FOO and a value of FOO_2... make sure the returned
// string is a valid identifier.
if (ascii_isdigit(result[0])) {
result = "_" + result;
}
return result;
}
uint GetGroupEndTag(const Descriptor* descriptor) {
const Descriptor* containing_type = descriptor->containing_type();
if (containing_type != NULL) {
const FieldDescriptor* field;
for (int i = 0; i < containing_type->field_count(); i++) {
field = containing_type->field(i);
if (field->type() == FieldDescriptor::Type::TYPE_GROUP &&
field->message_type() == descriptor) {
return internal::WireFormatLite::MakeTag(
field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP);
}
}
for (int i = 0; i < containing_type->extension_count(); i++) {
field = containing_type->extension(i);
if (field->type() == FieldDescriptor::Type::TYPE_GROUP &&
field->message_type() == descriptor) {
return internal::WireFormatLite::MakeTag(
field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP);
}
}
} else {
const FileDescriptor* containing_file = descriptor->file();
if (containing_file != NULL) {
const FieldDescriptor* field;
for (int i = 0; i < containing_file->extension_count(); i++) {
field = containing_file->extension(i);
if (field->type() == FieldDescriptor::Type::TYPE_GROUP &&
field->message_type() == descriptor) {
return internal::WireFormatLite::MakeTag(
field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP);
}
}
}
}
return 0;
}
std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
std::string result = GetFileNamespace(file);
if (!result.empty()) {
result += '.';
}
std::string classname;
if (file->package().empty()) {
classname = name;
} else {
// Strip the proto package from full_name since we've replaced it with
// the C# namespace.
classname = name.substr(file->package().size() + 1);
}
result += StringReplace(classname, ".", ".Types.", true);
return "global::" + result;
}
std::string GetReflectionClassName(const FileDescriptor* descriptor) {
std::string result = GetFileNamespace(descriptor);
if (!result.empty()) {
result += '.';
}
result += GetReflectionClassUnqualifiedName(descriptor);
return "global::" + result;
}
std::string GetFullExtensionName(const FieldDescriptor* descriptor) {
if (descriptor->extension_scope()) {
return GetClassName(descriptor->extension_scope()) + ".Extensions." + GetPropertyName(descriptor);
}
else {
return GetExtensionClassUnqualifiedName(descriptor->file()) + "." + GetPropertyName(descriptor);
}
}
std::string GetClassName(const Descriptor* descriptor) {
return ToCSharpName(descriptor->full_name(), descriptor->file());
}
std::string GetClassName(const EnumDescriptor* descriptor) {
return ToCSharpName(descriptor->full_name(), descriptor->file());
}
// Groups are hacky: The name of the field is just the lower-cased name
// of the group type. In C#, though, we would like to retain the original
// capitalization of the type name.
std::string GetFieldName(const FieldDescriptor* descriptor) {
if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
return descriptor->message_type()->name();
} else {
return descriptor->name();
}
}
std::string GetFieldConstantName(const FieldDescriptor* field) {
return GetPropertyName(field) + "FieldNumber";
}
std::string GetPropertyName(const FieldDescriptor* descriptor) {
// TODO(jtattermusch): consider introducing csharp_property_name field option
std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor));
// Avoid either our own type name or reserved names. Note that not all names
// are reserved - a field called to_string, write_to etc would still cause a problem.
// There are various ways of ending up with naming collisions, but we try to avoid obvious
// ones.
if (property_name == descriptor->containing_type()->name()
|| property_name == "Types"
|| property_name == "Descriptor") {
property_name += "_";
}
return property_name;
}
std::string GetOutputFile(const FileDescriptor* descriptor,
const std::string file_extension,
const bool generate_directories,
const std::string base_namespace,
std::string* error) {
std::string relative_filename = GetFileNameBase(descriptor) + file_extension;
if (!generate_directories) {
return relative_filename;
}
std::string ns = GetFileNamespace(descriptor);
std::string namespace_suffix = ns;
if (!base_namespace.empty()) {
// Check that the base_namespace is either equal to or a leading part of
// the file namespace. This isn't just a simple prefix; "Foo.B" shouldn't
// be regarded as a prefix of "Foo.Bar". The simplest option is to add "."
// to both.
std::string extended_ns = ns + ".";
if (extended_ns.find(base_namespace + ".") != 0) {
*error = "Namespace " + ns + " is not a prefix namespace of base namespace " + base_namespace;
return ""; // This will be ignored, because we've set an error.
}
namespace_suffix = ns.substr(base_namespace.length());
if (namespace_suffix.find(".") == 0) {
namespace_suffix = namespace_suffix.substr(1);
}
}
std::string namespace_dir = StringReplace(namespace_suffix, ".", "/", true);
if (!namespace_dir.empty()) {
namespace_dir += "/";
}
return namespace_dir + relative_filename;
}
// TODO: c&p from Java protoc plugin
// For encodings with fixed sizes, returns that size in bytes. Otherwise
// returns -1.
int GetFixedSize(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 internal::WireFormatLite::kFixed32Size;
case FieldDescriptor::TYPE_FIXED64 : return internal::WireFormatLite::kFixed64Size;
case FieldDescriptor::TYPE_SFIXED32: return internal::WireFormatLite::kSFixed32Size;
case FieldDescriptor::TYPE_SFIXED64: return internal::WireFormatLite::kSFixed64Size;
case FieldDescriptor::TYPE_FLOAT : return internal::WireFormatLite::kFloatSize;
case FieldDescriptor::TYPE_DOUBLE : return internal::WireFormatLite::kDoubleSize;
case FieldDescriptor::TYPE_BOOL : return internal::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;
}
static const char base64_chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string StringToBase64(const std::string& input) {
std::string result;
size_t remaining = input.size();
const unsigned char *src = (const unsigned char*) input.c_str();
while (remaining > 2) {
result += base64_chars[src[0] >> 2];
result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
result += base64_chars[((src[1] & 0xf) << 2) | (src[2] >> 6)];
result += base64_chars[src[2] & 0x3f];
remaining -= 3;
src += 3;
}
switch (remaining) {
case 2:
result += base64_chars[src[0] >> 2];
result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
result += base64_chars[(src[1] & 0xf) << 2];
result += '=';
src += 2;
break;
case 1:
result += base64_chars[src[0] >> 2];
result += base64_chars[((src[0] & 0x3) << 4)];
result += '=';
result += '=';
src += 1;
break;
}
return result;
}
std::string FileDescriptorToBase64(const FileDescriptor* descriptor) {
std::string fdp_bytes;
FileDescriptorProto fdp;
descriptor->CopyTo(&fdp);
fdp.SerializeToString(&fdp_bytes);
return StringToBase64(fdp_bytes);
}
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options* options) {
switch (descriptor->type()) {
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
if (descriptor->is_repeated()) {
if (descriptor->is_map()) {
return new MapFieldGenerator(descriptor, presenceIndex, options);
} else {
return new RepeatedMessageFieldGenerator(descriptor, presenceIndex, options);
}
} else {
if (IsWrapperType(descriptor)) {
if (descriptor->real_containing_oneof()) {
return new WrapperOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
return new WrapperFieldGenerator(descriptor, presenceIndex, options);
}
} else {
if (descriptor->real_containing_oneof()) {
return new MessageOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
return new MessageFieldGenerator(descriptor, presenceIndex, options);
}
}
}
case FieldDescriptor::TYPE_ENUM:
if (descriptor->is_repeated()) {
return new RepeatedEnumFieldGenerator(descriptor, presenceIndex, options);
} else {
if (descriptor->real_containing_oneof()) {
return new EnumOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
return new EnumFieldGenerator(descriptor, presenceIndex, options);
}
}
default:
if (descriptor->is_repeated()) {
return new RepeatedPrimitiveFieldGenerator(descriptor, presenceIndex, options);
} else {
if (descriptor->real_containing_oneof()) {
return new PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
return new PrimitiveFieldGenerator(descriptor, presenceIndex, options);
}
}
}
}
bool IsNullable(const FieldDescriptor* descriptor) {
if (descriptor->is_repeated()) {
return true;
}
switch (descriptor->type()) {
case FieldDescriptor::TYPE_ENUM:
case FieldDescriptor::TYPE_DOUBLE:
case FieldDescriptor::TYPE_FLOAT:
case FieldDescriptor::TYPE_INT64:
case FieldDescriptor::TYPE_UINT64:
case FieldDescriptor::TYPE_INT32:
case FieldDescriptor::TYPE_FIXED64:
case FieldDescriptor::TYPE_FIXED32:
case FieldDescriptor::TYPE_BOOL:
case FieldDescriptor::TYPE_UINT32:
case FieldDescriptor::TYPE_SFIXED32:
case FieldDescriptor::TYPE_SFIXED64:
case FieldDescriptor::TYPE_SINT32:
case FieldDescriptor::TYPE_SINT64:
return false;
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_STRING:
case FieldDescriptor::TYPE_BYTES:
return true;
default:
GOOGLE_LOG(FATAL) << "Unknown field type.";
return true;
}
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,195 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
#include <string>
#include <thirdparty/protobuf/port.h>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
struct Options;
class FieldGeneratorBase;
// TODO: start using this enum.
enum CSharpType {
CSHARPTYPE_INT32 = 1,
CSHARPTYPE_INT64 = 2,
CSHARPTYPE_UINT32 = 3,
CSHARPTYPE_UINT64 = 4,
CSHARPTYPE_FLOAT = 5,
CSHARPTYPE_DOUBLE = 6,
CSHARPTYPE_BOOL = 7,
CSHARPTYPE_STRING = 8,
CSHARPTYPE_BYTESTRING = 9,
CSHARPTYPE_MESSAGE = 10,
CSHARPTYPE_ENUM = 11,
MAX_CSHARPTYPE = 11
};
// Converts field type to corresponding C# type.
CSharpType GetCSharpType(FieldDescriptor::Type type);
std::string StripDotProto(const std::string& proto_file);
// Gets unqualified name of the reflection class
std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor);
// Gets unqualified name of the extension class
std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor);
std::string GetClassName(const EnumDescriptor* descriptor);
std::string GetFieldName(const FieldDescriptor* descriptor);
std::string GetFieldConstantName(const FieldDescriptor* field);
std::string GetPropertyName(const FieldDescriptor* descriptor);
int GetFixedSize(FieldDescriptor::Type type);
std::string UnderscoresToCamelCase(const std::string& input,
bool cap_next_letter,
bool preserve_period);
inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter) {
return UnderscoresToCamelCase(input, cap_next_letter, false);
}
std::string UnderscoresToPascalCase(const std::string& input);
// Note that we wouldn't normally want to export this (we're not expecting
// it to be used outside libprotoc itself) but this exposes it for testing.
std::string PROTOC_EXPORT GetEnumValueName(const std::string& enum_name,
const std::string& enum_value_name);
// TODO(jtattermusch): perhaps we could move this to strutil
std::string StringToBase64(const std::string& input);
std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options* options);
std::string GetFullExtensionName(const FieldDescriptor* descriptor);
bool IsNullable(const FieldDescriptor* descriptor);
// Determines whether the given message is a map entry message,
// i.e. one implicitly created by protoc due to a map<key, value> field.
inline bool IsMapEntryMessage(const Descriptor* descriptor) {
return descriptor->options().map_entry();
}
// Checks if this descriptor is for a group and gets its end tag or 0 if it's not a group
uint GetGroupEndTag(const Descriptor* descriptor);
// Determines whether we're generating code for the proto representation of
// descriptors etc, for use in the runtime. This is the only type which is
// allowed to use proto2 syntax, and it generates internal classes.
inline bool IsDescriptorProto(const FileDescriptor* descriptor) {
return descriptor->name() == "google/protobuf/descriptor.proto";
}
// Determines whether the given message is an options message within descriptor.proto.
inline bool IsDescriptorOptionMessage(const Descriptor* descriptor) {
if (!IsDescriptorProto(descriptor->file())) {
return false;
}
const std::string name = descriptor->full_name();
return name == "google.protobuf.FileOptions" ||
name == "google.protobuf.MessageOptions" ||
name == "google.protobuf.FieldOptions" ||
name == "google.protobuf.OneofOptions" ||
name == "google.protobuf.EnumOptions" ||
name == "google.protobuf.EnumValueOptions" ||
name == "google.protobuf.ServiceOptions" ||
name == "google.protobuf.MethodOptions";
}
inline bool IsWrapperType(const FieldDescriptor* descriptor) {
return descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
}
inline bool IsProto2(const FileDescriptor* descriptor) {
return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
}
inline bool SupportsPresenceApi(const FieldDescriptor* descriptor) {
// Unlike most languages, we don't generate Has/Clear members for message
// types, because they can always be set to null in C#. They're not really
// needed for oneof fields in proto2 either, as everything can be done via
// oneof case, but we follow the convention from other languages. Proto3
// oneof fields never have Has/Clear members - but will also never have
// the explicit optional keyword either.
//
// None of the built-in helpers (descriptor->has_presence() etc) describe
// quite the behavior we want, so the rules are explicit below.
if (descriptor->is_repeated() ||
descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
return false;
}
// has_optional_keyword() has more complex rules for proto2, but that
// doesn't matter given the first part of this condition.
return IsProto2(descriptor->file()) || descriptor->has_optional_keyword();
}
inline bool RequiresPresenceBit(const FieldDescriptor* descriptor) {
return SupportsPresenceApi(descriptor) &&
!IsNullable(descriptor) &&
!descriptor->is_extension() &&
!descriptor->real_containing_oneof();
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__

View File

@ -0,0 +1,152 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2015 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_map_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options* options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
}
MapFieldGenerator::~MapFieldGenerator() {
}
void MapFieldGenerator::GenerateMembers(io::Printer* printer) {
const FieldDescriptor* key_descriptor =
descriptor_->message_type()->FindFieldByName("key");
const FieldDescriptor* value_descriptor =
descriptor_->message_type()->FindFieldByName("value");
variables_["key_type_name"] = type_name(key_descriptor);
variables_["value_type_name"] = type_name(value_descriptor);
std::unique_ptr<FieldGeneratorBase> key_generator(
CreateFieldGenerator(key_descriptor, 1, this->options()));
std::unique_ptr<FieldGeneratorBase> value_generator(
CreateFieldGenerator(value_descriptor, 2, this->options()));
printer->Print(
variables_,
"private static readonly pbc::MapField<$key_type_name$, $value_type_name$>.Codec _map_$name$_codec\n"
" = new pbc::MapField<$key_type_name$, $value_type_name$>.Codec(");
key_generator->GenerateCodecCode(printer);
printer->Print(", ");
value_generator->GenerateCodecCode(printer);
printer->Print(
variables_,
", $tag$);\n"
"private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>();\n");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n"
" get { return $name$_; }\n"
"}\n");
}
void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(
variables_,
"$name$_.Add(other.$name$_);\n");
}
void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) {
GenerateParsingCode(printer, true);
}
void MapFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
printer->Print(
variables_,
use_parse_context
? "$name$_.AddEntriesFrom(ref input, _map_$name$_codec);\n"
: "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n");
}
void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
GenerateSerializationCode(printer, true);
}
void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
printer->Print(
variables_,
use_write_context
? "$name$_.WriteTo(ref output, _map_$name$_codec);\n"
: "$name$_.WriteTo(output, _map_$name$_codec);\n");
}
void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"size += $name$_.CalculateSize(_map_$name$_codec);\n");
}
void MapFieldGenerator::WriteHash(io::Printer* printer) {
printer->Print(
variables_,
"hash ^= $property_name$.GetHashCode();\n");
}
void MapFieldGenerator::WriteEquals(io::Printer* printer) {
printer->Print(
variables_,
"if (!$property_name$.Equals(other.$property_name$)) return false;\n");
}
void MapFieldGenerator::WriteToString(io::Printer* printer) {
// TODO: If we ever actually use ToString, we'll need to impleme this...
}
void MapFieldGenerator::GenerateCloningCode(io::Printer* printer) {
printer->Print(variables_,
"$name$_ = other.$name$_.Clone();\n");
}
void MapFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,75 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
#include <string>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_field_base.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
class MapFieldGenerator : public FieldGeneratorBase {
public:
MapFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options* options);
~MapFieldGenerator();
MapFieldGenerator(const MapFieldGenerator&) = delete;
MapFieldGenerator& operator=(const MapFieldGenerator&) = delete;
virtual void GenerateCloningCode(io::Printer* printer) override;
virtual void GenerateFreezingCode(io::Printer* printer) override;
virtual void GenerateMembers(io::Printer* printer) override;
virtual void GenerateMergingCode(io::Printer* printer) override;
virtual void GenerateParsingCode(io::Printer* printer) override;
virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
virtual void GenerateSerializationCode(io::Printer* printer) override;
virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
virtual void WriteHash(io::Printer* printer) override;
virtual void WriteEquals(io::Printer* printer) override;
virtual void WriteToString(io::Printer* printer) override;
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__

View File

@ -0,0 +1,779 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
#include <algorithm>
#include <map>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/wire_format.h>
#include <thirdparty/protobuf/wire_format_lite.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_options.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_enum.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_field_base.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_message.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_names.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
return d1->number() < d2->number();
}
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
const Options* options)
: SourceGeneratorBase(options),
descriptor_(descriptor),
has_bit_field_count_(0),
end_tag_(GetGroupEndTag(descriptor)),
has_extension_ranges_(descriptor->extension_range_count() > 0) {
// fields by number
for (int i = 0; i < descriptor_->field_count(); i++) {
fields_by_number_.push_back(descriptor_->field(i));
}
std::sort(fields_by_number_.begin(), fields_by_number_.end(),
CompareFieldNumbers);
int presence_bit_count = 0;
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (RequiresPresenceBit(field)) {
presence_bit_count++;
if (has_bit_field_count_ == 0 || (presence_bit_count % 32) == 0) {
has_bit_field_count_++;
}
}
}
}
MessageGenerator::~MessageGenerator() {
}
std::string MessageGenerator::class_name() {
return descriptor_->name();
}
std::string MessageGenerator::full_class_name() {
return GetClassName(descriptor_);
}
const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
return fields_by_number_;
}
void MessageGenerator::AddDeprecatedFlag(io::Printer* printer) {
if (descriptor_->options().deprecated()) {
printer->Print("[global::System.ObsoleteAttribute]\n");
}
}
void MessageGenerator::AddSerializableAttribute(io::Printer* printer) {
if (this->options()->serializable) {
printer->Print("[global::System.SerializableAttribute]\n");
}
}
void MessageGenerator::Generate(io::Printer* printer) {
std::map<std::string, std::string> vars;
vars["class_name"] = class_name();
vars["access_level"] = class_access_level();
WriteMessageDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
AddSerializableAttribute(printer);
printer->Print(
vars,
"$access_level$ sealed partial class $class_name$ : ");
if (has_extension_ranges_) {
printer->Print(vars, "pb::IExtendableMessage<$class_name$>\n");
}
else {
printer->Print(vars, "pb::IMessage<$class_name$>\n");
}
printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
printer->Print(" , pb::IBufferMessage\n");
printer->Print("#endif\n");
printer->Print("{\n");
printer->Indent();
// All static fields and properties
printer->Print(
vars,
"private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n");
printer->Print(
"private pb::UnknownFieldSet _unknownFields;\n");
if (has_extension_ranges_) {
if (IsDescriptorProto(descriptor_->file())) {
printer->Print(vars, "internal pb::ExtensionSet<$class_name$> _extensions;\n"); // CustomOptions compatibility
} else {
printer->Print(vars, "private pb::ExtensionSet<$class_name$> _extensions;\n");
}
// a read-only property for fast
// retrieval of the set in IsInitialized
printer->Print(vars,
"private pb::ExtensionSet<$class_name$> _Extensions { get { "
"return _extensions; } }\n");
}
for (int i = 0; i < has_bit_field_count_; i++) {
// don't use arrays since all arrays are heap allocated, saving allocations
// use ints instead of bytes since bytes lack bitwise operators, saving casts
printer->Print("private int _hasBits$i$;\n", "i", StrCat(i));
}
WriteGeneratedCodeAttributes(printer);
printer->Print(
vars,
"public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
// Access the message descriptor via the relevant file descriptor or containing message descriptor.
if (!descriptor_->containing_type()) {
vars["descriptor_accessor"] = GetReflectionClassName(descriptor_->file())
+ ".Descriptor.MessageTypes[" + StrCat(descriptor_->index()) + "]";
} else {
vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
+ ".Descriptor.NestedTypes[" + StrCat(descriptor_->index()) + "]";
}
WriteGeneratedCodeAttributes(printer);
printer->Print(
vars,
"public static pbr::MessageDescriptor Descriptor {\n"
" get { return $descriptor_accessor$; }\n"
"}\n"
"\n");
WriteGeneratedCodeAttributes(printer);
printer->Print(
vars,
"pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
" get { return Descriptor; }\n"
"}\n"
"\n");
// Parameterless constructor and partial OnConstruction method.
WriteGeneratedCodeAttributes(printer);
printer->Print(
vars,
"public $class_name$() {\n"
" OnConstruction();\n"
"}\n\n"
"partial void OnConstruction();\n\n");
GenerateCloningCode(printer);
GenerateFreezingCode(printer);
// Fields/properties
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
// Rats: we lose the debug comment here :(
printer->Print(
"/// <summary>Field number for the \"$field_name$\" field.</summary>\n"
"public const int $field_constant_name$ = $index$;\n",
"field_name", fieldDescriptor->name(),
"field_constant_name", GetFieldConstantName(fieldDescriptor),
"index", StrCat(fieldDescriptor->number()));
std::unique_ptr<FieldGeneratorBase> generator(
CreateFieldGeneratorInternal(fieldDescriptor));
generator->GenerateMembers(printer);
printer->Print("\n");
}
// oneof properties (for real oneofs, which come before synthetic ones)
for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
vars["original_name"] = oneof->name();
printer->Print(
vars,
"private object $name$_;\n"
"/// <summary>Enum of possible cases for the \"$original_name$\" oneof.</summary>\n"
"public enum $property_name$OneofCase {\n");
printer->Indent();
printer->Print("None = 0,\n");
for (int j = 0; j < oneof->field_count(); j++) {
const FieldDescriptor* field = oneof->field(j);
printer->Print("$field_property_name$ = $index$,\n",
"field_property_name", GetPropertyName(field),
"index", StrCat(field->number()));
}
printer->Outdent();
printer->Print("}\n");
// TODO: Should we put the oneof .proto comments here?
// It's unclear exactly where they should go.
printer->Print(
vars,
"private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n");
WriteGeneratedCodeAttributes(printer);
printer->Print(
vars,
"public $property_name$OneofCase $property_name$Case {\n"
" get { return $name$Case_; }\n"
"}\n\n");
WriteGeneratedCodeAttributes(printer);
printer->Print(
vars,
"public void Clear$property_name$() {\n"
" $name$Case_ = $property_name$OneofCase.None;\n"
" $name$_ = null;\n"
"}\n\n");
}
// Standard methods
GenerateFrameworkMethods(printer);
GenerateMessageSerializationMethods(printer);
GenerateMergingMethods(printer);
if (has_extension_ranges_) {
printer->Print(
vars,
"public TValue GetExtension<TValue>(pb::Extension<$class_name$, "
"TValue> extension) {\n"
" return pb::ExtensionSet.Get(ref _extensions, extension);\n"
"}\n"
"public pbc::RepeatedField<TValue> "
"GetExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> "
"extension) {\n"
" return pb::ExtensionSet.Get(ref _extensions, extension);\n"
"}\n"
"public pbc::RepeatedField<TValue> "
"GetOrInitializeExtension<TValue>(pb::RepeatedExtension<$class_name$, "
"TValue> extension) {\n"
" return pb::ExtensionSet.GetOrInitialize(ref _extensions, "
"extension);\n"
"}\n"
"public void SetExtension<TValue>(pb::Extension<$class_name$, TValue> "
"extension, TValue value) {\n"
" pb::ExtensionSet.Set(ref _extensions, extension, value);\n"
"}\n"
"public bool HasExtension<TValue>(pb::Extension<$class_name$, TValue> "
"extension) {\n"
" return pb::ExtensionSet.Has(ref _extensions, extension);\n"
"}\n"
"public void ClearExtension<TValue>(pb::Extension<$class_name$, "
"TValue> extension) {\n"
" pb::ExtensionSet.Clear(ref _extensions, extension);\n"
"}\n"
"public void "
"ClearExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> "
"extension) {\n"
" pb::ExtensionSet.Clear(ref _extensions, extension);\n"
"}\n\n");
}
// Nested messages and enums
if (HasNestedGeneratedTypes()) {
printer->Print(
vars,
"#region Nested types\n"
"/// <summary>Container for nested types declared in the $class_name$ message type.</summary>\n");
WriteGeneratedCodeAttributes(printer);
printer->Print("public static partial class Types {\n");
printer->Indent();
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
EnumGenerator enumGenerator(descriptor_->enum_type(i), this->options());
enumGenerator.Generate(printer);
}
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// Don't generate nested types for maps...
if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
MessageGenerator messageGenerator(
descriptor_->nested_type(i), this->options());
messageGenerator.Generate(printer);
}
}
printer->Outdent();
printer->Print("}\n"
"#endregion\n"
"\n");
}
if (descriptor_->extension_count() > 0) {
printer->Print(
vars,
"#region Extensions\n"
"/// <summary>Container for extensions for other messages declared in the $class_name$ message type.</summary>\n");
WriteGeneratedCodeAttributes(printer);
printer->Print("public static partial class Extensions {\n");
printer->Indent();
for (int i = 0; i < descriptor_->extension_count(); i++) {
std::unique_ptr<FieldGeneratorBase> generator(
CreateFieldGeneratorInternal(descriptor_->extension(i)));
generator->GenerateExtensionCode(printer);
}
printer->Outdent();
printer->Print(
"}\n"
"#endregion\n"
"\n");
}
printer->Outdent();
printer->Print("}\n");
printer->Print("\n");
}
// Helper to work out whether we need to generate a class to hold nested types/enums.
// Only tricky because we don't want to generate map entry types.
bool MessageGenerator::HasNestedGeneratedTypes()
{
if (descriptor_->enum_type_count() > 0) {
return true;
}
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
return true;
}
}
return false;
}
void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
std::map<std::string, std::string> vars;
WriteGeneratedCodeAttributes(printer);
vars["class_name"] = class_name();
printer->Print(
vars,
"public $class_name$($class_name$ other) : this() {\n");
printer->Indent();
for (int i = 0; i < has_bit_field_count_; i++) {
printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", StrCat(i));
}
// Clone non-oneof fields first (treating optional proto3 fields as non-oneof)
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->real_containing_oneof()) {
continue;
}
std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
generator->GenerateCloningCode(printer);
}
// Clone just the right field for each real oneof
for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) {
const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
printer->Print(vars, "switch (other.$property_name$Case) {\n");
printer->Indent();
for (int j = 0; j < oneof->field_count(); j++) {
const FieldDescriptor* field = oneof->field(j);
std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
vars["field_property_name"] = GetPropertyName(field);
printer->Print(
vars,
"case $property_name$OneofCase.$field_property_name$:\n");
printer->Indent();
generator->GenerateCloningCode(printer);
printer->Print("break;\n");
printer->Outdent();
}
printer->Outdent();
printer->Print("}\n\n");
}
// Clone unknown fields
printer->Print(
"_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);\n");
if (has_extension_ranges_) {
printer->Print(
"_extensions = pb::ExtensionSet.Clone(other._extensions);\n");
}
printer->Outdent();
printer->Print("}\n\n");
WriteGeneratedCodeAttributes(printer);
printer->Print(
vars,
"public $class_name$ Clone() {\n"
" return new $class_name$(this);\n"
"}\n\n");
}
void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {
}
void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
std::map<std::string, std::string> vars;
vars["class_name"] = class_name();
// Equality
WriteGeneratedCodeAttributes(printer);
printer->Print(
vars,
"public override bool Equals(object other) {\n"
" return Equals(other as $class_name$);\n"
"}\n\n");
WriteGeneratedCodeAttributes(printer);
printer->Print(
vars,
"public bool Equals($class_name$ other) {\n"
" if (ReferenceEquals(other, null)) {\n"
" return false;\n"
" }\n"
" if (ReferenceEquals(other, this)) {\n"
" return true;\n"
" }\n");
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); i++) {
std::unique_ptr<FieldGeneratorBase> generator(
CreateFieldGeneratorInternal(descriptor_->field(i)));
generator->WriteEquals(printer);
}
for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n",
"property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
}
if (has_extension_ranges_) {
printer->Print(
"if (!Equals(_extensions, other._extensions)) {\n"
" return false;\n"
"}\n");
}
printer->Outdent();
printer->Print(
" return Equals(_unknownFields, other._unknownFields);\n"
"}\n\n");
// GetHashCode
// Start with a non-zero value to easily distinguish between null and "empty" messages.
WriteGeneratedCodeAttributes(printer);
printer->Print(
"public override int GetHashCode() {\n"
" int hash = 1;\n");
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); i++) {
std::unique_ptr<FieldGeneratorBase> generator(
CreateFieldGeneratorInternal(descriptor_->field(i)));
generator->WriteHash(printer);
}
for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
printer->Print("hash ^= (int) $name$Case_;\n",
"name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
}
if (has_extension_ranges_) {
printer->Print(
"if (_extensions != null) {\n"
" hash ^= _extensions.GetHashCode();\n"
"}\n");
}
printer->Print(
"if (_unknownFields != null) {\n"
" hash ^= _unknownFields.GetHashCode();\n"
"}\n"
"return hash;\n");
printer->Outdent();
printer->Print("}\n\n");
WriteGeneratedCodeAttributes(printer);
printer->Print(
"public override string ToString() {\n"
" return pb::JsonFormatter.ToDiagnosticString(this);\n"
"}\n\n");
}
void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) {
WriteGeneratedCodeAttributes(printer);
printer->Print(
"public void WriteTo(pb::CodedOutputStream output) {\n");
printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
printer->Indent();
printer->Print("output.WriteRawMessage(this);\n");
printer->Outdent();
printer->Print("#else\n");
printer->Indent();
GenerateWriteToBody(printer, false);
printer->Outdent();
printer->Print("#endif\n");
printer->Print("}\n\n");
printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
WriteGeneratedCodeAttributes(printer);
printer->Print("void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {\n");
printer->Indent();
GenerateWriteToBody(printer, true);
printer->Outdent();
printer->Print("}\n");
printer->Print("#endif\n\n");
WriteGeneratedCodeAttributes(printer);
printer->Print(
"public int CalculateSize() {\n");
printer->Indent();
printer->Print("int size = 0;\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
std::unique_ptr<FieldGeneratorBase> generator(
CreateFieldGeneratorInternal(descriptor_->field(i)));
generator->GenerateSerializedSizeCode(printer);
}
if (has_extension_ranges_) {
printer->Print(
"if (_extensions != null) {\n"
" size += _extensions.CalculateSize();\n"
"}\n");
}
printer->Print(
"if (_unknownFields != null) {\n"
" size += _unknownFields.CalculateSize();\n"
"}\n");
printer->Print("return size;\n");
printer->Outdent();
printer->Print("}\n\n");
}
void MessageGenerator::GenerateWriteToBody(io::Printer* printer, bool use_write_context) {
// Serialize all the fields
for (int i = 0; i < fields_by_number().size(); i++) {
std::unique_ptr<FieldGeneratorBase> generator(
CreateFieldGeneratorInternal(fields_by_number()[i]));
generator->GenerateSerializationCode(printer, use_write_context);
}
if (has_extension_ranges_) {
// Serialize extensions
printer->Print(
use_write_context
? "if (_extensions != null) {\n"
" _extensions.WriteTo(ref output);\n"
"}\n"
: "if (_extensions != null) {\n"
" _extensions.WriteTo(output);\n"
"}\n");
}
// Serialize unknown fields
printer->Print(
use_write_context
? "if (_unknownFields != null) {\n"
" _unknownFields.WriteTo(ref output);\n"
"}\n"
: "if (_unknownFields != null) {\n"
" _unknownFields.WriteTo(output);\n"
"}\n");
// TODO(jonskeet): Memoize size of frozen messages?
}
void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
// Note: These are separate from GenerateMessageSerializationMethods()
// because they need to be generated even for messages that are optimized
// for code size.
std::map<std::string, std::string> vars;
vars["class_name"] = class_name();
WriteGeneratedCodeAttributes(printer);
printer->Print(
vars,
"public void MergeFrom($class_name$ other) {\n");
printer->Indent();
printer->Print(
"if (other == null) {\n"
" return;\n"
"}\n");
// Merge non-oneof fields, treating optional proto3 fields as normal fields
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->real_containing_oneof()) {
continue;
}
std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
generator->GenerateMergingCode(printer);
}
// Merge oneof fields (for non-synthetic oneofs)
for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) {
const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
printer->Print(vars, "switch (other.$property_name$Case) {\n");
printer->Indent();
for (int j = 0; j < oneof->field_count(); j++) {
const FieldDescriptor* field = oneof->field(j);
vars["field_property_name"] = GetPropertyName(field);
printer->Print(
vars,
"case $property_name$OneofCase.$field_property_name$:\n");
printer->Indent();
std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
generator->GenerateMergingCode(printer);
printer->Print("break;\n");
printer->Outdent();
}
printer->Outdent();
printer->Print("}\n\n");
}
// Merge extensions
if (has_extension_ranges_) {
printer->Print("pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions);\n");
}
// Merge unknown fields.
printer->Print(
"_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);\n");
printer->Outdent();
printer->Print("}\n\n");
WriteGeneratedCodeAttributes(printer);
printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
printer->Indent();
printer->Print("input.ReadRawMessage(this);\n");
printer->Outdent();
printer->Print("#else\n");
printer->Indent();
GenerateMainParseLoop(printer, false);
printer->Outdent();
printer->Print("#endif\n");
printer->Print("}\n\n");
printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
WriteGeneratedCodeAttributes(printer);
printer->Print("void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {\n");
printer->Indent();
GenerateMainParseLoop(printer, true);
printer->Outdent();
printer->Print("}\n"); // method
printer->Print("#endif\n\n");
}
void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, bool use_parse_context) {
std::map<std::string, std::string> vars;
vars["maybe_ref_input"] = use_parse_context ? "ref input" : "input";
printer->Print(
"uint tag;\n"
"while ((tag = input.ReadTag()) != 0) {\n"
" switch(tag) {\n");
printer->Indent();
printer->Indent();
if (end_tag_ != 0) {
printer->Print(
"case $end_tag$:\n"
" return;\n",
"end_tag", StrCat(end_tag_));
}
if (has_extension_ranges_) {
printer->Print(vars,
"default:\n"
" if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, $maybe_ref_input$)) {\n"
" _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, $maybe_ref_input$);\n"
" }\n"
" break;\n");
} else {
printer->Print(vars,
"default:\n"
" _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, $maybe_ref_input$);\n"
" break;\n");
}
for (int i = 0; i < fields_by_number().size(); i++) {
const FieldDescriptor* field = fields_by_number()[i];
internal::WireFormatLite::WireType wt =
internal::WireFormat::WireTypeForFieldType(field->type());
uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt);
// Handle both packed and unpacked repeated fields with the same Read*Array call;
// the two generated cases are the packed and unpacked tags.
// TODO(jonskeet): Check that is_packable is equivalent to
// is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
// It looks like it is...
if (field->is_packable()) {
printer->Print(
"case $packed_tag$:\n",
"packed_tag",
StrCat(
internal::WireFormatLite::MakeTag(
field->number(),
internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
}
printer->Print("case $tag$: {\n", "tag", StrCat(tag));
printer->Indent();
std::unique_ptr<FieldGeneratorBase> generator(
CreateFieldGeneratorInternal(field));
generator->GenerateParsingCode(printer, use_parse_context);
printer->Print("break;\n");
printer->Outdent();
printer->Print("}\n");
}
printer->Outdent();
printer->Print("}\n"); // switch
printer->Outdent();
printer->Print("}\n"); // while
}
// it's a waste of space to track presence for all values, so we only track them if they're not nullable
int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) {
if (!RequiresPresenceBit(descriptor)) {
return -1;
}
int index = 0;
for (int i = 0; i < fields_by_number().size(); i++) {
const FieldDescriptor* field = fields_by_number()[i];
if (field == descriptor) {
return index;
}
if (RequiresPresenceBit(field)) {
index++;
}
}
GOOGLE_LOG(DFATAL)<< "Could not find presence index for field " << descriptor->name();
return -1;
}
FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
const FieldDescriptor* descriptor) {
return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor), this->options());
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,94 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__
#include <string>
#include <vector>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_source_generator_base.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
class FieldGeneratorBase;
class MessageGenerator : public SourceGeneratorBase {
public:
MessageGenerator(const Descriptor* descriptor, const Options* options);
~MessageGenerator();
MessageGenerator(const MessageGenerator&) = delete;
MessageGenerator& operator=(const MessageGenerator&) = delete;
void GenerateCloningCode(io::Printer* printer);
void GenerateFreezingCode(io::Printer* printer);
void GenerateFrameworkMethods(io::Printer* printer);
void Generate(io::Printer* printer);
private:
const Descriptor* descriptor_;
std::vector<const FieldDescriptor*> fields_by_number_;
int has_bit_field_count_;
uint end_tag_;
bool has_extension_ranges_;
void GenerateMessageSerializationMethods(io::Printer* printer);
void GenerateWriteToBody(io::Printer* printer, bool use_write_context);
void GenerateMergingMethods(io::Printer* printer);
void GenerateMainParseLoop(io::Printer* printer, bool use_parse_context);
int GetPresenceIndex(const FieldDescriptor* descriptor);
FieldGeneratorBase* CreateFieldGeneratorInternal(
const FieldDescriptor* descriptor);
bool HasNestedGeneratedTypes();
void AddDeprecatedFlag(io::Printer* printer);
void AddSerializableAttribute(io::Printer* printer);
std::string class_name();
std::string full_class_name();
// field descriptors sorted by number
const std::vector<const FieldDescriptor*>& fields_by_number();
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__

View File

@ -0,0 +1,293 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/wire_format.h>
#include <thirdparty/protobuf/wire_format_lite.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_message_field.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_options.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
if (!SupportsPresenceApi(descriptor_)) {
variables_["has_property_check"] = name() + "_ != null";
variables_["has_not_property_check"] = name() + "_ == null";
}
}
MessageFieldGenerator::~MessageFieldGenerator() {
}
void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"private $type_name$ $name$_;\n");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $name$_; }\n"
" set {\n"
" $name$_ = value;\n"
" }\n"
"}\n");
if (SupportsPresenceApi(descriptor_)) {
printer->Print(
variables_,
"/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $name$_ != null; }\n"
"}\n");
printer->Print(
variables_,
"/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" $name$_ = null;\n"
"}\n");
}
}
void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(
variables_,
"if (other.$has_property_check$) {\n"
" if ($has_not_property_check$) {\n"
" $property_name$ = new $type_name$();\n"
" }\n"
" $property_name$.MergeFrom(other.$property_name$);\n"
"}\n");
}
void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_not_property_check$) {\n"
" $property_name$ = new $type_name$();\n"
"}\n");
if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
printer->Print(variables_, "input.ReadMessage($property_name$);\n");
} else {
printer->Print(variables_, "input.ReadGroup($property_name$);\n");
}
}
void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" output.WriteRawTag($tag_bytes$);\n"
" output.WriteMessage($property_name$);\n"
"}\n");
} else {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" output.WriteRawTag($tag_bytes$);\n"
" output.WriteGroup($property_name$);\n"
" output.WriteRawTag($end_tag_bytes$);\n"
"}\n");
}
}
void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
"}\n");
} else {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" size += $tag_size$ + pb::CodedOutputStream.ComputeGroupSize($property_name$);\n"
"}\n");
}
}
void MessageFieldGenerator::WriteHash(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
}
void MessageFieldGenerator::WriteEquals(io::Printer* printer) {
printer->Print(
variables_,
"if (!object.Equals($property_name$, other.$property_name$)) return false;\n");
}
void MessageFieldGenerator::WriteToString(io::Printer* printer) {
variables_["field_name"] = GetFieldName(descriptor_);
printer->Print(
variables_,
"PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");
}
void MessageFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
" new pb::Extension<$extended_type$, $type_name$>($number$, ");
GenerateCodecCode(printer);
printer->Print(");\n");
}
void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
printer->Print(variables_,
"$name$_ = other.$has_property_check$ ? other.$name$_.Clone() : null;\n");
}
void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
}
void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
printer->Print(
variables_,
"pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
} else {
printer->Print(
variables_,
"pb::FieldCodec.ForGroup($tag$, $end_tag$, $type_name$.Parser)");
}
}
MessageOneofFieldGenerator::MessageOneofFieldGenerator(
const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options)
: MessageFieldGenerator(descriptor, presenceIndex, options) {
SetCommonOneofFieldVariables(&variables_);
}
MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {
}
void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n"
" set {\n"
" $oneof_name$_ = value;\n"
" $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
" }\n"
"}\n");
if (SupportsPresenceApi(descriptor_)) {
printer->Print(
variables_,
"/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
"}\n");
printer->Print(
variables_,
"/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" if ($has_property_check$) {\n"
" Clear$oneof_property_name$();\n"
" }\n"
"}\n");
}
}
void MessageOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(variables_,
"if ($property_name$ == null) {\n"
" $property_name$ = new $type_name$();\n"
"}\n"
"$property_name$.MergeFrom(other.$property_name$);\n");
}
void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
// TODO(jonskeet): We may be able to do better than this
printer->Print(
variables_,
"$type_name$ subBuilder = new $type_name$();\n"
"if ($has_property_check$) {\n"
" subBuilder.MergeFrom($property_name$);\n"
"}\n");
if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
printer->Print("input.ReadMessage(subBuilder);\n");
} else {
printer->Print("input.ReadGroup(subBuilder);\n");
}
printer->Print(variables_, "$property_name$ = subBuilder;\n");
}
void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) {
printer->Print(
variables_,
"PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
}
void MessageOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
printer->Print(variables_,
"$property_name$ = other.$property_name$.Clone();\n");
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,93 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__
#include <string>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_field_base.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
class MessageFieldGenerator : public FieldGeneratorBase {
public:
MessageFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~MessageFieldGenerator();
MessageFieldGenerator(const MessageFieldGenerator&) = delete;
MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete;
virtual void GenerateCodecCode(io::Printer* printer) override;
virtual void GenerateCloningCode(io::Printer* printer) override;
virtual void GenerateFreezingCode(io::Printer* printer) override;
virtual void GenerateMembers(io::Printer* printer) override;
virtual void GenerateMergingCode(io::Printer* printer) override;
virtual void GenerateParsingCode(io::Printer* printer) override;
virtual void GenerateSerializationCode(io::Printer* printer) override;
virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
virtual void GenerateExtensionCode(io::Printer* printer) override;
virtual void WriteHash(io::Printer* printer) override;
virtual void WriteEquals(io::Printer* printer) override;
virtual void WriteToString(io::Printer* printer) override;
};
class MessageOneofFieldGenerator : public MessageFieldGenerator {
public:
MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~MessageOneofFieldGenerator();
MessageOneofFieldGenerator(const MessageOneofFieldGenerator&) = delete;
MessageOneofFieldGenerator& operator=(const MessageOneofFieldGenerator&) =
delete;
virtual void GenerateCloningCode(io::Printer* printer) override;
virtual void GenerateMembers(io::Printer* printer) override;
virtual void GenerateMergingCode(io::Printer* printer) override;
virtual void WriteToString(io::Printer* printer) override;
virtual void GenerateParsingCode(io::Printer* printer) override;
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__

View File

@ -0,0 +1,109 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// Provides a mechanism for mapping a descriptor to the
// fully-qualified name of the corresponding C# class.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
#include <string>
#include <thirdparty/protobuf/port.h>
#include <thirdparty/protobuf/stubs/common.h>
#include <thirdparty/protobuf/port_def.inc>
namespace google {
namespace protobuf {
class Descriptor;
class EnumDescriptor;
class FileDescriptor;
class ServiceDescriptor;
namespace compiler {
namespace csharp {
// Requires:
// descriptor != NULL
//
// Returns:
// The namespace to use for given file descriptor.
std::string PROTOC_EXPORT GetFileNamespace(const FileDescriptor* descriptor);
// Requires:
// descriptor != NULL
//
// Returns:
// The fully-qualified C# class name.
std::string PROTOC_EXPORT GetClassName(const Descriptor* descriptor);
// Requires:
// descriptor != NULL
//
// Returns:
// The fully-qualified name of the C# class that provides
// access to the file descriptor. Proto compiler generates
// such class for each .proto file processed.
std::string PROTOC_EXPORT
GetReflectionClassName(const FileDescriptor* descriptor);
// Generates output file name for given file descriptor. If generate_directories
// is true, the output file will be put under directory corresponding to file's
// namespace. base_namespace can be used to strip some of the top level
// directories. E.g. for file with namespace "Bar.Foo" and base_namespace="Bar",
// the resulting file will be put under directory "Foo" (and not "Bar/Foo").
//
// Requires:
// descriptor != NULL
// error != NULL
//
// Returns:
// The file name to use as output file for given file descriptor. In case
// of failure, this function will return empty string and error parameter
// will contain the error message.
std::string PROTOC_EXPORT GetOutputFile(const FileDescriptor* descriptor,
const std::string file_extension,
const bool generate_directories,
const std::string base_namespace,
std::string* error);
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#include <thirdparty/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__

View File

@ -0,0 +1,81 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
#include <string>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
// Generator options (used by csharp_generator.cc):
struct Options {
Options() :
file_extension(".cs"),
base_namespace(""),
base_namespace_specified(false),
internal_access(false),
serializable(false) {
}
// Extension of the generated file. Defaults to ".cs"
std::string file_extension;
// Base namespace to use to create directory hierarchy. Defaults to "".
// This option allows the simple creation of a conventional C# file layout,
// where directories are created relative to a project-specific base
// namespace. For example, in a project with a base namespace of PetShop, a
// proto of user.proto with a C# namespace of PetShop.Model.Shared would
// generate Model/Shared/User.cs underneath the specified --csharp_out
// directory.
//
// If no base namespace is specified, all files are generated in the
// --csharp_out directory, with no subdirectories created automatically.
std::string base_namespace;
// Whether the base namespace has been explicitly specified by the user.
// This is required as the base namespace can be explicitly set to the empty
// string, meaning "create a full directory hierarchy, starting from the first
// segment of the namespace."
bool base_namespace_specified;
// Whether the generated classes should have accessibility level of "internal".
// Defaults to false that generates "public" classes.
bool internal_access;
// Whether the generated classes should have a global::System.Serializable attribute added
// Defaults to false
bool serializable;
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__

View File

@ -0,0 +1,349 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_options.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_primitive_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
PrimitiveFieldGenerator::PrimitiveFieldGenerator(
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
// TODO(jonskeet): Make this cleaner...
is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
&& descriptor->type() != FieldDescriptor::TYPE_BYTES;
if (!is_value_type && !SupportsPresenceApi(descriptor_)) {
variables_["has_property_check"] = variables_["property_name"] + ".Length != 0";
variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0";
}
}
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {
}
void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
// Note: in multiple places, this code assumes that all fields
// that support presence are either nullable, or use a presence field bit.
// Fields which are oneof members are not generated here; they're generated in PrimitiveOneofFieldGenerator below.
// Extensions are not generated here either.
// Proto2 allows different default values to be specified. These are retained
// via static fields. They don't particularly need to be, but we don't need
// to change that. In Proto3 the default value we don't generate these
// fields, just using the literal instead.
if (IsProto2(descriptor_->file())) {
// Note: "private readonly static" isn't as idiomatic as
// "private static readonly", but changing this now would create a lot of
// churn in generated code with near-to-zero benefit.
printer->Print(
variables_,
"private readonly static $type_name$ $property_name$DefaultValue = $default_value$;\n\n");
variables_["default_value_access"] =
variables_["property_name"] + "DefaultValue";
} else {
variables_["default_value_access"] = variables_["default_value"];
}
// Declare the field itself.
printer->Print(
variables_,
"private $type_name$ $name_def_message$;\n");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
// Most of the work is done in the property:
// Declare the property itself (the same for all options)
printer->Print(variables_, "$access_level$ $type_name$ $property_name$ {\n");
// Specify the "getter", which may need to check for a presence field.
if (SupportsPresenceApi(descriptor_)) {
if (IsNullable(descriptor_)) {
printer->Print(
variables_,
" get { return $name$_ ?? $default_value_access$; }\n");
} else {
printer->Print(
variables_,
// Note: it's possible that this could be rewritten as a
// conditional ?: expression, but there's no significant benefit
// to changing it.
" get { if ($has_field_check$) { return $name$_; } else { return $default_value_access$; } }\n");
}
} else {
printer->Print(
variables_,
" get { return $name$_; }\n");
}
// Specify the "setter", which may need to set a field bit as well as the
// value.
printer->Print(" set {\n");
if (presenceIndex_ != -1) {
printer->Print(
variables_,
" $set_has_field$;\n");
}
if (is_value_type) {
printer->Print(
variables_,
" $name$_ = value;\n");
} else {
printer->Print(
variables_,
" $name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
}
printer->Print(
" }\n"
"}\n");
// The "HasFoo" property, where required.
if (SupportsPresenceApi(descriptor_)) {
printer->Print(variables_,
"/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return ");
if (IsNullable(descriptor_)) {
printer->Print(
variables_,
"$name$_ != null; }\n}\n");
} else {
printer->Print(
variables_,
"$has_field_check$; }\n}\n");
}
}
// The "ClearFoo" method, where required.
if (SupportsPresenceApi(descriptor_)) {
printer->Print(variables_,
"/// <summary>Clears the value of the \"$descriptor_name$\" field</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n");
if (IsNullable(descriptor_)) {
printer->Print(variables_, " $name$_ = null;\n");
} else {
printer->Print(variables_, " $clear_has_field$;\n");
}
printer->Print("}\n");
}
}
void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($other_has_property_check$) {\n"
" $property_name$ = other.$property_name$;\n"
"}\n");
}
void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
// Note: invoke the property setter rather than writing straight to the field,
// so that we can normalize "null to empty" for strings and bytes.
printer->Print(
variables_,
"$property_name$ = input.Read$capitalized_type_name$();\n");
}
void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" output.WriteRawTag($tag_bytes$);\n"
" output.Write$capitalized_type_name$($property_name$);\n"
"}\n");
}
void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n");
printer->Indent();
int fixedSize = GetFixedSize(descriptor_->type());
if (fixedSize == -1) {
printer->Print(
variables_,
"size += $tag_size$ + pb::CodedOutputStream.Compute$capitalized_type_name$Size($property_name$);\n");
} else {
printer->Print(
"size += $tag_size$ + $fixed_size$;\n",
"fixed_size", StrCat(fixedSize),
"tag_size", variables_["tag_size"]);
}
printer->Outdent();
printer->Print("}\n");
}
void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
const char *text = "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n";
if (descriptor_->type() == FieldDescriptor::TYPE_FLOAT) {
text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode($property_name$);\n";
} else if (descriptor_->type() == FieldDescriptor::TYPE_DOUBLE) {
text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode($property_name$);\n";
}
printer->Print(variables_, text);
}
void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
const char *text = "if ($property_name$ != other.$property_name$) return false;\n";
if (descriptor_->type() == FieldDescriptor::TYPE_FLOAT) {
text = "if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
} else if (descriptor_->type() == FieldDescriptor::TYPE_DOUBLE) {
text = "if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
}
printer->Print(variables_, text);
}
void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
printer->Print(
variables_,
"PrintField(\"$descriptor_name$\", $has_property_check$, $property_name$, writer);\n");
}
void PrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) {
printer->Print(variables_,
"$name$_ = other.$name$_;\n");
}
void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) {
printer->Print(
variables_,
"pb::FieldCodec.For$capitalized_type_name$($tag$, $default_value$)");
}
void PrimitiveFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
" new pb::Extension<$extended_type$, $type_name$>($number$, ");
GenerateCodecCode(printer);
printer->Print(");\n");
}
PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: PrimitiveFieldGenerator(descriptor, presenceIndex, options) {
SetCommonOneofFieldVariables(&variables_);
}
PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {
}
void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
" set {\n");
if (is_value_type) {
printer->Print(
variables_,
" $oneof_name$_ = value;\n");
} else {
printer->Print(
variables_,
" $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
}
printer->Print(
variables_,
" $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
" }\n"
"}\n");
if (SupportsPresenceApi(descriptor_)) {
printer->Print(
variables_,
"/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
"}\n");
printer->Print(
variables_,
"/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" if ($has_property_check$) {\n"
" Clear$oneof_property_name$();\n"
" }\n"
"}\n");
}
}
void PrimitiveOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(variables_, "$property_name$ = other.$property_name$;\n");
}
void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) {
printer->Print(variables_,
"PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
}
void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(
variables_,
"$property_name$ = input.Read$capitalized_type_name$();\n");
}
void PrimitiveOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
printer->Print(variables_,
"$property_name$ = other.$property_name$;\n");
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,97 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__
#include <string>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_field_base.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
struct Options;
class PrimitiveFieldGenerator : public FieldGeneratorBase {
public:
PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~PrimitiveFieldGenerator();
PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete;
PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete;
virtual void GenerateCodecCode(io::Printer* printer) override;
virtual void GenerateCloningCode(io::Printer* printer) override;
virtual void GenerateMembers(io::Printer* printer) override;
virtual void GenerateMergingCode(io::Printer* printer) override;
virtual void GenerateParsingCode(io::Printer* printer) override;
virtual void GenerateSerializationCode(io::Printer* printer) override;
virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
virtual void GenerateExtensionCode(io::Printer* printer) override;
virtual void WriteHash(io::Printer* printer) override;
virtual void WriteEquals(io::Printer* printer) override;
virtual void WriteToString(io::Printer* printer) override;
protected:
bool is_value_type;
};
class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
public:
PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
int presenceIndex,
const Options *options);
~PrimitiveOneofFieldGenerator();
PrimitiveOneofFieldGenerator(const PrimitiveOneofFieldGenerator&) = delete;
PrimitiveOneofFieldGenerator& operator=(const PrimitiveOneofFieldGenerator&) =
delete;
virtual void GenerateCloningCode(io::Printer* printer) override;
virtual void GenerateMembers(io::Printer* printer) override;
virtual void GenerateMergingCode(io::Printer* printer) override;
virtual void WriteToString(io::Printer* printer) override;
virtual void GenerateParsingCode(io::Printer* printer) override;
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__

View File

@ -0,0 +1,330 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/stubs/strutil.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_enum.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_field_base.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_message.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_names.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_options.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_reflection_class.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file,
const Options* options)
: SourceGeneratorBase(options),
file_(file) {
namespace_ = GetFileNamespace(file);
reflectionClassname_ = GetReflectionClassUnqualifiedName(file);
extensionClassname_ = GetExtensionClassUnqualifiedName(file);
}
ReflectionClassGenerator::~ReflectionClassGenerator() {
}
void ReflectionClassGenerator::Generate(io::Printer* printer) {
WriteIntroduction(printer);
WriteDescriptor(printer);
// Close the class declaration.
printer->Outdent();
printer->Print("}\n");
if (file_->extension_count() > 0) {
printer->Print(
"/// <summary>Holder for extension identifiers generated from the top "
"level of $file_name$</summary>\n"
"$access_level$ static partial class $class_name$ {\n",
"access_level", class_access_level(), "class_name", extensionClassname_,
"file_name", file_->name());
printer->Indent();
for (int i = 0; i < file_->extension_count(); i++) {
std::unique_ptr<FieldGeneratorBase> generator(
CreateFieldGenerator(file_->extension(i), -1, this->options()));
generator->GenerateExtensionCode(printer);
}
printer->Outdent();
printer->Print(
"}\n"
"\n");
}
// write children: Enums
if (file_->enum_type_count() > 0) {
printer->Print("#region Enums\n");
for (int i = 0; i < file_->enum_type_count(); i++) {
EnumGenerator enumGenerator(file_->enum_type(i), this->options());
enumGenerator.Generate(printer);
}
printer->Print("#endregion\n");
printer->Print("\n");
}
// write children: Messages
if (file_->message_type_count() > 0) {
printer->Print("#region Messages\n");
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator messageGenerator(file_->message_type(i), this->options());
messageGenerator.Generate(printer);
}
printer->Print("#endregion\n");
printer->Print("\n");
}
// TODO(jtattermusch): add insertion point for services.
if (!namespace_.empty()) {
printer->Outdent();
printer->Print("}\n");
}
printer->Print("\n");
printer->Print("#endregion Designer generated code\n");
}
void ReflectionClassGenerator::WriteIntroduction(io::Printer* printer) {
printer->Print(
"// <auto-generated>\n"
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"// source: $file_name$\n"
"// </auto-generated>\n"
"#pragma warning disable 1591, 0612, 3021\n"
"#region Designer generated code\n"
"\n"
"using pb = global::Google.Protobuf;\n"
"using pbc = global::Google.Protobuf.Collections;\n"
"using pbr = global::Google.Protobuf.Reflection;\n"
"using scg = global::System.Collections.Generic;\n",
"file_name", file_->name());
if (!namespace_.empty()) {
printer->Print("namespace $namespace$ {\n", "namespace", namespace_);
printer->Indent();
printer->Print("\n");
}
printer->Print(
"/// <summary>Holder for reflection information generated from $file_name$</summary>\n"
"$access_level$ static partial class $reflection_class_name$ {\n"
"\n",
"file_name", file_->name(),
"access_level", class_access_level(),
"reflection_class_name", reflectionClassname_);
printer->Indent();
}
void ReflectionClassGenerator::WriteDescriptor(io::Printer* printer) {
printer->Print(
"#region Descriptor\n"
"/// <summary>File descriptor for $file_name$</summary>\n"
"public static pbr::FileDescriptor Descriptor {\n"
" get { return descriptor; }\n"
"}\n"
"private static pbr::FileDescriptor descriptor;\n"
"\n"
"static $reflection_class_name$() {\n",
"file_name", file_->name(),
"reflection_class_name", reflectionClassname_);
printer->Indent();
printer->Print(
"byte[] descriptorData = global::System.Convert.FromBase64String(\n");
printer->Indent();
printer->Indent();
printer->Print("string.Concat(\n");
printer->Indent();
// TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
std::string base64 = FileDescriptorToBase64(file_);
while (base64.size() > 60) {
printer->Print("\"$base64$\",\n", "base64", base64.substr(0, 60));
base64 = base64.substr(60);
}
printer->Print("\"$base64$\"));\n", "base64", base64);
printer->Outdent();
printer->Outdent();
printer->Outdent();
// -----------------------------------------------------------------
// Invoke InternalBuildGeneratedFileFrom() to build the file.
printer->Print(
"descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,\n");
printer->Print(" new pbr::FileDescriptor[] { ");
for (int i = 0; i < file_->dependency_count(); i++) {
printer->Print(
"$full_reflection_class_name$.Descriptor, ",
"full_reflection_class_name",
GetReflectionClassName(file_->dependency(i)));
}
printer->Print("},\n"
" new pbr::GeneratedClrTypeInfo(");
// Specify all the generated code information, recursively.
if (file_->enum_type_count() > 0) {
printer->Print("new[] {");
for (int i = 0; i < file_->enum_type_count(); i++) {
printer->Print("typeof($type_name$), ", "type_name", GetClassName(file_->enum_type(i)));
}
printer->Print("}, ");
}
else {
printer->Print("null, ");
}
if (file_->extension_count() > 0) {
std::vector<std::string> extensions;
for (int i = 0; i < file_->extension_count(); i++) {
extensions.push_back(GetFullExtensionName(file_->extension(i)));
}
printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", "));
}
else {
printer->Print("null, ");
}
if (file_->message_type_count() > 0) {
printer->Print("new pbr::GeneratedClrTypeInfo[] {\n");
printer->Indent();
printer->Indent();
printer->Indent();
for (int i = 0; i < file_->message_type_count(); i++) {
WriteGeneratedCodeInfo(file_->message_type(i), printer, i == file_->message_type_count() - 1);
}
printer->Outdent();
printer->Print("\n}));\n");
printer->Outdent();
printer->Outdent();
}
else {
printer->Print("null));\n");
}
printer->Outdent();
printer->Print("}\n");
printer->Print("#endregion\n\n");
}
// Write out the generated code for a particular message. This consists of the CLR type, property names
// corresponding to fields, names corresponding to oneofs, nested enums, and nested types. Each array part
// can be specified as null if it would be empty, to make the generated code somewhat simpler to read.
// We write a line break at the end of each generated code info, so that in the final file we'll see all
// the types, pre-ordered depth first, one per line. The indentation will be slightly unusual,
// in that it will look like a single array when it's actually constructing a tree, but it'll be easy to
// read even with multiple levels of nesting.
// The "last" parameter indicates whether this message descriptor is the last one being printed in this immediate
// context. It governs whether or not a trailing comma and newline is written after the constructor, effectively
// just controlling the formatting in the generated code.
void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last) {
if (IsMapEntryMessage(descriptor)) {
printer->Print("null, ");
return;
}
// Generated message type
printer->Print("new pbr::GeneratedClrTypeInfo(typeof($type_name$), $type_name$.Parser, ", "type_name", GetClassName(descriptor));
// Fields
if (descriptor->field_count() > 0) {
std::vector<std::string> fields;
fields.reserve(descriptor->field_count());
for (int i = 0; i < descriptor->field_count(); i++) {
fields.push_back(GetPropertyName(descriptor->field(i)));
}
printer->Print("new[]{ \"$fields$\" }, ", "fields", Join(fields, "\", \""));
}
else {
printer->Print("null, ");
}
// Oneofs
if (descriptor->oneof_decl_count() > 0) {
std::vector<std::string> oneofs;
oneofs.reserve(descriptor->oneof_decl_count());
for (int i = 0; i < descriptor->oneof_decl_count(); i++) {
oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true));
}
printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", Join(oneofs, "\", \""));
}
else {
printer->Print("null, ");
}
// Nested enums
if (descriptor->enum_type_count() > 0) {
std::vector<std::string> enums;
enums.reserve(descriptor->enum_type_count());
for (int i = 0; i < descriptor->enum_type_count(); i++) {
enums.push_back(GetClassName(descriptor->enum_type(i)));
}
printer->Print("new[]{ typeof($enums$) }, ", "enums", Join(enums, "), typeof("));
}
else {
printer->Print("null, ");
}
// Extensions
if (descriptor->extension_count() > 0) {
std::vector<std::string> extensions;
for (int i = 0; i < descriptor->extension_count(); i++) {
extensions.push_back(GetFullExtensionName(descriptor->extension(i)));
}
printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", "));
}
else {
printer->Print("null, ");
}
// Nested types
if (descriptor->nested_type_count() > 0) {
// Need to specify array type explicitly here, as all elements may be null.
printer->Print("new pbr::GeneratedClrTypeInfo[] { ");
for (int i = 0; i < descriptor->nested_type_count(); i++) {
WriteGeneratedCodeInfo(descriptor->nested_type(i), printer, i == descriptor->nested_type_count() - 1);
}
printer->Print("}");
}
else {
printer->Print("null");
}
printer->Print(last ? ")" : "),\n");
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,75 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REFLECTION_CLASS_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REFLECTION_CLASS_H__
#include <string>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_source_generator_base.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/io/printer.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
class ReflectionClassGenerator : public SourceGeneratorBase {
public:
ReflectionClassGenerator(const FileDescriptor* file, const Options* options);
~ReflectionClassGenerator();
ReflectionClassGenerator(const ReflectionClassGenerator&) = delete;
ReflectionClassGenerator& operator=(const ReflectionClassGenerator&) = delete;
void Generate(io::Printer* printer);
private:
const FileDescriptor* file_;
std::string namespace_;
std::string reflectionClassname_;
std::string extensionClassname_;
void WriteIntroduction(io::Printer* printer);
void WriteDescriptor(io::Printer* printer);
void WriteGeneratedCodeInfo(const Descriptor* descriptor,
io::Printer* printer,
bool last);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REFLECTION_CLASS_H__

View File

@ -0,0 +1,148 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
#include <thirdparty/protobuf/compiler/code_generator.h>
#include <thirdparty/protobuf/descriptor.h>
#include <thirdparty/protobuf/descriptor.pb.h>
#include <thirdparty/protobuf/io/printer.h>
#include <thirdparty/protobuf/io/zero_copy_stream.h>
#include <thirdparty/protobuf/wire_format.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_helpers.h>
#include <thirdparty/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
}
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {
}
void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
" = pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x);\n");
printer->Print(variables_,
"private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
" get { return $name$_; }\n"
"}\n");
}
void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(
variables_,
"$name$_.Add(other.$name$_);\n");
}
void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
GenerateParsingCode(printer, true);
}
void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
printer->Print(
variables_,
use_parse_context
? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"
: "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
}
void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
GenerateSerializationCode(printer, true);
}
void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
printer->Print(
variables_,
use_write_context
? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
: "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
}
void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
}
void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) {
printer->Print(
variables_,
"hash ^= $name$_.GetHashCode();\n");
}
void RepeatedEnumFieldGenerator::WriteEquals(io::Printer* printer) {
printer->Print(
variables_,
"if(!$name$_.Equals(other.$name$_)) return false;\n");
}
void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) {
printer->Print(variables_,
"PrintField(\"$descriptor_name$\", $name$_, writer);\n");
}
void RepeatedEnumFieldGenerator::GenerateCloningCode(io::Printer* printer) {
printer->Print(variables_,
"$name$_ = other.$name$_.Clone();\n");
}
void RepeatedEnumFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ static readonly pb::RepeatedExtension<$extended_type$, $type_name$> $property_name$ =\n"
" new pb::RepeatedExtension<$extended_type$, $type_name$>($number$, "
"pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x));\n");
}
void RepeatedEnumFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

Some files were not shown because too many files have changed in this diff Show More