PROTOBUF_SYNC_PIPER
pull/9030/head
Josh Haberman 3 years ago
commit 624d29d833
  1. 4
      .gitignore
  2. 9
      CHANGES.txt
  3. 6
      WORKSPACE
  4. 8
      cmake/extract_includes.bat.in
  5. 1
      cmake/libprotobuf-lite.cmake
  6. 6
      docs/options.md
  7. 1
      docs/third_party.md
  8. 6
      java/README.md
  9. 2
      java/core/src/main/java/com/google/protobuf/ByteString.java
  10. 50
      java/core/src/main/java/com/google/protobuf/CanIgnoreReturnValue.java
  11. 55
      java/core/src/main/java/com/google/protobuf/CheckReturnValue.java
  12. 331
      java/core/src/main/java/com/google/protobuf/Descriptors.java
  13. 6
      java/core/src/main/java/com/google/protobuf/Utf8.java
  14. 37
      java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
  15. 36
      java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
  16. 33
      java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
  17. 7
      java/core/src/test/java/com/google/protobuf/Utf8Utils.java
  18. 2
      java/core/src/test/proto/com/google/protobuf/map_test.proto
  19. 36
      java/lite/src/test/java/com/google/protobuf/LiteTest.java
  20. 21
      java/pom.xml
  21. 1
      java/util/BUILD
  22. 5
      java/util/pom.xml
  23. 4
      java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
  24. 22
      java/util/src/main/java/com/google/protobuf/util/Timestamps.java
  25. 30
      java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
  26. 4
      kokoro/linux/dockerfile/test/java_stretch/Dockerfile
  27. 2
      objectivec/DevTools/check_version_stamps.sh
  28. 23
      python/google/protobuf/internal/api_implementation.cc
  29. 150
      python/google/protobuf/internal/containers.py
  30. 29
      python/google/protobuf/internal/text_format_test.py
  31. 12
      python/google/protobuf/internal/well_known_types.py
  32. 50
      python/google/protobuf/pyext/descriptor.cc
  33. 24
      python/google/protobuf/pyext/descriptor_containers.cc
  34. 6
      python/google/protobuf/pyext/descriptor_pool.cc
  35. 5
      python/google/protobuf/pyext/extension_dict.cc
  36. 12
      python/google/protobuf/pyext/field.cc
  37. 205
      python/google/protobuf/pyext/map_container.cc
  38. 132
      python/google/protobuf/pyext/message.cc
  39. 11
      python/google/protobuf/pyext/message_factory.cc
  40. 21
      python/google/protobuf/pyext/message_module.cc
  41. 15
      python/google/protobuf/pyext/repeated_composite_container.cc
  42. 35
      python/google/protobuf/pyext/repeated_scalar_container.cc
  43. 14
      python/google/protobuf/pyext/unknown_fields.cc
  44. 1
      src/Makefile.am
  45. 12
      src/google/protobuf/any.pb.h
  46. 40
      src/google/protobuf/api.pb.h
  47. 124
      src/google/protobuf/arena.cc
  48. 7
      src/google/protobuf/arena.h
  49. 142
      src/google/protobuf/arena_impl.h
  50. 6
      src/google/protobuf/arenastring.h
  51. 4
      src/google/protobuf/compiler/command_line_interface.cc
  52. 4
      src/google/protobuf/compiler/cpp/cpp_file.cc
  53. 4
      src/google/protobuf/compiler/cpp/cpp_helpers.cc
  54. 4
      src/google/protobuf/compiler/cpp/cpp_helpers.h
  55. 17
      src/google/protobuf/compiler/cpp/cpp_message.cc
  56. 4
      src/google/protobuf/compiler/cpp/cpp_message_field.cc
  57. 13
      src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc
  58. 6
      src/google/protobuf/compiler/cpp/cpp_service.cc
  59. 5
      src/google/protobuf/compiler/cpp/cpp_string_field.cc
  60. 4
      src/google/protobuf/compiler/java/java_primitive_field.cc
  61. 1
      src/google/protobuf/compiler/objectivec/objectivec_enum.cc
  62. 2
      src/google/protobuf/compiler/objectivec/objectivec_file.cc
  63. 56
      src/google/protobuf/compiler/objectivec/objectivec_generator.cc
  64. 42
      src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
  65. 2
      src/google/protobuf/compiler/objectivec/objectivec_helpers.h
  66. 2
      src/google/protobuf/compiler/parser.cc
  67. 12
      src/google/protobuf/compiler/php/php_generator.cc
  68. 66
      src/google/protobuf/compiler/plugin.pb.h
  69. 5
      src/google/protobuf/compiler/python/python_generator.cc
  70. 231
      src/google/protobuf/descriptor.cc
  71. 32
      src/google/protobuf/descriptor.h
  72. 36
      src/google/protobuf/descriptor.pb.cc
  73. 419
      src/google/protobuf/descriptor.pb.h
  74. 10
      src/google/protobuf/descriptor_unittest.cc
  75. 8
      src/google/protobuf/duration.pb.h
  76. 7
      src/google/protobuf/dynamic_message.cc
  77. 8
      src/google/protobuf/empty.pb.h
  78. 91
      src/google/protobuf/explicitly_constructed.h
  79. 44
      src/google/protobuf/extension_set.cc
  80. 30
      src/google/protobuf/extension_set.h
  81. 8
      src/google/protobuf/field_mask.pb.h
  82. 4
      src/google/protobuf/generated_message_reflection.cc
  83. 3
      src/google/protobuf/generated_message_table_driven_lite.h
  84. 8
      src/google/protobuf/generated_message_util.cc
  85. 4
      src/google/protobuf/implicit_weak_message.h
  86. 6
      src/google/protobuf/inlined_string_field.h
  87. 119
      src/google/protobuf/io/coded_stream.h
  88. 5
      src/google/protobuf/map_entry_lite.h
  89. 23
      src/google/protobuf/message.h
  90. 8
      src/google/protobuf/message_lite.cc
  91. 59
      src/google/protobuf/message_lite.h
  92. 3
      src/google/protobuf/message_unittest.cc
  93. 1
      src/google/protobuf/parse_context.cc
  94. 134
      src/google/protobuf/parse_context.h
  95. 36
      src/google/protobuf/port_def.inc
  96. 2
      src/google/protobuf/port_undef.inc
  97. 6
      src/google/protobuf/reflection_ops.cc
  98. 8
      src/google/protobuf/repeated_field.h
  99. 10
      src/google/protobuf/source_context.pb.h
  100. 30
      src/google/protobuf/struct.pb.h
  101. Some files were not shown because too many files have changed in this diff Show More

4
.gitignore vendored

@ -202,8 +202,8 @@ cmake/.idea
cmake/cmake-build-debug/
# Common build subdirectories.
./.build/
./_build/
.build/
_build/
# Visual Studio 2017
.vs

@ -1,4 +1,7 @@
Unreleased Changes (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
Protocol Compiler
* Make proto2::Message::DiscardUnknownFields() non-virtual
Python
* Removed Python 2.x support.
* Pure python descriptor_pool.AddSerializedFile() will always build the
@ -11,10 +14,16 @@ Unreleased Changes (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
C++
* Generated code now uses the c++11 standard integer types int{32,64}_t and
uint{32,64}_t
* Reduce memory usage of the DescriptorPool type.
Java
* Add @deprecated javadoc for set/get/has methods
* correctly decode \? escape sequence in text protos
* Avoid depending on Objects.requireNonNull() until we can verify that no users are depending on older Android versions.
* disallow null string map values in put and putAll
Kotlin
* Generated Kotlin code is Explicit API mode compatible
Unreleased Changes (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
C++

@ -40,6 +40,7 @@ maven_install(
artifacts = [
"com.google.code.gson:gson:2.8.6",
"com.google.errorprone:error_prone_annotations:2.3.2",
"com.google.j2objc:j2obj_annotations:1.3",
"com.google.guava:guava:30.1.1-jre",
"com.google.truth:truth:1.1.2",
"junit:junit:4.12",
@ -73,6 +74,11 @@ bind(
actual = "@maven//:com_google_errorprone_error_prone_annotations",
)
bind(
name = "j2objc_annotations",
actual = "@maven//:com_google_j2objc_j2objc_annotations",
)
bind(
name = "junit",
actual = "@maven//:junit_junit",

@ -21,15 +21,19 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arena_impl.h" include
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arenastring.h" include\google\protobuf\arenastring.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\code_generator.h" include\google\protobuf\compiler\code_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\command_line_interface.h" include\google\protobuf\compiler\command_line_interface.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_file.h" include\google\protobuf\compiler\cpp\cpp_file.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_generator.h" include\google\protobuf\compiler\cpp\cpp_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_helpers.h" include\google\protobuf\compiler\cpp\cpp_helpers.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_names.h" include\google\protobuf\compiler\cpp\cpp_names.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_doc_comment.h" include\google\protobuf\compiler\csharp\csharp_doc_comment.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_generator.h" include\google\protobuf\compiler\csharp\csharp_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_names.h" include\google\protobuf\compiler\csharp\csharp_names.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_options.h" include\google\protobuf\compiler\csharp\csharp_options.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\importer.h" include\google\protobuf\compiler\importer.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_generator.h" include\google\protobuf\compiler\java\java_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_kotlin_generator.h" include\google\protobuf\compiler\java\java_kotlin_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_names.h" include\google\protobuf\compiler\java\java_names.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\js\js_generator.h" include\google\protobuf\compiler\js\js_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\js\well_known_types_embed.h" include\google\protobuf\compiler\js\well_known_types_embed.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_generator.h" include\google\protobuf\compiler\objectivec\objectivec_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_helpers.h" include\google\protobuf\compiler\objectivec\objectivec_helpers.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\parser.h" include\google\protobuf\compiler\parser.h
@ -53,6 +57,7 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_util.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_bases.h" include\google\protobuf\generated_message_bases.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_reflection.h" include\google\protobuf\generated_message_reflection.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_table_driven.h" include\google\protobuf\generated_message_table_driven.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_table_driven_lite.h" include\google\protobuf\generated_message_table_driven_lite.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_tctable_decl.h" include\google\protobuf\generated_message_tctable_decl.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_tctable_impl.h" include\google\protobuf\generated_message_tctable_impl.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_tctable_impl.inc" include\google\protobuf\generated_message_tctable_impl.inc
@ -89,7 +94,6 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection_ops.h" inc
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field.h" include\google\protobuf\repeated_field.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\service.h" include\google\protobuf\service.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.pb.h" include\google\protobuf\source_context.pb.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\string_member_robber.h" include\google\protobuf\string_member_robber.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.pb.h" include\google\protobuf\struct.pb.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\bytestream.h" include\google\protobuf\stubs\bytestream.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\callback.h" include\google\protobuf\stubs\callback.h

@ -37,6 +37,7 @@ set(libprotobuf_lite_includes
${protobuf_source_dir}/src/google/protobuf/arena.h
${protobuf_source_dir}/src/google/protobuf/arena_impl.h
${protobuf_source_dir}/src/google/protobuf/arenastring.h
${protobuf_source_dir}/src/google/protobuf/explicitly_constructed.h
${protobuf_source_dir}/src/google/protobuf/extension_set.h
${protobuf_source_dir}/src/google/protobuf/extension_set_inl.h
${protobuf_source_dir}/src/google/protobuf/generated_enum_util.h

@ -205,7 +205,7 @@ with info about your project (name and website) so we can add an entry for you.
* Website: https://github.com/envoyproxy/protoc-gen-validate
* Extensions: 1071
1. protokt
1. Protokt
* Website: https://github.com/open-toast/protokt
* Extensions: 1072
@ -288,3 +288,7 @@ with info about your project (name and website) so we can add an entry for you.
1. Container Object Storage Interface (COSI)
* Website: https://github.com/kubernetes-sigs/container-object-storage-interface-spec
* Extension: 1115-1124
1. Protoc-gen-jsonschema
* Website: https://github.com/chrusty/protoc-gen-jsonschema
* Extension: 1125-1129

@ -70,6 +70,7 @@ These are projects we know about implementing Protocol Buffers for other program
* Kotlin: https://github.com/marcoferrer/kroto-plus
* Kotlin: https://github.com/Kotlin/kotlinx.serialization
* Kotlin: https://github.com/ButterCam/sisyphus
* Kotlin: https://github.com/open-toast/protokt
* Lua: http://code.google.com/p/protoc-gen-lua/
* Lua: http://github.com/indygreg/lua-protobuf
* Lua: https://github.com/Neopallium/lua-pb

@ -23,7 +23,7 @@ If you are using Maven, use the following:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.17.3</version>
<version>3.18.0</version>
</dependency>
```
@ -37,7 +37,7 @@ protobuf-java-util package:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.17.3</version>
<version>3.18.0</version>
</dependency>
```
@ -45,7 +45,7 @@ protobuf-java-util package:
If you are using Gradle, add the following to your `build.gradle` file's dependencies:
```
implementation 'com.google.protobuf:protobuf-java:3.17.3'
implementation 'com.google.protobuf:protobuf-java:3.18.0'
```
Again, be sure to check that the version number matches (or is newer than) the version number of protoc that you are using.

@ -73,6 +73,7 @@ import java.util.NoSuchElementException;
* @author carlanton@google.com Carl Haverl
* @author martinrb@google.com Martin Buchholz
*/
@CheckReturnValue
public abstract class ByteString implements Iterable<Byte>, Serializable {
/**
@ -1275,6 +1276,7 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
* @return the length of the range.
* @throws IndexOutOfBoundsException some or all of the range falls outside of the array.
*/
@CanIgnoreReturnValue
static int checkRange(int startIndex, int endIndex, int size) {
final int length = endIndex - startIndex;
if ((startIndex | endIndex | length | (size - endIndex)) < 0) {

@ -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.
package com.google.protobuf;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.CLASS;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Indicates that the return value of the annotated method can be safely ignored.
*
* <p>This is the opposite of {@link CheckReturnValue}. It can be used inside classes or packages
* annotated with {@code @CheckReturnValue} to exempt specific methods from the default.
*/
@Documented
@Target({METHOD, TYPE})
@Retention(CLASS)
@interface CanIgnoreReturnValue {}

@ -0,0 +1,55 @@
// 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.
package com.google.protobuf;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Indicates that the return value of the annotated method must be checked. An error is triggered
* when one of these methods is called but the result is not used.
*
* <p>{@code @CheckReturnValue} may be applied to a class or package to indicate that all methods in
* that class or package must have their return values checked. For convenience, we provide an
* annotation, {@link CanIgnoreReturnValue}, to exempt specific methods or classes from this
* behavior.
*/
@Documented
@Target({METHOD, CONSTRUCTOR, TYPE, PACKAGE})
@Retention(RUNTIME)
@interface CheckReturnValue {}

@ -53,8 +53,9 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -79,6 +80,13 @@ import java.util.logging.Logger;
*/
public final class Descriptors {
private static final Logger logger = Logger.getLogger(Descriptors.class.getName());
private static final int[] EMPTY_INT_ARRAY = new int[0];
private static final Descriptor[] EMPTY_DESCRIPTORS = new Descriptor[0];
private static final FieldDescriptor[] EMPTY_FIELD_DESCRIPTORS = new FieldDescriptor[0];
private static final EnumDescriptor[] EMPTY_ENUM_DESCRIPTORS = new EnumDescriptor[0];
private static final ServiceDescriptor[] EMPTY_SERVICE_DESCRIPTORS = new ServiceDescriptor[0];
private static final OneofDescriptor[] EMPTY_ONEOF_DESCRIPTORS = new OneofDescriptor[0];
/**
* Describes a {@code .proto} file, including everything defined within. That includes, in
* particular, descriptors for all the messages and file descriptors for all other imported {@code
@ -401,8 +409,7 @@ public final class Descriptors {
* except that the {@code FileDescriptorProto} is encoded in protocol buffer wire format.
*/
public static FileDescriptor internalBuildGeneratedFileFrom(
final String[] descriptorDataParts,
final FileDescriptor[] dependencies) {
final String[] descriptorDataParts, final FileDescriptor[] dependencies) {
final byte[] descriptorBytes = latin1Cat(descriptorDataParts);
FileDescriptorProto proto;
@ -434,10 +441,9 @@ public final class Descriptors {
final String[] dependencyClassNames,
final String[] dependencyFileNames,
final InternalDescriptorAssigner descriptorAssigner) {
FileDescriptor[] dependencies = findDescriptors(
descriptorOuterClass, dependencyClassNames, dependencyFileNames);
internalBuildGeneratedFileFrom(
descriptorDataParts, dependencies, descriptorAssigner);
FileDescriptor[] dependencies =
findDescriptors(descriptorOuterClass, dependencyClassNames, dependencyFileNames);
internalBuildGeneratedFileFrom(descriptorDataParts, dependencies, descriptorAssigner);
}
/**
@ -449,8 +455,8 @@ public final class Descriptors {
final Class<?> descriptorOuterClass,
final String[] dependencyClassNames,
final String[] dependencyFileNames) {
FileDescriptor[] dependencies = findDescriptors(
descriptorOuterClass, dependencyClassNames, dependencyFileNames);
FileDescriptor[] dependencies =
findDescriptors(descriptorOuterClass, dependencyClassNames, dependencyFileNames);
return internalBuildGeneratedFileFrom(descriptorDataParts, dependencies);
}
@ -482,7 +488,8 @@ public final class Descriptors {
* "Options" messages defined in descriptor.proto. The callback may also return null to indicate
* that no extensions are used in the descriptor.
*
* This interface is deprecated. Use the return value of internalBuildGeneratedFrom() instead.
* <p>This interface is deprecated. Use the return value of internalBuildGeneratedFrom()
* instead.
*/
@Deprecated
public interface InternalDescriptorAssigner {
@ -533,22 +540,34 @@ public final class Descriptors {
pool.addPackage(getPackage(), this);
messageTypes = new Descriptor[proto.getMessageTypeCount()];
messageTypes =
(proto.getMessageTypeCount() > 0)
? new Descriptor[proto.getMessageTypeCount()]
: EMPTY_DESCRIPTORS;
for (int i = 0; i < proto.getMessageTypeCount(); i++) {
messageTypes[i] = new Descriptor(proto.getMessageType(i), this, null, i);
}
enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
enumTypes =
(proto.getEnumTypeCount() > 0)
? new EnumDescriptor[proto.getEnumTypeCount()]
: EMPTY_ENUM_DESCRIPTORS;
for (int i = 0; i < proto.getEnumTypeCount(); i++) {
enumTypes[i] = new EnumDescriptor(proto.getEnumType(i), this, null, i);
}
services = new ServiceDescriptor[proto.getServiceCount()];
services =
(proto.getServiceCount() > 0)
? new ServiceDescriptor[proto.getServiceCount()]
: EMPTY_SERVICE_DESCRIPTORS;
for (int i = 0; i < proto.getServiceCount(); i++) {
services[i] = new ServiceDescriptor(proto.getService(i), this, i);
}
extensions = new FieldDescriptor[proto.getExtensionCount()];
extensions =
(proto.getExtensionCount() > 0)
? new FieldDescriptor[proto.getExtensionCount()]
: EMPTY_FIELD_DESCRIPTORS;
for (int i = 0; i < proto.getExtensionCount(); i++) {
extensions[i] = new FieldDescriptor(proto.getExtension(i), this, null, i, true);
}
@ -567,9 +586,9 @@ public final class Descriptors {
this.publicDependencies = new FileDescriptor[0];
messageTypes = new Descriptor[] {message};
enumTypes = new EnumDescriptor[0];
services = new ServiceDescriptor[0];
extensions = new FieldDescriptor[0];
enumTypes = EMPTY_ENUM_DESCRIPTORS;
services = EMPTY_SERVICE_DESCRIPTORS;
extensions = EMPTY_FIELD_DESCRIPTORS;
pool.addPackage(packageName, this);
pool.addSymbol(message);
@ -767,7 +786,9 @@ public final class Descriptors {
* @param name The unqualified name of the field (e.g. "foo"). For protocol buffer messages that
* follow <a
* href=https://developers.google.com/protocol-buffers/docs/style#message_and_field_names>Google's
* guidance on naming</a> this will be a snake case string, such as <pre>song_name</pre>.
* guidance on naming</a> this will be a snake case string, such as
* <pre>song_name</pre>
* .
* @return The field's descriptor, or {@code null} if not found.
*/
public FieldDescriptor findFieldByName(final String name) {
@ -786,7 +807,8 @@ public final class Descriptors {
* @return The field's descriptor, or {@code null} if not found.
*/
public FieldDescriptor findFieldByNumber(final int number) {
return file.pool.fieldsByNumber.get(new DescriptorPool.DescriptorIntPair(this, number));
return binarySearch(
fieldsSortedByNumber, fieldsSortedByNumber.length, FieldDescriptor.NUMBER_GETTER, number);
}
/**
@ -827,6 +849,7 @@ public final class Descriptors {
private final Descriptor[] nestedTypes;
private final EnumDescriptor[] enumTypes;
private final FieldDescriptor[] fields;
private final FieldDescriptor[] fieldsSortedByNumber;
private final FieldDescriptor[] extensions;
private final OneofDescriptor[] oneofs;
private final int realOneofCount;
@ -853,11 +876,12 @@ public final class Descriptors {
this.fullName = fullname;
this.containingType = null;
this.nestedTypes = new Descriptor[0];
this.enumTypes = new EnumDescriptor[0];
this.fields = new FieldDescriptor[0];
this.extensions = new FieldDescriptor[0];
this.oneofs = new OneofDescriptor[0];
this.nestedTypes = EMPTY_DESCRIPTORS;
this.enumTypes = EMPTY_ENUM_DESCRIPTORS;
this.fields = EMPTY_FIELD_DESCRIPTORS;
this.fieldsSortedByNumber = EMPTY_FIELD_DESCRIPTORS;
this.extensions = EMPTY_FIELD_DESCRIPTORS;
this.oneofs = EMPTY_ONEOF_DESCRIPTORS;
this.realOneofCount = 0;
// Create a placeholder FileDescriptor to hold this message.
@ -879,27 +903,44 @@ public final class Descriptors {
this.file = file;
containingType = parent;
oneofs = new OneofDescriptor[proto.getOneofDeclCount()];
oneofs =
(proto.getOneofDeclCount() > 0)
? new OneofDescriptor[proto.getOneofDeclCount()]
: EMPTY_ONEOF_DESCRIPTORS;
for (int i = 0; i < proto.getOneofDeclCount(); i++) {
oneofs[i] = new OneofDescriptor(proto.getOneofDecl(i), file, this, i);
}
nestedTypes = new Descriptor[proto.getNestedTypeCount()];
nestedTypes =
(proto.getNestedTypeCount() > 0)
? new Descriptor[proto.getNestedTypeCount()]
: EMPTY_DESCRIPTORS;
for (int i = 0; i < proto.getNestedTypeCount(); i++) {
nestedTypes[i] = new Descriptor(proto.getNestedType(i), file, this, i);
}
enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
enumTypes =
(proto.getEnumTypeCount() > 0)
? new EnumDescriptor[proto.getEnumTypeCount()]
: EMPTY_ENUM_DESCRIPTORS;
for (int i = 0; i < proto.getEnumTypeCount(); i++) {
enumTypes[i] = new EnumDescriptor(proto.getEnumType(i), file, this, i);
}
fields = new FieldDescriptor[proto.getFieldCount()];
fields =
(proto.getFieldCount() > 0)
? new FieldDescriptor[proto.getFieldCount()]
: EMPTY_FIELD_DESCRIPTORS;
for (int i = 0; i < proto.getFieldCount(); i++) {
fields[i] = new FieldDescriptor(proto.getField(i), file, this, i, false);
}
this.fieldsSortedByNumber =
(proto.getFieldCount() > 0) ? fields.clone() : EMPTY_FIELD_DESCRIPTORS;
extensions = new FieldDescriptor[proto.getExtensionCount()];
extensions =
(proto.getExtensionCount() > 0)
? new FieldDescriptor[proto.getExtensionCount()]
: EMPTY_FIELD_DESCRIPTORS;
for (int i = 0; i < proto.getExtensionCount(); i++) {
extensions[i] = new FieldDescriptor(proto.getExtension(i), file, this, i, true);
}
@ -930,18 +971,23 @@ public final class Descriptors {
file.pool.addSymbol(this);
// NOTE: The defined extension ranges are guaranteed to be disjoint.
extensionRangeLowerBounds = new int[proto.getExtensionRangeCount()];
extensionRangeUpperBounds = new int[proto.getExtensionRangeCount()];
int i = 0;
for (final DescriptorProto.ExtensionRange range : proto.getExtensionRangeList()) {
extensionRangeLowerBounds[i] = range.getStart();
extensionRangeUpperBounds[i] = range.getEnd();
i++;
if (proto.getExtensionRangeCount() > 0) {
extensionRangeLowerBounds = new int[proto.getExtensionRangeCount()];
extensionRangeUpperBounds = new int[proto.getExtensionRangeCount()];
int i = 0;
for (final DescriptorProto.ExtensionRange range : proto.getExtensionRangeList()) {
extensionRangeLowerBounds[i] = range.getStart();
extensionRangeUpperBounds[i] = range.getEnd();
i++;
}
// Since the ranges are disjoint, sorting these independently must still produce the correct
// order.
Arrays.sort(extensionRangeLowerBounds);
Arrays.sort(extensionRangeUpperBounds);
} else {
extensionRangeLowerBounds = EMPTY_INT_ARRAY;
extensionRangeUpperBounds = EMPTY_INT_ARRAY;
}
// Since the ranges are disjoint, sorting these independently must still produce the correct
// order.
Arrays.sort(extensionRangeLowerBounds);
Arrays.sort(extensionRangeUpperBounds);
}
/** Look up and cross-link all field types, etc. */
@ -953,12 +999,32 @@ public final class Descriptors {
for (final FieldDescriptor field : fields) {
field.crossLink();
}
Arrays.sort(fieldsSortedByNumber);
validateNoDuplicateFieldNumbers();
for (final FieldDescriptor extension : extensions) {
extension.crossLink();
}
}
private void validateNoDuplicateFieldNumbers() throws DescriptorValidationException {
for (int i = 0; i + 1 < fieldsSortedByNumber.length; i++) {
FieldDescriptor old = fieldsSortedByNumber[i];
FieldDescriptor field = fieldsSortedByNumber[i + 1];
if (old.getNumber() == field.getNumber()) {
throw new DescriptorValidationException(
field,
"Field number "
+ field.getNumber()
+ " has already been used in \""
+ field.getContainingType().getFullName()
+ "\" by field \""
+ old.getName()
+ "\".");
}
}
}
/** See {@link FileDescriptor#setProto}. */
private void setProto(final DescriptorProto proto) {
this.proto = proto;
@ -990,6 +1056,14 @@ public final class Descriptors {
/** Describes a field of a message type. */
public static final class FieldDescriptor extends GenericDescriptor
implements Comparable<FieldDescriptor>, FieldSet.FieldDescriptorLite<FieldDescriptor> {
private static final NumberGetter<FieldDescriptor> NUMBER_GETTER =
new NumberGetter<FieldDescriptor>() {
@Override
public int getNumber(FieldDescriptor fieldDescriptor) {
return fieldDescriptor.getNumber();
}
};
/**
* Get the index of this descriptor within its parent.
*
@ -1029,7 +1103,14 @@ public final class Descriptors {
/** Get the JSON name of this field. */
public String getJsonName() {
return jsonName;
String result = jsonName;
if (result != null) {
return result;
} else if (proto.hasJsonName()) {
return jsonName = proto.getJsonName();
} else {
return jsonName = fieldNameToJsonName(proto.getName());
}
}
/**
@ -1191,7 +1272,7 @@ public final class Descriptors {
* <p>For fields where hasPresence() == true, the return value of msg.hasField() is semantically
* meaningful.
*/
boolean hasPresence() {
public boolean hasPresence() {
if (isRepeated()) {
return false;
}
@ -1276,7 +1357,7 @@ public final class Descriptors {
private FieldDescriptorProto proto;
private final String fullName;
private final String jsonName;
private String jsonName;
private final FileDescriptor file;
private final Descriptor extensionScope;
private final boolean isProto3Optional;
@ -1397,11 +1478,6 @@ public final class Descriptors {
this.proto = proto;
fullName = computeFullName(file, parent, proto.getName());
this.file = file;
if (proto.hasJsonName()) {
jsonName = proto.getJsonName();
} else {
jsonName = fieldNameToJsonName(proto.getName());
}
if (proto.hasType()) {
type = Type.valueOf(proto.getType());
@ -1627,10 +1703,6 @@ public final class Descriptors {
}
}
if (!isExtension()) {
file.pool.addFieldByNumber(this);
}
if (containingType != null && containingType.getOptions().getMessageSetWireFormat()) {
if (isExtension()) {
if (!isOptional() || getType() != Type.MESSAGE) {
@ -1740,7 +1812,8 @@ public final class Descriptors {
*/
@Override
public EnumValueDescriptor findValueByNumber(final int number) {
return file.pool.enumValuesByNumber.get(new DescriptorPool.DescriptorIntPair(this, number));
return binarySearch(
valuesSortedByNumber, distinctNumbers, EnumValueDescriptor.NUMBER_GETTER, number);
}
/**
@ -1789,7 +1862,7 @@ public final class Descriptors {
result = reference.get();
}
if (result == null) {
result = new EnumValueDescriptor(file, this, key);
result = new EnumValueDescriptor(this, key);
unknownValues.put(key, new WeakReference<EnumValueDescriptor>(result));
}
}
@ -1806,7 +1879,9 @@ public final class Descriptors {
private final String fullName;
private final FileDescriptor file;
private final Descriptor containingType;
private EnumValueDescriptor[] values;
private final EnumValueDescriptor[] values;
private final EnumValueDescriptor[] valuesSortedByNumber;
private final int distinctNumbers;
private final WeakHashMap<Integer, WeakReference<EnumValueDescriptor>> unknownValues =
new WeakHashMap<>();
@ -1832,6 +1907,19 @@ public final class Descriptors {
for (int i = 0; i < proto.getValueCount(); i++) {
values[i] = new EnumValueDescriptor(proto.getValue(i), file, this, i);
}
valuesSortedByNumber = values.clone();
Arrays.sort(valuesSortedByNumber, EnumValueDescriptor.BY_NUMBER);
// deduplicate
int j = 0;
for (int i = 1; i < proto.getValueCount(); i++) {
EnumValueDescriptor oldValue = valuesSortedByNumber[j];
EnumValueDescriptor newValue = valuesSortedByNumber[i];
if (oldValue.getNumber() != newValue.getNumber()) {
valuesSortedByNumber[++j] = newValue;
}
}
this.distinctNumbers = j + 1;
Arrays.fill(valuesSortedByNumber, distinctNumbers, proto.getValueCount(), null);
file.pool.addSymbol(this);
}
@ -1855,6 +1943,22 @@ public final class Descriptors {
*/
public static final class EnumValueDescriptor extends GenericDescriptor
implements Internal.EnumLite {
static final Comparator<EnumValueDescriptor> BY_NUMBER =
new Comparator<EnumValueDescriptor>() {
@Override
public int compare(EnumValueDescriptor o1, EnumValueDescriptor o2) {
return Integer.compare(o1.getNumber(), o2.getNumber());
}
};
static final NumberGetter<EnumValueDescriptor> NUMBER_GETTER =
new NumberGetter<EnumValueDescriptor>() {
@Override
public int getNumber(EnumValueDescriptor enumValueDescriptor) {
return enumValueDescriptor.getNumber();
}
};
/**
* Get the index of this descriptor within its parent.
*
@ -1900,7 +2004,7 @@ public final class Descriptors {
/** Get the {@link FileDescriptor} containing this descriptor. */
@Override
public FileDescriptor getFile() {
return file;
return type.file;
}
/** Get the value's enum type. */
@ -1916,7 +2020,6 @@ public final class Descriptors {
private final int index;
private EnumValueDescriptorProto proto;
private final String fullName;
private final FileDescriptor file;
private final EnumDescriptor type;
private EnumValueDescriptor(
@ -1927,24 +2030,20 @@ public final class Descriptors {
throws DescriptorValidationException {
this.index = index;
this.proto = proto;
this.file = file;
type = parent;
fullName = parent.getFullName() + '.' + proto.getName();
file.pool.addSymbol(this);
file.pool.addEnumValueByNumber(this);
}
// Create an unknown enum value.
private EnumValueDescriptor(
final FileDescriptor file, final EnumDescriptor parent, final Integer number) {
private EnumValueDescriptor(final EnumDescriptor parent, final Integer number) {
String name = "UNKNOWN_ENUM_VALUE_" + parent.getName() + "_" + number;
EnumValueDescriptorProto proto =
EnumValueDescriptorProto.newBuilder().setName(name).setNumber(number).build();
this.index = -1;
this.proto = proto;
this.file = file;
this.type = parent;
this.fullName = parent.getFullName() + '.' + proto.getName();
@ -2156,8 +2255,9 @@ public final class Descriptors {
private void crossLink() throws DescriptorValidationException {
final GenericDescriptor input =
file.pool.lookupSymbol(
proto.getInputType(), this, DescriptorPool.SearchFilter.TYPES_ONLY);
getFile()
.pool
.lookupSymbol(proto.getInputType(), this, DescriptorPool.SearchFilter.TYPES_ONLY);
if (!(input instanceof Descriptor)) {
throw new DescriptorValidationException(
this, '\"' + proto.getInputType() + "\" is not a message type.");
@ -2165,8 +2265,9 @@ public final class Descriptors {
inputType = (Descriptor) input;
final GenericDescriptor output =
file.pool.lookupSymbol(
proto.getOutputType(), this, DescriptorPool.SearchFilter.TYPES_ONLY);
getFile()
.pool
.lookupSymbol(proto.getOutputType(), this, DescriptorPool.SearchFilter.TYPES_ONLY);
if (!(output instanceof Descriptor)) {
throw new DescriptorValidationException(
this, '\"' + proto.getOutputType() + "\" is not a message type.");
@ -2288,7 +2389,9 @@ public final class Descriptors {
}
DescriptorPool(final FileDescriptor[] dependencies, boolean allowUnknownDependencies) {
this.dependencies = new HashSet<>();
this.dependencies =
Collections.newSetFromMap(
new IdentityHashMap<FileDescriptor, Boolean>(dependencies.length));
this.allowUnknownDependencies = allowUnknownDependencies;
for (Descriptors.FileDescriptor dependency : dependencies) {
@ -2321,8 +2424,6 @@ public final class Descriptors {
private boolean allowUnknownDependencies;
private final Map<String, GenericDescriptor> descriptorsByName = new HashMap<>();
private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber = new HashMap<>();
private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber = new HashMap<>();
/** Find a generic descriptor by fully-qualified name. */
GenericDescriptor findSymbol(final String fullName) {
@ -2581,68 +2682,6 @@ public final class Descriptors {
}
}
/** A (GenericDescriptor, int) pair, used as a map key. */
private static final class DescriptorIntPair {
private final GenericDescriptor descriptor;
private final int number;
DescriptorIntPair(final GenericDescriptor descriptor, final int number) {
this.descriptor = descriptor;
this.number = number;
}
@Override
public int hashCode() {
return descriptor.hashCode() * ((1 << 16) - 1) + number;
}
@Override
public boolean equals(final Object obj) {
if (!(obj instanceof DescriptorIntPair)) {
return false;
}
final DescriptorIntPair other = (DescriptorIntPair) obj;
return descriptor == other.descriptor && number == other.number;
}
}
/**
* Adds a field to the fieldsByNumber table. Throws an exception if a field with the same
* containing type and number already exists.
*/
void addFieldByNumber(final FieldDescriptor field) throws DescriptorValidationException {
final DescriptorIntPair key =
new DescriptorIntPair(field.getContainingType(), field.getNumber());
final FieldDescriptor old = fieldsByNumber.put(key, field);
if (old != null) {
fieldsByNumber.put(key, old);
throw new DescriptorValidationException(
field,
"Field number "
+ field.getNumber()
+ " has already been used in \""
+ field.getContainingType().getFullName()
+ "\" by field \""
+ old.getName()
+ "\".");
}
}
/**
* Adds an enum value to the enumValuesByNumber table. If an enum value with the same type and
* number already exists, does nothing. (This is allowed; the first value define with the number
* takes precedence.)
*/
void addEnumValueByNumber(final EnumValueDescriptor value) {
final DescriptorIntPair key = new DescriptorIntPair(value.getType(), value.getNumber());
final EnumValueDescriptor old = enumValuesByNumber.put(key, value);
if (old != null) {
enumValuesByNumber.put(key, old);
// Not an error: Multiple enum values may have the same number, but
// we only want the first one in the map.
}
}
/**
* Verifies that the descriptor's name is valid (i.e. it contains only letters, digits, and
* underscores, and does not start with a digit).
@ -2660,9 +2699,10 @@ public final class Descriptors {
// Subsequent characters may be letters, numbers, or digits.
for (int i = 0; i < name.length(); i++) {
final char c = name.charAt(i);
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
|| (c == '_')
|| ('0' <= c && c <= '9' && i > 0)) {
if (('a' <= c && c <= 'z')
|| ('A' <= c && c <= 'Z')
|| (c == '_')
|| ('0' <= c && c <= '9' && i > 0)) {
// Valid
continue;
}
@ -2752,4 +2792,27 @@ public final class Descriptors {
private int fieldCount;
private FieldDescriptor[] fields;
}
private static <T> T binarySearch(T[] array, int size, NumberGetter<T> getter, int number) {
int left = 0;
int right = size - 1;
while (left <= right) {
int mid = (left + right) / 2;
T midValue = array[mid];
int midValueNumber = getter.getNumber(midValue);
if (number < midValueNumber) {
right = mid - 1;
} else if (number > midValueNumber) {
left = mid + 1;
} else {
return midValue;
}
}
return null;
}
private interface NumberGetter<T> {
int getNumber(T t);
}
}

@ -1676,9 +1676,9 @@ final class Utf8 {
}
// Read bytes until 8-byte aligned so that we can read longs in the loop below.
// We do this by ANDing the address with 7 to determine the number of bytes that need to
// be read before we're 8-byte aligned.
final int unaligned = 8 - ((int) address & 7);
// This is equivalent to (8-address) mod 8, the number of bytes we need to read before we're
// 8-byte aligned.
final int unaligned = (int) (-address & 7);
for (int j = unaligned; j > 0; j--) {
if (UnsafeUtil.getByte(address++) < 0) {
return unaligned - j;

@ -65,6 +65,8 @@ import protobuf_unittest.UnittestProto.TestPackedTypes;
import protobuf_unittest.UnittestProto.TestUnpackedTypes;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
@ -1747,6 +1749,41 @@ public class GeneratedMessageTest {
assertThat(message.getPayload().hasOneofNestedMessage()).isTrue();
}
@Test
public void testOneofParseFailurePropagatesUnderlyingException() {
final byte[] bytes = TestOneof2.newBuilder().setFooInt(123).build().toByteArray();
final IOException injectedException = new IOException("oh no");
CodedInputStream failingInputStream =
CodedInputStream.newInstance(
new InputStream() {
boolean first = true;
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (!first) {
throw injectedException;
}
first = false;
System.arraycopy(bytes, 0, b, off, len);
return len;
}
@Override
public int read() {
throw new UnsupportedOperationException();
}
},
bytes.length - 1);
TestOneof2.Builder builder = TestOneof2.newBuilder();
try {
builder.mergeFrom(failingInputStream, ExtensionRegistry.getEmptyRegistry());
assertWithMessage("Expected mergeFrom to fail").fail();
} catch (IOException e) {
assertThat(e).isSameInstanceAs(injectedException);
}
}
@Test
public void testGetRepeatedFieldBuilder() {
Descriptor descriptor = TestAllTypes.getDescriptor();

@ -43,8 +43,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@ -335,8 +335,19 @@ public final class MapForProto2LiteTest {
assertMapValuesSet(destination.build());
}
@Test
public void testPutChecksNullKey() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
try {
builder.putStringToInt32Field(null, 1);
assertWithMessage("expected exception").fail();
} catch (NullPointerException expected) {
}
}
@Test
public void testPutChecksNullKeysAndValues() throws Exception {
public void testPutChecksNullValues() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
try {
@ -806,12 +817,31 @@ public final class MapForProto2LiteTest {
}
}
@Test
public void testPutAllWithNullStringKey() throws Exception {
TestMap.Builder sourceBuilder = TestMap.newBuilder();
// order preserving map used here to help test rollback
Map<Integer, String> data = new LinkedHashMap<>();
data.put(7, "foo");
data.put(null, "bar");
data.put(9, "baz");
try {
sourceBuilder.putAllInt32ToStringField(data);
fail("allowed null string key");
} catch (NullPointerException expected) {
// Verify rollback of previously added values.
// They all go in or none do.
assertThat(sourceBuilder.getInt32ToStringFieldMap()).isEmpty();
}
}
@Test
public void testPutAllWithNullStringValue() throws Exception {
TestMap.Builder sourceBuilder = TestMap.newBuilder();
// order preserving map used here to help test rollback
Map<Integer, String> data = new TreeMap<>();
Map<Integer, String> data = new LinkedHashMap<>();
data.put(7, "foo");
data.put(8, "bar");
data.put(9, null);

@ -51,6 +51,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@ -484,7 +485,7 @@ public class MapForProto2Test {
}
@Test
public void testPutChecksNullKeysAndValues() throws Exception {
public void testPutChecksNullValues() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
try {
@ -516,6 +517,17 @@ public class MapForProto2Test {
}
}
@Test
public void testPutChecksNullKey() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
try {
builder.putStringToInt32Field(null, 1);
assertWithMessage("expected exception").fail();
} catch (NullPointerException expected) {
}
}
@Test
public void testSerializeAndParse() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
@ -1234,6 +1246,25 @@ public class MapForProto2Test {
}
}
@Test
public void testPutAllWithNullStringKey() throws Exception {
TestMap.Builder sourceBuilder = TestMap.newBuilder();
// order preserving map used here to help test rollback
Map<Integer, String> data = new LinkedHashMap<>();
data.put(7, "foo");
data.put(null, "bar");
data.put(9, "baz");
try {
sourceBuilder.putAllInt32ToStringField(data);
fail("allowed null string key");
} catch (NullPointerException expected) {
// Verify rollback of previously added values.
// They all go in or none do.
assertThat(sourceBuilder.getInt32ToStringFieldMap()).isEmpty();
}
}
@Test
public void testPutNullStringValue() throws Exception {
TestMap.Builder sourceBuilder = TestMap.newBuilder();

@ -171,20 +171,19 @@ final class Utf8Utils {
codePoint = rnd.nextInt(distribution[3]);
if (codePoint < distribution[0]) {
// 1 bytes
sb.append(0x7F);
sb.append((char) 0x7F);
} else if (codePoint < distribution[1]) {
// 2 bytes
sb.append(0x7FF);
sb.append((char) 0x7FF);
} else if (codePoint < distribution[2]) {
// 3 bytes
sb.append(MIN_SURROGATE - 1);
sb.append((char) (MIN_SURROGATE - 1));
} else {
// 4 bytes
sb.append(MIN_HIGH_SURROGATE);
sb.append(MIN_LOW_SURROGATE);
}
} while (Utf8Utils.isSurrogate(codePoint));
sb.appendCodePoint(codePoint);
}
strings[i] = sb.toString();
}

@ -30,7 +30,7 @@
syntax = "proto3";
package map_lite_test;
package map_test;
option java_package = "map_test";
option java_outer_classname = "MapTestProto";

@ -55,6 +55,7 @@ import map_lite_test.MapTestProto.TestMap;
import map_lite_test.MapTestProto.TestMap.MessageValue;
import protobuf_unittest.NestedExtensionLite;
import protobuf_unittest.NonNestedExtensionLite;
import protobuf_unittest.UnittestProto.TestOneof2;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
@ -1429,6 +1430,41 @@ public class LiteTest {
assertToStringEquals("oneof_nested_message {\n bb: 2\n cc: 4\n}", result);
}
@Test
public void testMergeFrom_failureWhenReadingValue_propagatesOriginalException() {
final byte[] bytes = TestOneof2.newBuilder().setFooInt(123).build().toByteArray();
final IOException injectedException = new IOException("oh no");
CodedInputStream failingInputStream =
CodedInputStream.newInstance(
new InputStream() {
boolean first = true;
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (!first) {
throw injectedException;
}
first = false;
System.arraycopy(bytes, 0, b, off, len);
return len;
}
@Override
public int read() {
throw new UnsupportedOperationException();
}
},
bytes.length - 1);
TestOneof2.Builder builder = TestOneof2.newBuilder();
try {
builder.mergeFrom(failingInputStream, ExtensionRegistryLite.getEmptyRegistry());
assertWithMessage("Expected mergeFrom to fail").fail();
} catch (IOException e) {
assertThat(e).isSameInstanceAs(injectedException);
}
}
@Test
public void testToStringDefaultInstance() throws Exception {
assertToStringEquals("", TestAllTypesLite.getDefaultInstance());

@ -166,6 +166,27 @@
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.20</version>
<configuration>
<signature>
<groupId>net.sf.androidscents.signature</groupId>
<artifactId>android-api-level-14</artifactId>
<version>4.0_r4</version>
</signature>
</configuration>
<executions>
<execution>
<id>android</id>
<phase>test</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>

@ -12,6 +12,7 @@ java_library(
visibility = ["//visibility:public"],
deps = [
"//external:error_prone_annotations",
"//external:j2objc_annotations",
"//external:gson",
"//external:guava",
"//java/core",

@ -27,6 +27,11 @@
<artifactId>error_prone_annotations</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>com.google.j2objc</groupId>
<artifactId>j2objc-annotations</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>

@ -1558,7 +1558,7 @@ public class JsonFormat {
try {
Timestamp value = Timestamps.parse(json.getAsString());
builder.mergeFrom(value.toByteString());
} catch (ParseException e) {
} catch (ParseException | UnsupportedOperationException e) {
throw new InvalidProtocolBufferException("Failed to parse timestamp: " + json);
}
}
@ -1568,7 +1568,7 @@ public class JsonFormat {
try {
Duration value = Durations.parse(json.getAsString());
builder.mergeFrom(value.toByteString());
} catch (ParseException e) {
} catch (ParseException | UnsupportedOperationException e) {
throw new InvalidProtocolBufferException("Failed to parse duration: " + json);
}
}

@ -38,6 +38,7 @@ import static com.google.common.math.LongMath.checkedSubtract;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.CompileTimeConstant;
import com.google.j2objc.annotations.J2ObjCIncompatible;
import com.google.protobuf.Duration;
import com.google.protobuf.Timestamp;
import java.io.Serializable;
@ -328,6 +329,27 @@ public final class Timestamps {
(int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
}
/**
* Create a Timestamp from a java.util.Date. If the java.util.Date is a java.sql.Timestamp,
* full nanonsecond precision is retained.
*
* @throws IllegalArgumentException if the year is before 1 CE or after 9999 CE
*/
@SuppressWarnings("GoodTime") // this is a legacy conversion API
@J2ObjCIncompatible
public static Timestamp fromDate(Date date) {
if (date instanceof java.sql.Timestamp) {
java.sql.Timestamp sqlTimestamp = (java.sql.Timestamp) date;
long integralSeconds = sqlTimestamp.getTime() / 1000L; // truncate the fractional seconds
return Timestamp.newBuilder()
.setSeconds(integralSeconds)
.setNanos(sqlTimestamp.getNanos())
.build();
} else {
return fromMillis(date.getTime());
}
}
/**
* Convert a Timestamp to the number of milliseconds elapsed from the epoch.
*

@ -821,6 +821,21 @@ public class JsonFormatTest {
assertRoundTripEquals(message);
}
@Test
public void testTimestampMergeError() throws Exception {
final String incorrectTimestampString = "{\"seconds\":1800,\"nanos\":0}";
try {
TestTimestamp.Builder builder = TestTimestamp.newBuilder();
mergeFromJson(String.format("{\"timestamp_value\": %s}", incorrectTimestampString), builder);
assertWithMessage("expected exception").fail();
} catch (InvalidProtocolBufferException e) {
// Exception expected.
assertThat(e)
.hasMessageThat()
.isEqualTo("Failed to parse timestamp: " + incorrectTimestampString);
}
}
@Test
public void testDuration() throws Exception {
TestDuration message =
@ -830,6 +845,21 @@ public class JsonFormatTest {
assertRoundTripEquals(message);
}
@Test
public void testDurationMergeError() throws Exception {
final String incorrectDurationString = "{\"seconds\":10,\"nanos\":500}";
try {
TestDuration.Builder builder = TestDuration.newBuilder();
mergeFromJson(String.format("{\"duration_value\": %s}", incorrectDurationString), builder);
assertWithMessage("expected exception").fail();
} catch (InvalidProtocolBufferException e) {
// Exception expected.
assertThat(e)
.hasMessageThat()
.isEqualTo("Failed to parse duration: " + incorrectDurationString);
}
}
@Test
public void testFieldMask() throws Exception {
TestFieldMask message =

@ -24,7 +24,7 @@ RUN apt-get update && apt-get install -y \
maven \
openjdk-8-jdk \
# Python dependencies
python-setuptools \
python-pip \
python3-setuptools \
python3-pip \
virtualenv \
&& apt-get clean

@ -25,7 +25,7 @@ check_constant() {
# Collect version from generator sources.
local GeneratorVersion=$( \
cat "${GeneratorSrc}" \
| sed -n -e "s:const int32 ${ConstantName} = \([0-9]*\);:\1:p"
| sed -n -e "s:const int32_t ${ConstantName} = \([0-9]*\);:\1:p"
)
if [[ -z "${GeneratorVersion}" ]] ; then
die "Failed to find ${ConstantName} in the generator source (${GeneratorSrc})."

@ -77,7 +77,6 @@ static const char kModuleDocstring[] =
"constants defined in C, such that one can set defaults at compilation\n"
"(e.g. with blaze flag --copt=-DPYTHON_PROTO2_CPP_IMPL_V2).";
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT,
kModuleName,
kModuleDocstring,
@ -87,38 +86,22 @@ static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT,
NULL,
NULL,
NULL};
#define INITFUNC PyInit__api_implementation
#define INITFUNC_ERRORVAL NULL
#else
#define INITFUNC init_api_implementation
#define INITFUNC_ERRORVAL
#endif
extern "C" {
PyMODINIT_FUNC INITFUNC() {
#if PY_MAJOR_VERSION >= 3
PyMODINIT_FUNC PyInit__api_implementation() {
PyObject* module = PyModule_Create(&_module);
#else
PyObject* module = Py_InitModule3(const_cast<char*>(kModuleName), NULL,
const_cast<char*>(kModuleDocstring));
#endif
if (module == NULL) {
return INITFUNC_ERRORVAL;
return NULL;
}
// Adds the module variable "api_version".
if (PyModule_AddIntConstant(module, const_cast<char*>(kImplVersionName),
kImplVersion))
#if PY_MAJOR_VERSION < 3
return;
#else
{
kImplVersion)) {
Py_DECREF(module);
return NULL;
}
return module;
#endif
}
}

@ -42,149 +42,7 @@ are:
__author__ = 'petar@google.com (Petar Petrov)'
import sys
try:
# This fallback applies for all versions of Python before 3.3
import collections.abc as collections_abc
except ImportError:
import collections as collections_abc
if sys.version_info[0] < 3:
# We would use collections_abc.MutableMapping all the time, but in Python 2
# it doesn't define __slots__. This causes two significant problems:
#
# 1. we can't disallow arbitrary attribute assignment, even if our derived
# classes *do* define __slots__.
#
# 2. we can't safely derive a C type from it without __slots__ defined (the
# interpreter expects to find a dict at tp_dictoffset, which we can't
# robustly provide. And we don't want an instance dict anyway.
#
# So this is the Python 2.7 definition of Mapping/MutableMapping functions
# verbatim, except that:
# 1. We declare __slots__.
# 2. We don't declare this as a virtual base class. The classes defined
# in collections_abc are the interesting base classes, not us.
#
# Note: deriving from object is critical. It is the only thing that makes
# this a true type, allowing us to derive from it in C++ cleanly and making
# __slots__ properly disallow arbitrary element assignment.
class Mapping(object):
__slots__ = ()
def get(self, key, default=None):
try:
return self[key]
except KeyError:
return default
def __contains__(self, key):
try:
self[key]
except KeyError:
return False
else:
return True
def iterkeys(self):
return iter(self)
def itervalues(self):
for key in self:
yield self[key]
def iteritems(self):
for key in self:
yield (key, self[key])
def keys(self):
return list(self)
def items(self):
return [(key, self[key]) for key in self]
def values(self):
return [self[key] for key in self]
# Mappings are not hashable by default, but subclasses can change this
__hash__ = None
def __eq__(self, other):
if not isinstance(other, collections_abc.Mapping):
return NotImplemented
return dict(self.items()) == dict(other.items())
def __ne__(self, other):
return not (self == other)
class MutableMapping(Mapping):
__slots__ = ()
__marker = object()
def pop(self, key, default=__marker):
try:
value = self[key]
except KeyError:
if default is self.__marker:
raise
return default
else:
del self[key]
return value
def popitem(self):
try:
key = next(iter(self))
except StopIteration:
raise KeyError
value = self[key]
del self[key]
return key, value
def clear(self):
try:
while True:
self.popitem()
except KeyError:
pass
def update(*args, **kwds):
if len(args) > 2:
raise TypeError("update() takes at most 2 positional "
"arguments ({} given)".format(len(args)))
elif not args:
raise TypeError("update() takes at least 1 argument (0 given)")
self = args[0]
other = args[1] if len(args) >= 2 else ()
if isinstance(other, Mapping):
for key in other:
self[key] = other[key]
elif hasattr(other, "keys"):
for key in other.keys():
self[key] = other[key]
else:
for key, value in other:
self[key] = value
for key, value in kwds.items():
self[key] = value
def setdefault(self, key, default=None):
try:
return self[key]
except KeyError:
self[key] = default
return default
collections_abc.Mapping.register(Mapping)
collections_abc.MutableMapping.register(MutableMapping)
else:
# In Python 3 we can just use MutableMapping directly, because it defines
# __slots__.
MutableMapping = collections_abc.MutableMapping
import collections.abc
class BaseContainer(object):
@ -235,7 +93,7 @@ class BaseContainer(object):
self._values.reverse()
collections_abc.MutableSequence.register(BaseContainer)
collections.abc.MutableSequence.register(BaseContainer)
class RepeatedScalarFieldContainer(BaseContainer):
@ -458,7 +316,7 @@ class RepeatedCompositeFieldContainer(BaseContainer):
return self._values == other._values
class ScalarMap(MutableMapping):
class ScalarMap(collections.abc.MutableMapping):
"""Simple, type-checked, dict-like container for holding repeated scalars."""
@ -548,7 +406,7 @@ class ScalarMap(MutableMapping):
return self._entry_descriptor._concrete_class
class MessageMap(MutableMapping):
class MessageMap(collections.abc.MutableMapping):
"""Simple, type-checked, dict-like container for with submessage values."""

@ -520,6 +520,35 @@ class TextFormatMessageToStringTests(TextFormatBase):
' type: TYPE_INT32\n'
' oneof_index: 0\n'
'}\n'
'field {\n'
' name: "map_field"\n'
' number: 3\n'
' label: LABEL_REPEATED\n'
' type: TYPE_MESSAGE\n'
' type_name: ".protobuf_unittest.TestMessageWithCustomOptions.'
'MapFieldEntry"\n'
' options {\n'
' [protobuf_unittest.field_opt1]: 12345\n'
' }\n'
'}\n'
'nested_type {\n'
' name: "MapFieldEntry"\n'
' field {\n'
' name: "key"\n'
' number: 1\n'
' label: LABEL_OPTIONAL\n'
' type: TYPE_STRING\n'
' }\n'
' field {\n'
' name: "value"\n'
' number: 2\n'
' label: LABEL_OPTIONAL\n'
' type: TYPE_STRING\n'
' }\n'
' options {\n'
' map_entry: true\n'
' }\n'
'}\n'
'enum_type {\n'
' name: "AnEnum"\n'
' value {\n'

@ -41,16 +41,10 @@ This files defines well known classes which need extra maintenance including:
__author__ = 'jieluo@google.com (Jie Luo)'
import calendar
import collections.abc
from datetime import datetime
from datetime import timedelta
try:
# Since python 3
import collections.abc as collections_abc
except ImportError:
# Won't work after python 3.8
import collections as collections_abc
from google.protobuf.descriptor import FieldDescriptor
_TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S'
@ -806,7 +800,7 @@ class Struct(object):
for key, value in dictionary.items():
_SetStructValue(self.fields[key], value)
collections_abc.MutableMapping.register(Struct)
collections.abc.MutableMapping.register(Struct)
class ListValue(object):
@ -852,7 +846,7 @@ class ListValue(object):
list_value.Clear()
return list_value
collections_abc.MutableSequence.register(ListValue)
collections.abc.MutableSequence.register(ListValue)
WKTBASES = {

@ -49,22 +49,12 @@
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#include <google/protobuf/stubs/hash.h>
#if PY_MAJOR_VERSION >= 3
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
#define PyString_Check PyUnicode_Check
#define PyString_InternFromString PyUnicode_InternFromString
#define PyInt_FromLong PyLong_FromLong
#define PyInt_FromSize_t PyLong_FromSize_t
#if PY_VERSION_HEX < 0x03030000
#error "Python 3.0 - 3.2 are not supported."
#endif
#define PyString_AsStringAndSize(ob, charpp, sizep) \
(PyUnicode_Check(ob) ? ((*(charpp) = const_cast<char*>( \
PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \
? -1 \
: 0) \
: PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
#endif
namespace google {
namespace protobuf {
@ -79,7 +69,7 @@ namespace python {
std::unordered_map<const void*, PyObject*>* interned_descriptors;
PyObject* PyString_FromCppString(const std::string& str) {
return PyString_FromStringAndSize(str.c_str(), str.size());
return PyUnicode_FromStringAndSize(str.c_str(), str.size());
}
// Check that the calling Python code is the global scope of a _pb2.py module.
@ -565,8 +555,8 @@ static PyObject* GetExtensionRanges(PyBaseDescriptor *self, void *closure) {
for (int i = 0; i < descriptor->extension_range_count(); i++) {
const Descriptor::ExtensionRange* range = descriptor->extension_range(i);
PyObject* start = PyInt_FromLong(range->start);
PyObject* end = PyInt_FromLong(range->end);
PyObject* start = PyLong_FromLong(range->start);
PyObject* end = PyLong_FromLong(range->end);
PyList_SetItem(range_list, i, PyTuple_Pack(2, start, end));
}
@ -640,7 +630,7 @@ static PyObject* EnumValueName(PyBaseDescriptor *self, PyObject *args) {
}
static PyObject* GetSyntax(PyBaseDescriptor *self, void *closure) {
return PyString_InternFromString(
return PyUnicode_InternFromString(
FileDescriptor::SyntaxName(_GetDescriptor(self)->file()->syntax()));
}
@ -767,23 +757,23 @@ static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
}
static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->type());
return PyLong_FromLong(_GetDescriptor(self)->type());
}
static PyObject* GetCppType(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->cpp_type());
return PyLong_FromLong(_GetDescriptor(self)->cpp_type());
}
static PyObject* GetLabel(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->label());
return PyLong_FromLong(_GetDescriptor(self)->label());
}
static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->number());
return PyLong_FromLong(_GetDescriptor(self)->number());
}
static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->index());
return PyLong_FromLong(_GetDescriptor(self)->index());
}
static PyObject* GetID(PyBaseDescriptor *self, void *closure) {
@ -809,7 +799,7 @@ static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) {
switch (_GetDescriptor(self)->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32: {
int32_t value = _GetDescriptor(self)->default_value_int32();
result = PyInt_FromLong(value);
result = PyLong_FromLong(value);
break;
}
case FieldDescriptor::CPPTYPE_INT64: {
@ -819,7 +809,7 @@ static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) {
}
case FieldDescriptor::CPPTYPE_UINT32: {
uint32_t value = _GetDescriptor(self)->default_value_uint32();
result = PyInt_FromSize_t(value);
result = PyLong_FromSsize_t(value);
break;
}
case FieldDescriptor::CPPTYPE_UINT64: {
@ -850,7 +840,7 @@ static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) {
case FieldDescriptor::CPPTYPE_ENUM: {
const EnumValueDescriptor* value =
_GetDescriptor(self)->default_value_enum();
result = PyInt_FromLong(value->number());
result = PyLong_FromLong(value->number());
break;
}
case FieldDescriptor::CPPTYPE_MESSAGE: {
@ -1222,11 +1212,11 @@ static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
}
static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->number());
return PyLong_FromLong(_GetDescriptor(self)->number());
}
static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->index());
return PyLong_FromLong(_GetDescriptor(self)->index());
}
static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
@ -1418,7 +1408,7 @@ static int SetSerializedOptions(PyFileDescriptor *self, PyObject *value,
}
static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) {
return PyString_InternFromString(
return PyUnicode_InternFromString(
FileDescriptor::SyntaxName(_GetDescriptor(self)->syntax()));
}
@ -1550,7 +1540,7 @@ static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
}
static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->index());
return PyLong_FromLong(_GetDescriptor(self)->index());
}
static PyObject* GetFields(PyBaseDescriptor* self, void *closure) {
@ -1676,7 +1666,7 @@ static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
}
static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->index());
return PyLong_FromLong(_GetDescriptor(self)->index());
}
static PyObject* GetMethods(PyBaseDescriptor* self, void *closure) {
@ -1799,7 +1789,7 @@ static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
}
static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->index());
return PyLong_FromLong(_GetDescriptor(self)->index());
}
static PyObject* GetContainingService(PyBaseDescriptor *self, void *closure) {
@ -1890,7 +1880,7 @@ static bool AddEnumValues(PyTypeObject *type,
const EnumDescriptor* enum_descriptor) {
for (int i = 0; i < enum_descriptor->value_count(); ++i) {
const EnumValueDescriptor* value = enum_descriptor->value(i);
ScopedPyObjectPtr obj(PyInt_FromLong(value->number()));
ScopedPyObjectPtr obj(PyLong_FromLong(value->number()));
if (obj == NULL) {
return false;
}
@ -1903,7 +1893,7 @@ static bool AddEnumValues(PyTypeObject *type,
}
static bool AddIntConstant(PyTypeObject *type, const char* name, int value) {
ScopedPyObjectPtr obj(PyInt_FromLong(value));
ScopedPyObjectPtr obj(PyLong_FromLong(value));
if (PyDict_SetItemString(type->tp_dict, name, obj.get()) < 0) {
return false;
}

@ -57,20 +57,12 @@
#include <google/protobuf/pyext/descriptor.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#if PY_MAJOR_VERSION >= 3
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
#define PyString_FromFormat PyUnicode_FromFormat
#define PyInt_FromLong PyLong_FromLong
#if PY_VERSION_HEX < 0x03030000
#error "Python 3.0 - 3.2 are not supported."
#endif
#define PyString_AsStringAndSize(ob, charpp, sizep) \
(PyUnicode_Check(ob) ? ((*(charpp) = const_cast<char*>( \
PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \
? -1 \
: 0) \
: PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
#endif
namespace google {
namespace protobuf {
@ -232,18 +224,18 @@ static PyObject* _NewKey_ByIndex(PyContainer* self, Py_ssize_t index) {
case PyContainer::KIND_BYNAME:
{
const std::string& name(self->container_def->get_item_name_fn(item));
return PyString_FromStringAndSize(name.c_str(), name.size());
return PyUnicode_FromStringAndSize(name.c_str(), name.size());
}
case PyContainer::KIND_BYCAMELCASENAME:
{
const std::string& name(
self->container_def->get_item_camelcase_name_fn(item));
return PyString_FromStringAndSize(name.c_str(), name.size());
return PyUnicode_FromStringAndSize(name.c_str(), name.size());
}
case PyContainer::KIND_BYNUMBER:
{
int value = self->container_def->get_item_number_fn(item);
return PyInt_FromLong(value);
return PyLong_FromLong(value);
}
default:
PyErr_SetNone(PyExc_NotImplementedError);
@ -320,8 +312,8 @@ static PyObject* ContainerRepr(PyContainer* self) {
kind = "mapping by number";
break;
}
return PyString_FromFormat(
"<%s %s>", self->container_def->mapping_name, kind);
return PyUnicode_FromFormat("<%s %s>", self->container_def->mapping_name,
kind);
}
extern PyTypeObject DescriptorMapping_Type;
@ -678,7 +670,7 @@ static PyObject* Index(PyContainer* self, PyObject* item) {
PyErr_SetNone(PyExc_ValueError);
return NULL;
} else {
return PyInt_FromLong(position);
return PyLong_FromLong(position);
}
}
// Implements "list.__contains__()": is the object in the sequence.
@ -696,9 +688,9 @@ static int SeqContains(PyContainer* self, PyObject* item) {
static PyObject* Count(PyContainer* self, PyObject* item) {
int position = Find(self, item);
if (position < 0) {
return PyInt_FromLong(0);
return PyLong_FromLong(0);
} else {
return PyInt_FromLong(1);
return PyLong_FromLong(1);
}
}

@ -43,18 +43,12 @@
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#include <google/protobuf/stubs/hash.h>
#if PY_MAJOR_VERSION >= 3
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
#if PY_VERSION_HEX < 0x03030000
#error "Python 3.0 - 3.2 are not supported."
#endif
#define PyString_AsStringAndSize(ob, charpp, sizep) \
(PyUnicode_Check(ob) ? ((*(charpp) = const_cast<char*>( \
PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \
? -1 \
: 0) \
: PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
#endif
namespace google {
namespace protobuf {

@ -49,17 +49,12 @@
#include <google/protobuf/pyext/repeated_scalar_container.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#if PY_MAJOR_VERSION >= 3
#if PY_VERSION_HEX < 0x03030000
#error "Python 3.0 - 3.2 are not supported."
#endif
#define PyString_AsStringAndSize(ob, charpp, sizep) \
(PyUnicode_Check(ob) ? ((*(charpp) = const_cast<char*>( \
PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \
? -1 \
: 0) \
: PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
#endif
namespace google {
namespace protobuf {

@ -34,10 +34,6 @@
#include <google/protobuf/pyext/descriptor.h>
#include <google/protobuf/pyext/message.h>
#if PY_MAJOR_VERSION >= 3
#define PyString_FromFormat PyUnicode_FromFormat
#endif
namespace google {
namespace protobuf {
namespace python {
@ -45,8 +41,8 @@ namespace python {
namespace field {
static PyObject* Repr(PyMessageFieldProperty* self) {
return PyString_FromFormat("<field property '%s'>",
self->field_descriptor->full_name().c_str());
return PyUnicode_FromFormat("<field property '%s'>",
self->field_descriptor->full_name().c_str());
}
static PyObject* DescrGet(PyMessageFieldProperty* self, PyObject* obj,
@ -74,8 +70,8 @@ static PyObject* GetDescriptor(PyMessageFieldProperty* self, void* closure) {
}
static PyObject* GetDoc(PyMessageFieldProperty* self, void* closure) {
return PyString_FromFormat("Field %s",
self->field_descriptor->full_name().c_str());
return PyUnicode_FromFormat("Field %s",
self->field_descriptor->full_name().c_str());
}
static PyGetSetDef Getters[] = {

@ -46,11 +46,6 @@
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#include <google/protobuf/stubs/map_util.h>
#if PY_MAJOR_VERSION >= 3
#define PyInt_FromLong PyLong_FromLong
#define PyInt_FromSize_t PyLong_FromSize_t
#endif
namespace google {
namespace protobuf {
namespace python {
@ -177,11 +172,11 @@ static PyObject* MapKeyToPython(MapContainer* self, const MapKey& key) {
self->parent_field_descriptor->message_type()->map_key();
switch (field_descriptor->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
return PyInt_FromLong(key.GetInt32Value());
return PyLong_FromLong(key.GetInt32Value());
case FieldDescriptor::CPPTYPE_INT64:
return PyLong_FromLongLong(key.GetInt64Value());
case FieldDescriptor::CPPTYPE_UINT32:
return PyInt_FromSize_t(key.GetUInt32Value());
return PyLong_FromSize_t(key.GetUInt32Value());
case FieldDescriptor::CPPTYPE_UINT64:
return PyLong_FromUnsignedLongLong(key.GetUInt64Value());
case FieldDescriptor::CPPTYPE_BOOL:
@ -203,11 +198,11 @@ PyObject* MapValueRefToPython(MapContainer* self, const MapValueRef& value) {
self->parent_field_descriptor->message_type()->map_value();
switch (field_descriptor->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
return PyInt_FromLong(value.GetInt32Value());
return PyLong_FromLong(value.GetInt32Value());
case FieldDescriptor::CPPTYPE_INT64:
return PyLong_FromLongLong(value.GetInt64Value());
case FieldDescriptor::CPPTYPE_UINT32:
return PyInt_FromSize_t(value.GetUInt32Value());
return PyLong_FromSize_t(value.GetUInt32Value());
case FieldDescriptor::CPPTYPE_UINT64:
return PyLong_FromUnsignedLongLong(value.GetUInt64Value());
case FieldDescriptor::CPPTYPE_FLOAT:
@ -219,7 +214,7 @@ PyObject* MapValueRefToPython(MapContainer* self, const MapValueRef& value) {
case FieldDescriptor::CPPTYPE_STRING:
return ToStringObject(field_descriptor, value.GetStringValue());
case FieldDescriptor::CPPTYPE_ENUM:
return PyInt_FromLong(value.GetEnumValue());
return PyLong_FromLong(value.GetEnumValue());
default:
PyErr_Format(
PyExc_SystemError, "Couldn't convert type %d to value",
@ -550,73 +545,21 @@ static PyMethodDef ScalarMapMethods[] = {
{NULL, NULL},
};
PyTypeObject *ScalarMapContainer_Type;
#if PY_MAJOR_VERSION >= 3
static PyType_Slot ScalarMapContainer_Type_slots[] = {
{Py_tp_dealloc, (void *)ScalarMapDealloc},
{Py_mp_length, (void *)MapReflectionFriend::Length},
{Py_mp_subscript, (void *)MapReflectionFriend::ScalarMapGetItem},
{Py_mp_ass_subscript, (void *)MapReflectionFriend::ScalarMapSetItem},
{Py_tp_methods, (void *)ScalarMapMethods},
{Py_tp_iter, (void *)MapReflectionFriend::GetIterator},
{Py_tp_repr, (void *)MapReflectionFriend::ScalarMapToStr},
{0, 0},
};
PyType_Spec ScalarMapContainer_Type_spec = {
FULL_MODULE_NAME ".ScalarMapContainer",
sizeof(MapContainer),
0,
Py_TPFLAGS_DEFAULT,
ScalarMapContainer_Type_slots
};
#else
static PyMappingMethods ScalarMapMappingMethods = {
MapReflectionFriend::Length, // mp_length
MapReflectionFriend::ScalarMapGetItem, // mp_subscript
MapReflectionFriend::ScalarMapSetItem, // mp_ass_subscript
};
PyTypeObject _ScalarMapContainer_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
FULL_MODULE_NAME ".ScalarMapContainer", // tp_name
sizeof(MapContainer), // tp_basicsize
0, // tp_itemsize
ScalarMapDealloc, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
MapReflectionFriend::ScalarMapToStr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
&ScalarMapMappingMethods, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
"A scalar map container", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
MapReflectionFriend::GetIterator, // tp_iter
0, // tp_iternext
ScalarMapMethods, // tp_methods
0, // tp_members
0, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
};
#endif
PyTypeObject* ScalarMapContainer_Type;
static PyType_Slot ScalarMapContainer_Type_slots[] = {
{Py_tp_dealloc, (void*)ScalarMapDealloc},
{Py_mp_length, (void*)MapReflectionFriend::Length},
{Py_mp_subscript, (void*)MapReflectionFriend::ScalarMapGetItem},
{Py_mp_ass_subscript, (void*)MapReflectionFriend::ScalarMapSetItem},
{Py_tp_methods, (void*)ScalarMapMethods},
{Py_tp_iter, (void*)MapReflectionFriend::GetIterator},
{Py_tp_repr, (void*)MapReflectionFriend::ScalarMapToStr},
{0, 0},
};
PyType_Spec ScalarMapContainer_Type_spec = {
FULL_MODULE_NAME ".ScalarMapContainer", sizeof(MapContainer), 0,
Py_TPFLAGS_DEFAULT, ScalarMapContainer_Type_slots};
// MessageMap //////////////////////////////////////////////////////////////////
@ -819,72 +762,20 @@ static PyMethodDef MessageMapMethods[] = {
{NULL, NULL},
};
PyTypeObject *MessageMapContainer_Type;
#if PY_MAJOR_VERSION >= 3
static PyType_Slot MessageMapContainer_Type_slots[] = {
{Py_tp_dealloc, (void *)MessageMapDealloc},
{Py_mp_length, (void *)MapReflectionFriend::Length},
{Py_mp_subscript, (void *)MapReflectionFriend::MessageMapGetItem},
{Py_mp_ass_subscript, (void *)MapReflectionFriend::MessageMapSetItem},
{Py_tp_methods, (void *)MessageMapMethods},
{Py_tp_iter, (void *)MapReflectionFriend::GetIterator},
{Py_tp_repr, (void *)MapReflectionFriend::MessageMapToStr},
{0, 0}
};
PyType_Spec MessageMapContainer_Type_spec = {
FULL_MODULE_NAME ".MessageMapContainer",
sizeof(MessageMapContainer),
0,
Py_TPFLAGS_DEFAULT,
MessageMapContainer_Type_slots
};
#else
static PyMappingMethods MessageMapMappingMethods = {
MapReflectionFriend::Length, // mp_length
MapReflectionFriend::MessageMapGetItem, // mp_subscript
MapReflectionFriend::MessageMapSetItem, // mp_ass_subscript
};
PyTypeObject _MessageMapContainer_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
FULL_MODULE_NAME ".MessageMapContainer", // tp_name
sizeof(MessageMapContainer), // tp_basicsize
0, // tp_itemsize
MessageMapDealloc, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
MapReflectionFriend::MessageMapToStr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
&MessageMapMappingMethods, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
"A map container for message", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
MapReflectionFriend::GetIterator, // tp_iter
0, // tp_iternext
MessageMapMethods, // tp_methods
0, // tp_members
0, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
};
#endif
PyTypeObject* MessageMapContainer_Type;
static PyType_Slot MessageMapContainer_Type_slots[] = {
{Py_tp_dealloc, (void*)MessageMapDealloc},
{Py_mp_length, (void*)MapReflectionFriend::Length},
{Py_mp_subscript, (void*)MapReflectionFriend::MessageMapGetItem},
{Py_mp_ass_subscript, (void*)MapReflectionFriend::MessageMapSetItem},
{Py_tp_methods, (void*)MessageMapMethods},
{Py_tp_iter, (void*)MapReflectionFriend::GetIterator},
{Py_tp_repr, (void*)MapReflectionFriend::MessageMapToStr},
{0, 0}};
PyType_Spec MessageMapContainer_Type_spec = {
FULL_MODULE_NAME ".MessageMapContainer", sizeof(MessageMapContainer), 0,
Py_TPFLAGS_DEFAULT, MessageMapContainer_Type_slots};
// MapIterator /////////////////////////////////////////////////////////////////
@ -1001,20 +892,18 @@ PyTypeObject MapIterator_Type = {
bool InitMapContainers() {
// ScalarMapContainer_Type derives from our MutableMapping type.
ScopedPyObjectPtr containers(PyImport_ImportModule(
"google.protobuf.internal.containers"));
if (containers == NULL) {
ScopedPyObjectPtr abc(PyImport_ImportModule("collections.abc"));
if (abc == NULL) {
return false;
}
ScopedPyObjectPtr mutable_mapping(
PyObject_GetAttrString(containers.get(), "MutableMapping"));
PyObject_GetAttrString(abc.get(), "MutableMapping"));
if (mutable_mapping == NULL) {
return false;
}
Py_INCREF(mutable_mapping.get());
#if PY_MAJOR_VERSION >= 3
ScopedPyObjectPtr bases(PyTuple_Pack(1, mutable_mapping.get()));
if (bases == NULL) {
return false;
@ -1022,35 +911,13 @@ bool InitMapContainers() {
ScalarMapContainer_Type = reinterpret_cast<PyTypeObject*>(
PyType_FromSpecWithBases(&ScalarMapContainer_Type_spec, bases.get()));
#else
_ScalarMapContainer_Type.tp_base =
reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
if (PyType_Ready(&_ScalarMapContainer_Type) < 0) {
return false;
}
ScalarMapContainer_Type = &_ScalarMapContainer_Type;
#endif
if (PyType_Ready(&MapIterator_Type) < 0) {
return false;
}
#if PY_MAJOR_VERSION >= 3
MessageMapContainer_Type = reinterpret_cast<PyTypeObject*>(
PyType_FromSpecWithBases(&MessageMapContainer_Type_spec, bases.get()));
#else
Py_INCREF(mutable_mapping.get());
_MessageMapContainer_Type.tp_base =
reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
if (PyType_Ready(&_MessageMapContainer_Type) < 0) {
return false;
}
MessageMapContainer_Type = &_MessageMapContainer_Type;
#endif
return true;
}

@ -77,27 +77,14 @@
#include <google/protobuf/port_def.inc>
// clang-format on
#if PY_MAJOR_VERSION >= 3
#define PyInt_AsLong PyLong_AsLong
#define PyInt_FromLong PyLong_FromLong
#define PyInt_FromSize_t PyLong_FromSize_t
#define PyString_Check PyUnicode_Check
#define PyString_FromString PyUnicode_FromString
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
#define PyString_FromFormat PyUnicode_FromFormat
#if PY_VERSION_HEX < 0x03030000
#error "Python 3.0 - 3.2 are not supported."
#else
#define PyString_AsString(ob) \
(PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob))
#define PyString_AsString(ob) \
(PyUnicode_Check(ob) ? PyUnicode_AsUTF8(ob) : PyBytes_AsString(ob))
#define PyString_AsStringAndSize(ob, charpp, sizep) \
(PyUnicode_Check(ob) ? ((*(charpp) = const_cast<char*>( \
PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \
? -1 \
: 0) \
: PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
#endif
#endif
namespace google {
namespace protobuf {
@ -125,8 +112,6 @@ static PyObject* WKT_classes = NULL;
namespace message_meta {
static int InsertEmptyWeakref(PyTypeObject* base);
namespace {
// Copied over from internal 'google/protobuf/stubs/strutil.h'.
inline void LowerString(std::string* s) {
@ -176,8 +161,8 @@ static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) {
for (int j = 0; j < enum_descriptor->value_count(); ++j) {
const EnumValueDescriptor* enum_value_descriptor =
enum_descriptor->value(j);
ScopedPyObjectPtr value_number(PyInt_FromLong(
enum_value_descriptor->number()));
ScopedPyObjectPtr value_number(
PyLong_FromLong(enum_value_descriptor->number()));
if (value_number == NULL) {
return -1;
}
@ -287,13 +272,6 @@ static PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
}
CMessageClass* newtype = reinterpret_cast<CMessageClass*>(result.get());
// Insert the empty weakref into the base classes.
if (InsertEmptyWeakref(
reinterpret_cast<PyTypeObject*>(PythonMessage_class)) < 0 ||
InsertEmptyWeakref(CMessage_Type) < 0) {
return NULL;
}
// Cache the descriptor, both as Python object and as C++ pointer.
const Descriptor* descriptor =
PyMessageDescriptor_AsDescriptor(py_descriptor);
@ -348,32 +326,6 @@ static int GcClear(PyObject* pself) {
return PyType_Type.tp_clear(pself);
}
// This function inserts and empty weakref at the end of the list of
// subclasses for the main protocol buffer Message class.
//
// This eliminates a O(n^2) behaviour in the internal add_subclass
// routine.
static int InsertEmptyWeakref(PyTypeObject *base_type) {
#if PY_MAJOR_VERSION >= 3
// Python 3.4 has already included the fix for the issue that this
// hack addresses. For further background and the fix please see
// https://bugs.python.org/issue17936.
return 0;
#else
#ifdef Py_DEBUG
// The code below causes all new subclasses to append an entry, which is never
// cleared. This is a small memory leak, which we disable in Py_DEBUG mode
// to have stable refcounting checks.
#else
PyObject *subclasses = base_type->tp_subclasses;
if (subclasses && PyList_CheckExact(subclasses)) {
return PyList_Append(subclasses, kEmptyWeakref);
}
#endif // !Py_DEBUG
return 0;
#endif // PY_MAJOR_VERSION >= 3
}
// The _extensions_by_name dictionary is built on every access.
// TODO(amauryfa): Migrate all users to pool.FindAllExtensions()
static PyObject* GetExtensionsByName(CMessageClass *self, void *closure) {
@ -426,7 +378,7 @@ static PyObject* GetExtensionsByNumber(CMessageClass *self, void *closure) {
if (extension == NULL) {
return NULL;
}
ScopedPyObjectPtr number(PyInt_FromLong(extensions[i]->number()));
ScopedPyObjectPtr number(PyLong_FromLong(extensions[i]->number()));
if (number == NULL) {
return NULL;
}
@ -464,7 +416,7 @@ static PyObject* GetClassAttribute(CMessageClass *self, PyObject* name) {
self->message_descriptor->FindExtensionByLowercaseName(field_name);
}
if (field) {
return PyInt_FromLong(field->number());
return PyLong_FromLong(field->number());
}
}
PyErr_SetObject(PyExc_AttributeError, name);
@ -617,20 +569,6 @@ bool VerifyIntegerCastAndRange(PyObject* arg, ValueType value) {
template <class T>
bool CheckAndGetInteger(PyObject* arg, T* value) {
// The fast path.
#if PY_MAJOR_VERSION < 3
// For the typical case, offer a fast path.
if (PROTOBUF_PREDICT_TRUE(PyInt_Check(arg))) {
long int_result = PyInt_AsLong(arg);
if (PROTOBUF_PREDICT_TRUE(IsValidNumericCast<T>(int_result))) {
*value = static_cast<T>(int_result);
return true;
} else {
OutOfRangeError(arg);
return false;
}
}
#endif
// This effectively defines an integer as "an object that can be cast as
// an integer and can be used as an ordinal number".
// This definition includes everything that implements numbers.Integral
@ -720,7 +658,7 @@ bool CheckAndGetFloat(PyObject* arg, float* value) {
}
bool CheckAndGetBool(PyObject* arg, bool* value) {
long long_value = PyInt_AsLong(arg);
long long_value = PyLong_AsLong(arg); // NOLINT
if (long_value == -1 && PyErr_Occurred()) {
FormatTypeError(arg, "int, long, bool");
return false;
@ -977,7 +915,7 @@ const FieldDescriptor* GetExtensionDescriptor(PyObject* extension) {
// descriptor, otherwise simply return value. Always returns a new reference.
static PyObject* GetIntegerEnumValue(const FieldDescriptor& descriptor,
PyObject* value) {
if (PyString_Check(value) || PyUnicode_Check(value)) {
if (PyUnicode_Check(value)) {
const EnumDescriptor* enum_descriptor = descriptor.enum_type();
if (enum_descriptor == NULL) {
PyErr_SetString(PyExc_TypeError, "not an enum field");
@ -994,7 +932,7 @@ static PyObject* GetIntegerEnumValue(const FieldDescriptor& descriptor,
PyErr_Format(PyExc_ValueError, "unknown enum label \"%s\"", enum_label);
return NULL;
}
return PyInt_FromLong(enum_value_descriptor->number());
return PyLong_FromLong(enum_value_descriptor->number());
}
Py_INCREF(value);
return value;
@ -1016,15 +954,7 @@ int DeleteRepeatedField(
if (PySlice_Check(slice)) {
from = to = step = slice_length = 0;
#if PY_MAJOR_VERSION < 3
PySlice_GetIndicesEx(
reinterpret_cast<PySliceObject*>(slice),
length, &from, &to, &step, &slice_length);
#else
PySlice_GetIndicesEx(
slice,
length, &from, &to, &step, &slice_length);
#endif
PySlice_GetIndicesEx(slice, length, &from, &to, &step, &slice_length);
if (from < to) {
min = from;
max = to - 1;
@ -1121,7 +1051,7 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) {
PyObject* name;
PyObject* value;
while (PyDict_Next(kwargs, &pos, &name, &value)) {
if (!(PyString_Check(name) || PyUnicode_Check(name))) {
if (!(PyUnicode_Check(name))) {
PyErr_SetString(PyExc_ValueError, "Field name must be a string");
return -1;
}
@ -1396,7 +1326,7 @@ PyObject* IsInitialized(CMessage* self, PyObject* args) {
if (initialization_errors == NULL) {
return NULL;
}
ScopedPyObjectPtr extend_name(PyString_FromString("extend"));
ScopedPyObjectPtr extend_name(PyUnicode_FromString("extend"));
if (extend_name == NULL) {
return NULL;
}
@ -1469,16 +1399,10 @@ bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) {
PyObject* HasField(CMessage* self, PyObject* arg) {
char* field_name;
Py_ssize_t size;
#if PY_MAJOR_VERSION < 3
if (PyString_AsStringAndSize(arg, &field_name, &size) < 0) {
return NULL;
}
#else
field_name = const_cast<char*>(PyUnicode_AsUTF8AndSize(arg, &size));
if (!field_name) {
return NULL;
}
#endif
Message* message = self->message;
bool is_in_oneof;
@ -1746,7 +1670,7 @@ static PyObject* InternalSerializeToString(
if (errors == NULL) {
return NULL;
}
ScopedPyObjectPtr comma(PyString_FromString(","));
ScopedPyObjectPtr comma(PyUnicode_FromString(","));
if (comma == NULL) {
return NULL;
}
@ -1872,7 +1796,7 @@ static PyObject* ToStr(CMessage* self) {
PyErr_SetString(PyExc_ValueError, "Unable to convert message to str");
return NULL;
}
return PyString_FromString(output.c_str());
return PyUnicode_FromString(output.c_str());
}
PyObject* MergeFrom(CMessage* self, PyObject* arg) {
@ -2004,9 +1928,9 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
// TODO(jieluo): Raise error and return NULL instead.
// b/27494216
PyErr_Warn(nullptr, "Unexpected end-group tag: Not all data was converted");
return PyInt_FromLong(data.len - ctx.BytesUntilLimit(ptr));
return PyLong_FromLong(data.len - ctx.BytesUntilLimit(ptr));
}
return PyInt_FromLong(data.len);
return PyLong_FromLong(data.len);
}
static PyObject* ParseFromString(CMessage* self, PyObject* arg) {
@ -2071,7 +1995,7 @@ static PyObject* WhichOneof(CMessage* self, PyObject* arg) {
Py_RETURN_NONE;
} else {
const std::string& name = field_in_oneof->name();
return PyString_FromStringAndSize(name.c_str(), name.size());
return PyUnicode_FromStringAndSize(name.c_str(), name.size());
}
}
@ -2171,8 +2095,8 @@ PyObject* FindInitializationErrors(CMessage* self) {
}
for (size_t i = 0; i < errors.size(); ++i) {
const std::string& error = errors[i];
PyObject* error_string = PyString_FromStringAndSize(
error.c_str(), error.length());
PyObject* error_string =
PyUnicode_FromStringAndSize(error.c_str(), error.length());
if (error_string == NULL) {
Py_DECREF(error_list);
return NULL;
@ -2228,7 +2152,7 @@ PyObject* InternalGetScalar(const Message* message,
switch (field_descriptor->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32: {
int32_t value = reflection->GetInt32(*message, field_descriptor);
result = PyInt_FromLong(value);
result = PyLong_FromLong(value);
break;
}
case FieldDescriptor::CPPTYPE_INT64: {
@ -2238,7 +2162,7 @@ PyObject* InternalGetScalar(const Message* message,
}
case FieldDescriptor::CPPTYPE_UINT32: {
uint32_t value = reflection->GetUInt32(*message, field_descriptor);
result = PyInt_FromSize_t(value);
result = PyLong_FromSsize_t(value);
break;
}
case FieldDescriptor::CPPTYPE_UINT64: {
@ -2271,7 +2195,7 @@ PyObject* InternalGetScalar(const Message* message,
case FieldDescriptor::CPPTYPE_ENUM: {
const EnumValueDescriptor* enum_value =
message->GetReflection()->GetEnum(*message, field_descriptor);
result = PyInt_FromLong(enum_value->number());
result = PyLong_FromLong(enum_value->number());
break;
}
default:
@ -2461,7 +2385,7 @@ PyObject* ToUnicode(CMessage* self) {
if (text_format == NULL) {
return NULL;
}
ScopedPyObjectPtr method_name(PyString_FromString("MessageToString"));
ScopedPyObjectPtr method_name(PyUnicode_FromString("MessageToString"));
if (method_name == NULL) {
return NULL;
}
@ -2472,11 +2396,7 @@ PyObject* ToUnicode(CMessage* self) {
if (encoded == NULL) {
return NULL;
}
#if PY_MAJOR_VERSION < 3
PyObject* decoded = PyString_AsDecodedObject(encoded.get(), "utf-8", NULL);
#else
PyObject* decoded = PyUnicode_FromEncodedObject(encoded.get(), "utf-8", NULL);
#endif
if (decoded == NULL) {
return NULL;
}
@ -2966,7 +2886,7 @@ void InitGlobals() {
// TODO(gps): Check all return values in this function for NULL and propagate
// the error (MemoryError) on up to result in an import failure. These should
// also be freed and reset to NULL during finalization.
kDESCRIPTOR = PyString_FromString("DESCRIPTOR");
kDESCRIPTOR = PyUnicode_FromString("DESCRIPTOR");
PyObject *dummy_obj = PySet_New(NULL);
kEmptyWeakref = PyWeakref_NewRef(dummy_obj, NULL);
@ -3035,11 +2955,7 @@ bool InitProto2MessageModule(PyObject *m) {
reinterpret_cast<PyObject*>(&RepeatedCompositeContainer_Type));
// Register them as MutableSequence.
#if PY_MAJOR_VERSION >= 3
ScopedPyObjectPtr collections(PyImport_ImportModule("collections.abc"));
#else
ScopedPyObjectPtr collections(PyImport_ImportModule("collections"));
#endif
if (collections == NULL) {
return false;
}

@ -38,17 +38,12 @@
#include <google/protobuf/pyext/message_factory.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#if PY_MAJOR_VERSION >= 3
#if PY_VERSION_HEX < 0x03030000
#error "Python 3.0 - 3.2 are not supported."
#endif
#define PyString_AsStringAndSize(ob, charpp, sizep) \
(PyUnicode_Check(ob) ? ((*(charpp) = const_cast<char*>( \
#define PyString_AsStringAndSize(ob, charpp, sizep) \
(PyUnicode_Check(ob) ? ((*(charpp) = const_cast<char*>( \
PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \
? -1 \
: 0) \
: PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
#endif
: PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
namespace google {
namespace protobuf {

@ -95,7 +95,6 @@ static PyMethodDef ModuleMethods[] = {
// DO NOT USE: For migration and testing only.
{NULL, NULL}};
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT,
"_message",
module_docstring,
@ -105,27 +104,17 @@ static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT,
NULL,
NULL,
NULL};
#define INITFUNC PyInit__message
#define INITFUNC_ERRORVAL NULL
#else // Python 2
#define INITFUNC init_message
#define INITFUNC_ERRORVAL
#endif
PyMODINIT_FUNC INITFUNC() {
PyMODINIT_FUNC PyInit__message() {
PyObject* m;
#if PY_MAJOR_VERSION >= 3
m = PyModule_Create(&_module);
#else
m = Py_InitModule3("_message", ModuleMethods, module_docstring);
#endif
if (m == NULL) {
return INITFUNC_ERRORVAL;
return NULL;
}
if (!google::protobuf::python::InitProto2MessageModule(m)) {
Py_DECREF(m);
return INITFUNC_ERRORVAL;
return NULL;
}
// Adds the C++ API
@ -137,10 +126,8 @@ PyMODINIT_FUNC INITFUNC() {
})) {
PyModule_AddObject(m, "proto_API", api);
} else {
return INITFUNC_ERRORVAL;
return NULL;
}
#if PY_MAJOR_VERSION >= 3
return m;
#endif
}

@ -48,12 +48,6 @@
#include <google/protobuf/reflection.h>
#include <google/protobuf/stubs/map_util.h>
#if PY_MAJOR_VERSION >= 3
#define PyInt_Check PyLong_Check
#define PyInt_AsLong PyLong_AsLong
#define PyInt_FromLong PyLong_FromLong
#endif
namespace google {
namespace protobuf {
namespace python {
@ -246,13 +240,8 @@ PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* item) {
Py_ssize_t from, to, step, slicelength, cur, i;
PyObject* result;
#if PY_MAJOR_VERSION >= 3
if (PySlice_GetIndicesEx(item,
length, &from, &to, &step, &slicelength) == -1) {
#else
if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(item),
length, &from, &to, &step, &slicelength) == -1) {
#endif
if (PySlice_GetIndicesEx(item, length, &from, &to, &step, &slicelength) ==
-1) {
return nullptr;
}

@ -46,15 +46,8 @@
#include <google/protobuf/pyext/message.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#if PY_MAJOR_VERSION >= 3
#define PyInt_FromLong PyLong_FromLong
#if PY_VERSION_HEX < 0x03030000
#error "Python 3.0 - 3.2 are not supported."
#else
#define PyString_AsString(ob) \
(PyUnicode_Check(ob) ? PyUnicode_AsUTF8(ob) : PyBytes_AsString(ob))
#endif
#endif
namespace google {
namespace protobuf {
@ -210,7 +203,7 @@ static PyObject* Item(PyObject* pself, Py_ssize_t index) {
case FieldDescriptor::CPPTYPE_INT32: {
int32_t value =
reflection->GetRepeatedInt32(*message, field_descriptor, index);
result = PyInt_FromLong(value);
result = PyLong_FromLong(value);
break;
}
case FieldDescriptor::CPPTYPE_INT64: {
@ -253,7 +246,7 @@ static PyObject* Item(PyObject* pself, Py_ssize_t index) {
const EnumValueDescriptor* enum_value =
message->GetReflection()->GetRepeatedEnum(*message, field_descriptor,
index);
result = PyInt_FromLong(enum_value->number());
result = PyLong_FromLong(enum_value->number());
break;
}
case FieldDescriptor::CPPTYPE_STRING: {
@ -279,22 +272,12 @@ static PyObject* Subscript(PyObject* pself, PyObject* slice) {
Py_ssize_t length;
Py_ssize_t slicelength;
bool return_list = false;
#if PY_MAJOR_VERSION < 3
if (PyInt_Check(slice)) {
from = to = PyInt_AsLong(slice);
} else // NOLINT
#endif
if (PyLong_Check(slice)) {
if (PyLong_Check(slice)) {
from = to = PyLong_AsLong(slice);
} else if (PySlice_Check(slice)) {
length = Len(pself);
#if PY_MAJOR_VERSION >= 3
if (PySlice_GetIndicesEx(slice, length, &from, &to, &step, &slicelength) ==
-1) {
#else
if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), length,
&from, &to, &step, &slicelength) == -1) {
#endif
return nullptr;
}
return_list = true;
@ -436,23 +419,13 @@ static int AssSubscript(PyObject* pself, PyObject* slice, PyObject* value) {
Message* message = self->parent->message;
const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
#if PY_MAJOR_VERSION < 3
if (PyInt_Check(slice)) {
from = to = PyInt_AsLong(slice);
} else // NOLINT
#endif
if (PyLong_Check(slice)) {
if (PyLong_Check(slice)) {
from = to = PyLong_AsLong(slice);
} else if (PySlice_Check(slice)) {
const Reflection* reflection = message->GetReflection();
length = reflection->FieldSize(*message, field_descriptor);
#if PY_MAJOR_VERSION >= 3
if (PySlice_GetIndicesEx(slice, length, &from, &to, &step, &slicelength) ==
-1) {
#else
if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), length,
&from, &to, &step, &slicelength) == -1) {
#endif
return -1;
}
create_list = true;

@ -40,10 +40,6 @@
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/wire_format_lite.h>
#if PY_MAJOR_VERSION >= 3
#define PyInt_FromLong PyLong_FromLong
#endif
namespace google {
namespace protobuf {
namespace python {
@ -237,7 +233,7 @@ static PyObject* GetFieldNumber(PyUnknownFieldRef* self, void *closure) {
if (unknown_field == NULL) {
return NULL;
}
return PyInt_FromLong(unknown_field->number());
return PyLong_FromLong(unknown_field->number());
}
using internal::WireFormatLite;
@ -267,7 +263,7 @@ static PyObject* GetWireType(PyUnknownFieldRef* self, void *closure) {
wire_type = WireFormatLite::WIRETYPE_START_GROUP;
break;
}
return PyInt_FromLong(wire_type);
return PyLong_FromLong(wire_type);
}
static PyObject* GetData(PyUnknownFieldRef* self, void *closure) {
@ -278,13 +274,13 @@ static PyObject* GetData(PyUnknownFieldRef* self, void *closure) {
PyObject* data = NULL;
switch (field->type()) {
case UnknownField::TYPE_VARINT:
data = PyInt_FromLong(field->varint());
data = PyLong_FromLong(field->varint());
break;
case UnknownField::TYPE_FIXED32:
data = PyInt_FromLong(field->fixed32());
data = PyLong_FromLong(field->fixed32());
break;
case UnknownField::TYPE_FIXED64:
data = PyInt_FromLong(field->fixed64());
data = PyLong_FromLong(field->fixed64());
break;
case UnknownField::TYPE_LENGTH_DELIMITED:
data = PyBytes_FromStringAndSize(field->length_delimited().data(),

@ -100,6 +100,7 @@ nobase_include_HEADERS = \
google/protobuf/duration.pb.h \
google/protobuf/dynamic_message.h \
google/protobuf/empty.pb.h \
google/protobuf/explicitly_constructed.h \
google/protobuf/extension_set.h \
google/protobuf/extension_set_inl.h \
google/protobuf/field_access_listener.h \

@ -172,11 +172,7 @@ class PROTOBUF_EXPORT Any final :
// implements Message ----------------------------------------------
inline Any* New() const final {
return new Any();
}
Any* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
Any* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<Any>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -200,6 +196,8 @@ class PROTOBUF_EXPORT Any final :
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";
@ -231,7 +229,7 @@ class PROTOBUF_EXPORT Any final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_type_url(ArgT0&& arg0, ArgT... args);
std::string* mutable_type_url();
PROTOBUF_MUST_USE_RESULT std::string* release_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;
@ -245,7 +243,7 @@ class PROTOBUF_EXPORT Any final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_value(ArgT0&& arg0, ArgT... args);
std::string* mutable_value();
PROTOBUF_MUST_USE_RESULT std::string* release_value();
PROTOBUF_NODISCARD std::string* release_value();
void set_allocated_value(std::string* value);
private:
const std::string& _internal_value() const;

@ -149,11 +149,7 @@ class PROTOBUF_EXPORT Api final :
// implements Message ----------------------------------------------
inline Api* New() const final {
return new Api();
}
Api* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
Api* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<Api>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -177,6 +173,8 @@ class PROTOBUF_EXPORT Api final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(Api* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.Api";
@ -267,7 +265,7 @@ class PROTOBUF_EXPORT Api final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_name(ArgT0&& arg0, ArgT... args);
std::string* mutable_name();
PROTOBUF_MUST_USE_RESULT std::string* release_name();
PROTOBUF_NODISCARD std::string* release_name();
void set_allocated_name(std::string* name);
private:
const std::string& _internal_name() const;
@ -281,7 +279,7 @@ class PROTOBUF_EXPORT Api final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_version(ArgT0&& arg0, ArgT... args);
std::string* mutable_version();
PROTOBUF_MUST_USE_RESULT std::string* release_version();
PROTOBUF_NODISCARD std::string* release_version();
void set_allocated_version(std::string* version);
private:
const std::string& _internal_version() const;
@ -296,7 +294,7 @@ class PROTOBUF_EXPORT Api final :
public:
void clear_source_context();
const ::PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const;
PROTOBUF_MUST_USE_RESULT ::PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
::PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context();
void set_allocated_source_context(::PROTOBUF_NAMESPACE_ID::SourceContext* source_context);
private:
@ -409,11 +407,7 @@ class PROTOBUF_EXPORT Method final :
// implements Message ----------------------------------------------
inline Method* New() const final {
return new Method();
}
Method* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
Method* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<Method>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -437,6 +431,8 @@ class PROTOBUF_EXPORT Method final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(Method* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.Method";
@ -491,7 +487,7 @@ class PROTOBUF_EXPORT Method final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_name(ArgT0&& arg0, ArgT... args);
std::string* mutable_name();
PROTOBUF_MUST_USE_RESULT std::string* release_name();
PROTOBUF_NODISCARD std::string* release_name();
void set_allocated_name(std::string* name);
private:
const std::string& _internal_name() const;
@ -505,7 +501,7 @@ class PROTOBUF_EXPORT Method final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_request_type_url(ArgT0&& arg0, ArgT... args);
std::string* mutable_request_type_url();
PROTOBUF_MUST_USE_RESULT std::string* release_request_type_url();
PROTOBUF_NODISCARD std::string* release_request_type_url();
void set_allocated_request_type_url(std::string* request_type_url);
private:
const std::string& _internal_request_type_url() const;
@ -519,7 +515,7 @@ class PROTOBUF_EXPORT Method final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_response_type_url(ArgT0&& arg0, ArgT... args);
std::string* mutable_response_type_url();
PROTOBUF_MUST_USE_RESULT std::string* release_response_type_url();
PROTOBUF_NODISCARD std::string* release_response_type_url();
void set_allocated_response_type_url(std::string* response_type_url);
private:
const std::string& _internal_response_type_url() const;
@ -647,11 +643,7 @@ class PROTOBUF_EXPORT Mixin final :
// implements Message ----------------------------------------------
inline Mixin* New() const final {
return new Mixin();
}
Mixin* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
Mixin* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<Mixin>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -675,6 +667,8 @@ class PROTOBUF_EXPORT Mixin final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(Mixin* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.Mixin";
@ -706,7 +700,7 @@ class PROTOBUF_EXPORT Mixin final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_name(ArgT0&& arg0, ArgT... args);
std::string* mutable_name();
PROTOBUF_MUST_USE_RESULT std::string* release_name();
PROTOBUF_NODISCARD std::string* release_name();
void set_allocated_name(std::string* name);
private:
const std::string& _internal_name() const;
@ -720,7 +714,7 @@ class PROTOBUF_EXPORT Mixin final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_root(ArgT0&& arg0, ArgT... args);
std::string* mutable_root();
PROTOBUF_MUST_USE_RESULT std::string* release_root();
PROTOBUF_NODISCARD std::string* release_root();
void set_allocated_root(std::string* root);
private:
const std::string& _internal_root() const;

@ -216,31 +216,54 @@ PROTOBUF_THREAD_LOCAL ThreadSafeArena::ThreadCache
void ThreadSafeArena::InitializeFrom(void* mem, size_t size) {
GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0u);
Init(false);
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_ |= kUserOwnedInitialBlock;
alloc_policy_.set_is_user_owned_initial_block(true);
SetInitialBlock(mem, size);
}
}
void ThreadSafeArena::InitializeWithPolicy(void* mem, size_t size,
bool record_allocs,
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(record_allocs);
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_ = kUserOwnedInitialBlock;
alloc_policy_.set_is_user_owned_initial_block(true);
} else {
alloc_policy_ = 0;
auto tmp = AllocateMemory(&policy, 0, kMinimumSize);
mem = tmp.ptr;
size = tmp.size;
@ -255,10 +278,18 @@ void ThreadSafeArena::InitializeWithPolicy(void* mem, size_t size,
return;
}
new (p) AllocationPolicy{policy};
alloc_policy_ |= reinterpret_cast<intptr_t>(p);
// 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(bool record_allocs) {
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
@ -273,9 +304,14 @@ void ThreadSafeArena::Init(bool record_allocs) {
id = lifecycle_id_generator_.id.fetch_add(1, relaxed) * kInc;
}
tc.next_lifecycle_id = id + kDelta;
tag_and_id_ = id | (record_allocs ? kRecordAllocs : 0);
// 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) {
@ -294,13 +330,13 @@ ThreadSafeArena::~ThreadSafeArena() {
auto mem = Free(&space_allocated);
// Policy is about to get deleted.
auto p = AllocPolicy();
auto* p = alloc_policy_.get();
ArenaMetricsCollector* collector = p ? p->metrics_collector : nullptr;
if (alloc_policy_ & kUserOwnedInitialBlock) {
if (alloc_policy_.is_user_owned_initial_block()) {
space_allocated += mem.size;
} else {
GetDeallocator(AllocPolicy(), &space_allocated)(mem);
GetDeallocator(alloc_policy_.get(), &space_allocated)(mem);
}
if (collector) collector->OnDestroy(space_allocated);
@ -308,7 +344,7 @@ ThreadSafeArena::~ThreadSafeArena() {
SerialArena::Memory ThreadSafeArena::Free(size_t* space_allocated) {
SerialArena::Memory mem = {nullptr, 0};
auto deallocator = GetDeallocator(AllocPolicy(), space_allocated);
auto deallocator = GetDeallocator(alloc_policy_.get(), space_allocated);
PerSerialArena([deallocator, &mem](SerialArena* a) {
if (mem.ptr) deallocator(mem);
mem = a->Free(deallocator);
@ -325,26 +361,28 @@ uint64_t ThreadSafeArena::Reset() {
size_t space_allocated = 0;
auto mem = Free(&space_allocated);
if (AllocPolicy()) {
auto saved_policy = *AllocPolicy();
if (alloc_policy_ & kUserOwnedInitialBlock) {
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(AllocPolicy(), &space_allocated)(mem);
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, ShouldRecordAlloc(), saved_policy);
InitializeWithPolicy(mem.ptr, mem.size, saved_policy);
} else {
GOOGLE_DCHECK(!alloc_policy_.should_record_allocs());
// Nullptr policy
if (alloc_policy_ & kUserOwnedInitialBlock) {
if (alloc_policy_.is_user_owned_initial_block()) {
space_allocated += mem.size;
InitializeFrom(mem.ptr, mem.size);
} else {
GetDeallocator(AllocPolicy(), &space_allocated)(mem);
Init(false);
GetDeallocator(alloc_policy_.get(), &space_allocated)(mem);
Init();
}
}
@ -355,8 +393,9 @@ std::pair<void*, SerialArena::CleanupNode*>
ThreadSafeArena::AllocateAlignedWithCleanup(size_t n,
const std::type_info* type) {
SerialArena* arena;
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(tag_and_id_, &arena))) {
return arena->AllocateAlignedWithCleanup(n, AllocPolicy());
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
GetSerialArenaFast(&arena))) {
return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get());
} else {
return AllocateAlignedWithCleanupFallback(n, type);
}
@ -364,46 +403,39 @@ ThreadSafeArena::AllocateAlignedWithCleanup(size_t n,
void ThreadSafeArena::AddCleanup(void* elem, void (*cleanup)(void*)) {
SerialArena* arena;
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(LifeCycleId(), &arena))) {
arena->AddCleanup(elem, cleanup, AllocPolicy());
} else {
return AddCleanupFallback(elem, cleanup);
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 (ShouldRecordAlloc()) {
RecordAlloc(type, n);
if (alloc_policy_.should_record_allocs()) {
alloc_policy_.RecordAlloc(type, n);
SerialArena* arena;
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(LifeCycleId(), &arena))) {
return arena->AllocateAligned(n, AllocPolicy());
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
return arena->AllocateAligned(n, alloc_policy_.get());
}
}
return GetSerialArenaFallback(&thread_cache())
->AllocateAligned(n, AllocPolicy());
->AllocateAligned(n, alloc_policy_.get());
}
PROTOBUF_NOINLINE
std::pair<void*, SerialArena::CleanupNode*>
ThreadSafeArena::AllocateAlignedWithCleanupFallback(
size_t n, const std::type_info* type) {
if (ShouldRecordAlloc()) {
RecordAlloc(type, n);
if (alloc_policy_.should_record_allocs()) {
alloc_policy_.RecordAlloc(type, n);
SerialArena* arena;
if (GetSerialArenaFast(LifeCycleId(), &arena)) {
return arena->AllocateAlignedWithCleanup(n, AllocPolicy());
if (GetSerialArenaFast(&arena)) {
return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get());
}
}
return GetSerialArenaFallback(&thread_cache())
->AllocateAlignedWithCleanup(n, AllocPolicy());
}
PROTOBUF_NOINLINE
void ThreadSafeArena::AddCleanupFallback(void* elem, void (*cleanup)(void*)) {
GetSerialArenaFallback(&thread_cache())
->AddCleanup(elem, cleanup, AllocPolicy());
->AllocateAlignedWithCleanup(n, alloc_policy_.get());
}
uint64_t ThreadSafeArena::SpaceAllocated() const {
@ -421,7 +453,7 @@ uint64_t ThreadSafeArena::SpaceUsed() const {
for (; serial; serial = serial->next()) {
space_used += serial->SpaceUsed();
}
return space_used - (AllocPolicy() ? sizeof(AllocationPolicy) : 0);
return space_used - (alloc_policy_.get() ? sizeof(AllocationPolicy) : 0);
}
void ThreadSafeArena::CleanupList() {
@ -442,7 +474,7 @@ SerialArena* ThreadSafeArena::GetSerialArenaFallback(void* me) {
// 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(AllocPolicy(), 0, kSerialArenaSize), me);
AllocateMemory(alloc_policy_.get(), 0, kSerialArenaSize), me);
SerialArena* head = threads_.load(std::memory_order_relaxed);
do {

@ -65,13 +65,6 @@ namespace google {
namespace protobuf {
struct ArenaOptions; // defined below
} // namespace protobuf
} // namespace google
namespace google {
namespace protobuf {
class Arena; // defined below
class Message; // defined in message.h
class MessageLite;

@ -108,6 +108,75 @@ struct AllocationPolicy {
}
};
// 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
@ -179,6 +248,7 @@ class PROTOBUF_EXPORT SerialArena {
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);
}
@ -270,27 +340,18 @@ struct MessageOwned {
// use #ifdef the select the best implementation based on hardware / OS.
class PROTOBUF_EXPORT ThreadSafeArena {
public:
ThreadSafeArena() { Init(false); }
ThreadSafeArena() { Init(); }
// Constructor solely used by message-owned arena.
ThreadSafeArena(internal::MessageOwned) : alloc_policy_(kMessageOwnedArena) {
Init(false);
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) {
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);
} else {
auto collector = policy.metrics_collector;
bool record_allocs = collector && collector->RecordAllocs();
InitializeWithPolicy(mem, size, record_allocs, policy);
}
InitializeWithPolicy(mem, size, policy);
}
// Destructor deletes all owned heap allocated objects, and destructs objects
@ -306,7 +367,8 @@ class PROTOBUF_EXPORT ThreadSafeArena {
void* AllocateAligned(size_t n, const std::type_info* type) {
SerialArena* arena;
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(tag_and_id_, &arena))) {
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
GetSerialArenaFast(&arena))) {
return arena->AllocateAligned(n, AllocPolicy());
} else {
return AllocateAlignedFallback(n, type);
@ -320,7 +382,8 @@ class PROTOBUF_EXPORT ThreadSafeArena {
// code for the happy path.
PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
SerialArena* a;
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFromThreadCache(tag_and_id_, &a))) {
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
GetSerialArenaFromThreadCache(&a))) {
return a->MaybeAllocateAligned(n, out);
}
return false;
@ -334,58 +397,41 @@ class PROTOBUF_EXPORT ThreadSafeArena {
// Checks whether this arena is message-owned.
PROTOBUF_ALWAYS_INLINE bool IsMessageOwned() const {
return alloc_policy_ & kMessageOwnedArena;
return tag_and_id_ & kMessageOwnedArena;
}
private:
// Unique for each arena. Changes on Reset().
uint64_t tag_and_id_;
// The LSB of tag_and_id_ indicates if allocs in this arena are recorded.
enum { kRecordAllocs = 1 };
intptr_t alloc_policy_ = 0; // Tagged pointer to AllocPolicy.
// The LSB of alloc_policy_ indicates if the user owns the initial block.
// The second LSB of alloc_policy_ indicates if the arena is message-owned.
enum {
kUserOwnedInitialBlock = 1,
kMessageOwnedArena = 2,
};
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 reinterpret_cast<const AllocationPolicy*>(alloc_policy_ & -8);
}
const AllocationPolicy* AllocPolicy() const { return alloc_policy_.get(); }
void InitializeFrom(void* mem, size_t size);
void InitializeWithPolicy(void* mem, size_t size, bool record_allocs,
AllocationPolicy policy);
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 AddCleanupFallback(void* elem, void (*cleanup)(void*));
void Init(bool record_allocs);
void Init();
void SetInitialBlock(void* mem, size_t size);
// Delete or Destruct all objects owned by the arena.
void CleanupList();
inline bool ShouldRecordAlloc() const { return tag_and_id_ & kRecordAllocs; }
inline uint64_t LifeCycleId() const {
return tag_and_id_ & (-kRecordAllocs - 1);
}
inline void RecordAlloc(const std::type_info* allocated_type,
size_t n) const {
AllocPolicy()->metrics_collector->OnAlloc(allocated_type, n);
return tag_and_id_ & ~kMessageOwnedArena;
}
inline void CacheSerialArena(SerialArena* serial) {
thread_cache().last_serial_arena = serial;
thread_cache().last_lifecycle_id_seen = LifeCycleId();
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.
@ -393,10 +439,8 @@ class PROTOBUF_EXPORT ThreadSafeArena {
hint_.store(serial, std::memory_order_release);
}
PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(uint64_t lifecycle_id,
SerialArena** arena) {
if (GetSerialArenaFromThreadCache(lifecycle_id, arena)) return true;
if (lifecycle_id & kRecordAllocs) return false;
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.
@ -410,12 +454,12 @@ class PROTOBUF_EXPORT ThreadSafeArena {
}
PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFromThreadCache(
uint64_t lifecycle_id, SerialArena** arena) {
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 == lifecycle_id)) {
if (PROTOBUF_PREDICT_TRUE(tc->last_lifecycle_id_seen == tag_and_id_)) {
*arena = tc->last_serial_arena;
return true;
}

@ -243,9 +243,9 @@ struct PROTOBUF_EXPORT ArenaStringPtr {
// 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_MUST_USE_RESULT std::string* Release(
const std::string* default_value, ::google::protobuf::Arena* arena);
PROTOBUF_MUST_USE_RESULT std::string* ReleaseNonDefault(
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

@ -2423,8 +2423,8 @@ bool CommandLineInterface::WriteDescriptorSet(
to_output.insert(parsed_files.begin(), parsed_files.end());
for (int i = 0; i < parsed_files.size(); i++) {
const FileDescriptor* file = parsed_files[i];
for (int i = 0; i < file->dependency_count(); i++) {
const FileDescriptor* dependency = file->dependency(i);
for (int j = 0; j < file->dependency_count(); j++) {
const FileDescriptor* dependency = file->dependency(j);
// if the dependency isn't in parsed files, mark it as already seen
if (to_output.find(dependency) == to_output.end()) {
already_seen.insert(dependency);

@ -154,8 +154,8 @@ void FileGenerator::GenerateMacroUndefs(io::Printer* printer) {
for (int i = 0; i < fields.size(); i++) {
const std::string& name = fields[i]->name();
static const char* kMacroNames[] = {"major", "minor"};
for (int i = 0; i < GOOGLE_ARRAYSIZE(kMacroNames); ++i) {
if (name == kMacroNames[i]) {
for (int j = 0; j < GOOGLE_ARRAYSIZE(kMacroNames); ++j) {
if (name == kMacroNames[j]) {
names_to_undef.push_back(name);
break;
}

@ -1168,8 +1168,8 @@ MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) {
if (descriptor->extension_range_count() > 0) {
result.contains_extension = true;
}
for (int i = 0; i < descriptor->field_count(); i++) {
const FieldDescriptor* field = descriptor->field(i);
for (int j = 0; j < descriptor->field_count(); j++) {
const FieldDescriptor* field = descriptor->field(j);
if (field->is_required()) {
result.contains_required = true;
}

@ -63,8 +63,8 @@ inline std::string ProtobufNamespace(const Options& /* options */) {
return "PROTOBUF_NAMESPACE_ID";
}
inline std::string MacroPrefix(const Options& options) {
return options.opensource_runtime ? "GOOGLE_PROTOBUF" : "GOOGLE_PROTOBUF";
inline std::string MacroPrefix(const Options& /* options */) {
return "GOOGLE_PROTOBUF";
}
inline std::string DeprecatedAttribute(const Options& /* options */,

@ -974,7 +974,7 @@ $annotate_extension_set$
template <typename _proto_TypeTraits,
::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
bool _is_packed>
inline PROTOBUF_MUST_USE_RESULT
PROTOBUF_NODISCARD inline
typename _proto_TypeTraits::Singular::MutableType
ReleaseExtension(
const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
@ -1649,11 +1649,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
"\n"
"// implements Message ----------------------------------------------\n"
"\n"
"inline $classname$* New() const final {\n"
" return new $classname$();\n"
"}\n"
"\n"
"$classname$* New(::$proto_ns$::Arena* arena) const final {\n"
"$classname$* New(::$proto_ns$::Arena* arena = nullptr) const final {\n"
" return CreateMaybeMessage<$classname$>(arena);\n"
"}\n");
@ -1736,6 +1732,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
format(
// Friend AnyMetadata so that it can call this FullMessageName() method.
"\nprivate:\n"
"friend class ::$proto_ns$::internal::AnyMetadata;\n"
"static $1$ FullMessageName() {\n"
" return \"$full_name$\";\n"
@ -3115,7 +3112,9 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) {
"metadata_);\n");
if (descriptor_->extension_range_count() > 0) {
format("_extensions_.MergeFrom(from._extensions_);\n");
format(
"_extensions_.MergeFrom(internal_default_instance(), "
"from._extensions_);\n");
}
GenerateConstructorBody(printer, processed, true);
@ -3710,7 +3709,9 @@ void MessageGenerator::GenerateClassSpecificMergeFrom(io::Printer* printer) {
// Merging of extensions and unknown fields is done last, to maximize
// the opportunity for tail calls.
if (descriptor_->extension_range_count() > 0) {
format("_extensions_.MergeFrom(from._extensions_);\n");
format(
"_extensions_.MergeFrom(internal_default_instance(), "
"from._extensions_);\n");
}
format(

@ -109,7 +109,7 @@ void MessageFieldGenerator::GenerateAccessorDeclarations(
format(
"$deprecated_attr$const $type$& ${1$$name$$}$() const { "
"__builtin_trap(); }\n"
"PROTOBUF_MUST_USE_RESULT $deprecated_attr$$type$* "
"PROTOBUF_NODISCARD $deprecated_attr$$type$* "
"${1$$release_name$$}$() { "
"__builtin_trap(); }\n"
"$deprecated_attr$$type$* ${1$mutable_$name$$}$() { "
@ -126,7 +126,7 @@ void MessageFieldGenerator::GenerateAccessorDeclarations(
}
format(
"$deprecated_attr$const $type$& ${1$$name$$}$() const;\n"
"PROTOBUF_MUST_USE_RESULT $deprecated_attr$$type$* "
"PROTOBUF_NODISCARD $deprecated_attr$$type$* "
"${1$$release_name$$}$();\n"
"$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n"
"$deprecated_attr$void ${1$set_allocated_$name$$}$"

@ -766,15 +766,22 @@ void ParseFunctionGenerator::GenerateLengthDelim(Formatter& format,
"$msg$GetArenaForAllocation());\n"
" $msg$set_has_$name$();\n"
"}\n"
"ptr = ctx->ParseMessage($msg$$1$_.$name$_, ptr);\n",
"auto* lazy_field = $msg$$1$_.$name$_;\n",
field->containing_oneof()->name());
} else if (HasHasbit(field)) {
format(
"_Internal::set_has_$name$(&$has_bits$);\n"
"ptr = ctx->ParseMessage(&$msg$$name$_, ptr);\n");
"auto* lazy_field = &$msg$$name$_;\n");
} else {
format("ptr = ctx->ParseMessage(&$msg$$name$_, ptr);\n");
format("auto* lazy_field = &$msg$$name$_;\n");
}
format(
"::$proto_ns$::internal::LazyFieldParseHelper<\n"
" ::$proto_ns$::internal::LazyField> parse_helper(\n"
" $1$::default_instance(),\n"
" $msg$GetArenaForAllocation(), lazy_field);\n"
"ptr = ctx->ParseMessage(&parse_helper, ptr);\n",
FieldMessageTypeName(field, options_));
} else if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
if (!field->is_repeated()) {
format(

@ -241,12 +241,12 @@ void ServiceGenerator::GenerateCallMethod(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);
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(
format_method(
" case $1$:\n"
" $name$(controller,\n"
" ::$proto_ns$::internal::DownCast<const $input_type$*>(\n"

@ -170,7 +170,7 @@ void StringFieldGenerator::GenerateAccessorDeclarations(
descriptor_);
format(
"$deprecated_attr$std::string* ${1$mutable_$name$$}$();\n"
"PROTOBUF_MUST_USE_RESULT $deprecated_attr$std::string* "
"PROTOBUF_NODISCARD $deprecated_attr$std::string* "
"${1$$release_name$$}$();\n"
"$deprecated_attr$void ${1$set_allocated_$name$$}$(std::string* "
"$name$);\n",
@ -290,7 +290,7 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions(
" $clear_hasbit$\n");
if (!inlined_) {
format(
" return $name$_.ReleaseNonDefault($init_value$, "
" auto* p = $name$_.ReleaseNonDefault($init_value$, "
"GetArenaForAllocation());\n");
if (descriptor_->default_value_string().empty()) {
format(
@ -300,6 +300,7 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions(
" }\n"
"#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
}
format(" return p;\n");
} else {
format(
" return $name$_.Release(nullptr, GetArenaForAllocation(), "

@ -618,8 +618,8 @@ void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode(
void ImmutablePrimitiveOneofFieldGenerator::GenerateParsingCode(
io::Printer* printer) const {
printer->Print(variables_,
"$set_oneof_case_message$;\n"
"$oneof_name$_ = input.read$capitalized_type$();\n");
"$oneof_name$_ = input.read$capitalized_type$();\n"
"$set_oneof_case_message$;\n");
}
void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializationCode(

@ -127,7 +127,6 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
if (alias_values_to_skip_.find(all_values_[i]) != alias_values_to_skip_.end()) {
continue;
}
SourceLocation location;
if (all_values_[i]->GetSourceLocation(&location)) {
std::string comments = BuildCommentsString(location, true).c_str();
if (comments.length() > 0) {

@ -52,7 +52,7 @@ namespace objectivec {
namespace {
// This is also found in GPBBootstrap.h, and needs to be kept in sync.
const int32 GOOGLE_PROTOBUF_OBJC_VERSION = 30004;
const int32_t GOOGLE_PROTOBUF_OBJC_VERSION = 30004;
const char* kHeaderExtension = ".pbobjc.h";

@ -44,6 +44,28 @@ namespace protobuf {
namespace compiler {
namespace objectivec {
namespace {
// Convert a string with "yes"/"no" (case insensitive) to a boolean, returning
// true/false for if the input string was a valid value. If the input string is
// invalid, `result` is unchanged.
bool StringToBool(const std::string& value, bool* result) {
std::string upper_value(value);
UpperString(&upper_value);
if (upper_value == "NO") {
*result = false;
return true;
}
if (upper_value == "YES") {
*result = true;
return true;
}
return false;
}
} // namespace
ObjectiveCGenerator::ObjectiveCGenerator() {}
ObjectiveCGenerator::~ObjectiveCGenerator() {}
@ -101,6 +123,31 @@ bool ObjectiveCGenerator::GenerateAll(
generation_options.expected_prefixes_suppressions.push_back(
std::string(split_piece));
}
} else if (options[i].first == "prefixes_must_be_registered") {
// If objc prefix file option value must be registered to be used. This
// option has no meaning if an "expected_prefixes_path" isn't set. The
// available options are:
// "no": They don't have to be registered.
// "yes": They must be registered and an error will be raised if a files
// tried to use a prefix that isn't registered.
// Default is "no".
if (!StringToBool(options[i].second,
&generation_options.prefixes_must_be_registered)) {
*error = "error: Unknown value for prefixes_must_be_registered: " + options[i].second;
return false;
}
} else if (options[i].first == "require_prefixes") {
// If every file must have an objc prefix file option to be used. The
// available options are:
// "no": Files can be generated without the prefix option.
// "yes": Files must have the objc prefix option, and an error will be
// raised if a files doesn't have one.
// Default is "no".
if (!StringToBool(options[i].second,
&generation_options.require_prefixes)) {
*error = "error: Unknown value for require_prefixes: " + options[i].second;
return false;
}
} else if (options[i].first == "generate_for_named_framework") {
// The name of the framework that protos are being generated for. This
// will cause the #import statements to be framework based using this
@ -146,12 +193,9 @@ bool ObjectiveCGenerator::GenerateAll(
// is just what to do if that isn't set. The available options are:
// "no": Not prefixed (the existing mode).
// "yes": Make a prefix out of the proto package.
std::string upper_value(options[i].second);
UpperString(&upper_value);
if (upper_value == "NO") {
SetUseProtoPackageAsDefaultPrefix(false);
} else if (upper_value == "YES") {
SetUseProtoPackageAsDefaultPrefix(true);
bool value = false;
if (StringToBool(options[i].second, &value)) {
SetUseProtoPackageAsDefaultPrefix(value);
} else {
*error = "error: Unknown use_package_as_prefix: " + options[i].second;
return false;

@ -178,6 +178,8 @@ Options::Options() {
expected_prefixes_suppressions =
Split(suppressions, ";", true);
}
prefixes_must_be_registered = false;
require_prefixes = false;
}
namespace {
@ -992,7 +994,7 @@ std::string DefaultValue(const FieldDescriptor* field) {
// Must convert to a standard byte order for packing length into
// a cstring.
uint32 length = ghtonl(default_string.length());
uint32_t length = ghtonl(default_string.length());
std::string bytes((const char*)&length, sizeof(length));
bytes.append(default_string);
return "(NSData*)\"" + EscapeTrigraphs(CEscape(bytes)) + "\"";
@ -1227,6 +1229,7 @@ bool LoadExpectedPackagePrefixes(const Options& generation_options,
bool ValidateObjCClassPrefix(
const FileDescriptor* file, const std::string& expected_prefixes_path,
const std::map<std::string, std::string>& expected_package_prefixes,
bool prefixes_must_be_registered, bool require_prefixes,
std::string* out_error) {
// Reminder: An explicit prefix option of "" is valid in case the default
// prefixing is set to use the proto package and a file needs to be generated
@ -1265,6 +1268,12 @@ bool ValidateObjCClassPrefix(
// If there was no prefix option, we're done at this point.
if (!has_prefix) {
if (require_prefixes) {
*out_error =
"error: '" + file->name() + "' does not have a required 'option" +
" objc_class_prefix'.";
return false;
}
return true;
}
@ -1344,9 +1353,18 @@ bool ValidateObjCClassPrefix(
std::cerr.flush();
}
// Check: Warning - If the given package/prefix pair wasn't expected, issue a
// warning suggesting it gets added to the file.
// Check: Error/Warning - If the given package/prefix pair wasn't expected,
// issue a error/warning to added to the file.
if (have_expected_prefix_file) {
if (prefixes_must_be_registered) {
*out_error =
"error: '" + file->name() + "' has 'option objc_class_prefix = \"" +
prefix + "\";', but it is not registered; add it to the expected" +
" prefixes file (" + expected_prefixes_path + ") for the package" +
"'" + package + "'.";
return false;
}
std::cerr
<< "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
<< prefix << "\";' in '" << file->name() << "';"
@ -1391,6 +1409,8 @@ bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
ValidateObjCClassPrefix(files[i],
generation_options.expected_prefixes_path,
expected_package_prefixes,
generation_options.prefixes_must_be_registered,
generation_options.require_prefixes,
out_error);
if (!is_valid) {
return false;
@ -1403,7 +1423,7 @@ TextFormatDecodeData::TextFormatDecodeData() { }
TextFormatDecodeData::~TextFormatDecodeData() { }
void TextFormatDecodeData::AddString(int32 key,
void TextFormatDecodeData::AddString(int32_t key,
const std::string& input_for_decode,
const std::string& desired_output) {
for (std::vector<DataEntry>::const_iterator i = entries_.begin();
@ -1459,12 +1479,12 @@ class DecodeDataBuilder {
}
private:
static constexpr uint8 kAddUnderscore = 0x80;
static constexpr uint8_t kAddUnderscore = 0x80;
static constexpr uint8 kOpAsIs = 0x00;
static constexpr uint8 kOpFirstUpper = 0x40;
static constexpr uint8 kOpFirstLower = 0x20;
static constexpr uint8 kOpAllUpper = 0x60;
static constexpr uint8_t kOpAsIs = 0x00;
static constexpr uint8_t kOpFirstUpper = 0x40;
static constexpr uint8_t kOpFirstLower = 0x20;
static constexpr uint8_t kOpAllUpper = 0x60;
static constexpr int kMaxSegmentLen = 0x1f;
@ -1474,7 +1494,7 @@ class DecodeDataBuilder {
}
void Push() {
uint8 op = (op_ | segment_len_);
uint8_t op = (op_ | segment_len_);
if (need_underscore_) op |= kAddUnderscore;
if (op != 0) {
decode_data_ += (char)op;
@ -1506,7 +1526,7 @@ class DecodeDataBuilder {
bool need_underscore_;
bool is_all_upper_;
uint8 op_;
uint8_t op_;
int segment_len_;
std::string decode_data_;

@ -67,6 +67,8 @@ struct Options {
std::string generate_for_named_framework;
std::string named_framework_to_proto_path_mappings_path;
std::string runtime_import_prefix;
bool prefixes_must_be_registered;
bool require_prefixes;
};
// Escape C++ trigraphs by escaping question marks to "\?".

@ -1549,7 +1549,7 @@ bool Parser::ParseOption(Message* options,
value_location.AddPath(
UninterpretedOption::kNegativeIntValueFieldNumber);
uninterpreted_option->set_negative_int_value(
static_cast<int64_t>(-value));
static_cast<int64_t>(0 - value));
} else {
value_location.AddPath(
UninterpretedOption::kPositiveIntValueFieldNumber);

@ -1119,9 +1119,9 @@ void GenerateAddFilesToPool(const FileDescriptor* file, const Options& options,
file, &nodes_without_dependency, &deps, &dependency_count);
while (!nodes_without_dependency.empty()) {
auto file = *nodes_without_dependency.begin();
nodes_without_dependency.erase(file);
for (auto dependent : deps[file]) {
auto file_node = *nodes_without_dependency.begin();
nodes_without_dependency.erase(file_node);
for (auto dependent : deps[file_node]) {
if (dependency_count[dependent] == 1) {
dependency_count.erase(dependent);
nodes_without_dependency.insert(dependent);
@ -1130,11 +1130,11 @@ void GenerateAddFilesToPool(const FileDescriptor* file, const Options& options,
}
}
bool needs_aggregate = NeedsUnwrapping(file, options);
bool needs_aggregate = NeedsUnwrapping(file_node, options);
if (needs_aggregate) {
auto file_proto = sorted_file_set.add_file();
file->CopyTo(file_proto);
file_node->CopyTo(file_proto);
// Filter out descriptor.proto as it cannot be depended on for now.
RepeatedPtrField<std::string>* dependency =
@ -1156,7 +1156,7 @@ void GenerateAddFilesToPool(const FileDescriptor* file, const Options& options,
it->clear_extension();
}
} else {
std::string dependency_filename = GeneratedMetadataFileName(file, false);
std::string dependency_filename = GeneratedMetadataFileName(file_node, false);
printer->Print(
"\\^name^::initOnce();\n",
"name", FilenameToClassname(dependency_filename));

@ -192,11 +192,7 @@ class PROTOC_EXPORT Version final :
// implements Message ----------------------------------------------
inline Version* New() const final {
return new Version();
}
Version* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
Version* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<Version>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -220,6 +216,8 @@ class PROTOC_EXPORT Version final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(Version* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.compiler.Version";
@ -257,7 +255,7 @@ class PROTOC_EXPORT Version final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_suffix(ArgT0&& arg0, ArgT... args);
std::string* mutable_suffix();
PROTOBUF_MUST_USE_RESULT std::string* release_suffix();
PROTOBUF_NODISCARD std::string* release_suffix();
void set_allocated_suffix(std::string* suffix);
private:
const std::string& _internal_suffix() const;
@ -402,11 +400,7 @@ class PROTOC_EXPORT CodeGeneratorRequest final :
// implements Message ----------------------------------------------
inline CodeGeneratorRequest* New() const final {
return new CodeGeneratorRequest();
}
CodeGeneratorRequest* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
CodeGeneratorRequest* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<CodeGeneratorRequest>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -430,6 +424,8 @@ class PROTOC_EXPORT CodeGeneratorRequest final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(CodeGeneratorRequest* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.compiler.CodeGeneratorRequest";
@ -509,7 +505,7 @@ class PROTOC_EXPORT CodeGeneratorRequest final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_parameter(ArgT0&& arg0, ArgT... args);
std::string* mutable_parameter();
PROTOBUF_MUST_USE_RESULT std::string* release_parameter();
PROTOBUF_NODISCARD std::string* release_parameter();
void set_allocated_parameter(std::string* parameter);
private:
const std::string& _internal_parameter() const;
@ -524,7 +520,7 @@ class PROTOC_EXPORT CodeGeneratorRequest final :
public:
void clear_compiler_version();
const ::PROTOBUF_NAMESPACE_ID::compiler::Version& compiler_version() const;
PROTOBUF_MUST_USE_RESULT ::PROTOBUF_NAMESPACE_ID::compiler::Version* release_compiler_version();
PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::compiler::Version* release_compiler_version();
::PROTOBUF_NAMESPACE_ID::compiler::Version* mutable_compiler_version();
void set_allocated_compiler_version(::PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version);
private:
@ -633,11 +629,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final :
// implements Message ----------------------------------------------
inline CodeGeneratorResponse_File* New() const final {
return new CodeGeneratorResponse_File();
}
CodeGeneratorResponse_File* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
CodeGeneratorResponse_File* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<CodeGeneratorResponse_File>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -661,6 +653,8 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(CodeGeneratorResponse_File* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.compiler.CodeGeneratorResponse.File";
@ -698,7 +692,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_name(ArgT0&& arg0, ArgT... args);
std::string* mutable_name();
PROTOBUF_MUST_USE_RESULT std::string* release_name();
PROTOBUF_NODISCARD std::string* release_name();
void set_allocated_name(std::string* name);
private:
const std::string& _internal_name() const;
@ -716,7 +710,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_insertion_point(ArgT0&& arg0, ArgT... args);
std::string* mutable_insertion_point();
PROTOBUF_MUST_USE_RESULT std::string* release_insertion_point();
PROTOBUF_NODISCARD std::string* release_insertion_point();
void set_allocated_insertion_point(std::string* insertion_point);
private:
const std::string& _internal_insertion_point() const;
@ -734,7 +728,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_content(ArgT0&& arg0, ArgT... args);
std::string* mutable_content();
PROTOBUF_MUST_USE_RESULT std::string* release_content();
PROTOBUF_NODISCARD std::string* release_content();
void set_allocated_content(std::string* content);
private:
const std::string& _internal_content() const;
@ -749,7 +743,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final :
public:
void clear_generated_code_info();
const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& generated_code_info() const;
PROTOBUF_MUST_USE_RESULT ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* release_generated_code_info();
PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* release_generated_code_info();
::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* mutable_generated_code_info();
void set_allocated_generated_code_info(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info);
private:
@ -858,11 +852,7 @@ class PROTOC_EXPORT CodeGeneratorResponse final :
// implements Message ----------------------------------------------
inline CodeGeneratorResponse* New() const final {
return new CodeGeneratorResponse();
}
CodeGeneratorResponse* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
CodeGeneratorResponse* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<CodeGeneratorResponse>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -886,6 +876,8 @@ class PROTOC_EXPORT CodeGeneratorResponse final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(CodeGeneratorResponse* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.compiler.CodeGeneratorResponse";
@ -972,7 +964,7 @@ class PROTOC_EXPORT CodeGeneratorResponse final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_error(ArgT0&& arg0, ArgT... args);
std::string* mutable_error();
PROTOBUF_MUST_USE_RESULT std::string* release_error();
PROTOBUF_NODISCARD std::string* release_error();
void set_allocated_error(std::string* error);
private:
const std::string& _internal_error() const;
@ -1147,12 +1139,13 @@ inline std::string* Version::release_suffix() {
return nullptr;
}
_has_bits_[0] &= ~0x00000001u;
return suffix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
auto* p = suffix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
if (suffix_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
}
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
return p;
}
inline void Version::set_allocated_suffix(std::string* suffix) {
if (suffix != nullptr) {
@ -1294,12 +1287,13 @@ inline std::string* CodeGeneratorRequest::release_parameter() {
return nullptr;
}
_has_bits_[0] &= ~0x00000001u;
return parameter_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
auto* p = parameter_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
if (parameter_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
}
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
return p;
}
inline void CodeGeneratorRequest::set_allocated_parameter(std::string* parameter) {
if (parameter != nullptr) {
@ -1493,12 +1487,13 @@ inline std::string* CodeGeneratorResponse_File::release_name() {
return nullptr;
}
_has_bits_[0] &= ~0x00000001u;
return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
auto* p = name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
if (name_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
}
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
return p;
}
inline void CodeGeneratorResponse_File::set_allocated_name(std::string* name) {
if (name != nullptr) {
@ -1561,12 +1556,13 @@ inline std::string* CodeGeneratorResponse_File::release_insertion_point() {
return nullptr;
}
_has_bits_[0] &= ~0x00000002u;
return insertion_point_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
auto* p = insertion_point_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
if (insertion_point_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
}
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
return p;
}
inline void CodeGeneratorResponse_File::set_allocated_insertion_point(std::string* insertion_point) {
if (insertion_point != nullptr) {
@ -1629,12 +1625,13 @@ inline std::string* CodeGeneratorResponse_File::release_content() {
return nullptr;
}
_has_bits_[0] &= ~0x00000004u;
return content_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
auto* p = content_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
if (content_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
}
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
return p;
}
inline void CodeGeneratorResponse_File::set_allocated_content(std::string* content) {
if (content != nullptr) {
@ -1789,12 +1786,13 @@ inline std::string* CodeGeneratorResponse::release_error() {
return nullptr;
}
_has_bits_[0] &= ~0x00000001u;
return error_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
auto* p = error_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
if (error_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
}
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
return p;
}
inline void CodeGeneratorResponse::set_allocated_error(std::string* error) {
if (error != nullptr) {

@ -799,12 +799,11 @@ void Generator::PrintCreateDescriptor(
printer_->Indent();
for (int i = 0; i < message_descriptor.oneof_decl_count(); ++i) {
const OneofDescriptor* desc = message_descriptor.oneof_decl(i);
std::map<std::string, std::string> m;
m.clear();
m["name"] = desc->name();
m["full_name"] = desc->full_name();
m["index"] = StrCat(desc->index());
std::string options_string =
OptionsValue(desc->options().SerializeAsString());
options_string = OptionsValue(desc->options().SerializeAsString());
if (options_string == "None") {
m["serialized_options"] = "";
} else {

@ -156,6 +156,7 @@ class Symbol {
struct QueryKey : internal::SymbolBase {
StringPiece name;
const void* parent;
int field_number;
};
DEFINE_MEMBERS(QueryKey, QUERY_KEY, query_key);
#undef DEFINE_MEMBERS
@ -220,7 +221,7 @@ class Symbol {
return "";
}
std::pair<const void*, StringPiece> parent_key() const {
std::pair<const void*, StringPiece> parent_name_key() const {
const auto or_file = [&](const void* p) { return p ? p : GetFile(); };
switch (type()) {
case MESSAGE:
@ -255,6 +256,22 @@ class Symbol {
return {};
}
std::pair<const void*, int> parent_number_key() const {
switch (type()) {
case FIELD:
return {field_descriptor()->containing_type(),
field_descriptor()->number()};
case ENUM_VALUE:
return {enum_value_descriptor()->type(),
enum_value_descriptor()->number()};
case QUERY_KEY:
return {query_key()->parent, query_key()->field_number};
default:
GOOGLE_CHECK(false);
}
return {};
}
private:
const internal::SymbolBase* ptr_;
};
@ -499,7 +516,6 @@ class PrefixRemover {
typedef std::pair<const void*, StringPiece> PointerStringPair;
typedef std::pair<const Descriptor*, int> DescriptorIntPair;
typedef std::pair<const EnumDescriptor*, int> EnumIntPair;
#define HASH_MAP std::unordered_map
#define HASH_SET std::unordered_set
@ -561,12 +577,12 @@ using SymbolsByNameSet =
struct SymbolByParentHash {
size_t operator()(Symbol s) const {
return PointerStringPairHash{}(s.parent_key());
return PointerStringPairHash{}(s.parent_name_key());
}
};
struct SymbolByParentEq {
bool operator()(Symbol a, Symbol b) const {
return a.parent_key() == b.parent_key();
return a.parent_name_key() == b.parent_name_key();
}
};
using SymbolsByParentSet =
@ -580,15 +596,21 @@ typedef HASH_MAP<PointerStringPair, const FieldDescriptor*,
PointerStringPairHash>
FieldsByNameMap;
typedef HASH_MAP<DescriptorIntPair, const FieldDescriptor*,
PointerIntegerPairHash<DescriptorIntPair>,
std::equal_to<DescriptorIntPair>>
FieldsByNumberMap;
struct FieldsByNumberHash {
size_t operator()(Symbol s) const {
return PointerIntegerPairHash<std::pair<const void*, int>>{}(
s.parent_number_key());
}
};
struct FieldsByNumberEq {
bool operator()(Symbol a, Symbol b) const {
return a.parent_number_key() == b.parent_number_key();
}
};
using FieldsByNumberSet =
HASH_SET<Symbol, FieldsByNumberHash, FieldsByNumberEq>;
using EnumValuesByNumberSet = FieldsByNumberSet;
typedef HASH_MAP<EnumIntPair, const EnumValueDescriptor*,
PointerIntegerPairHash<EnumIntPair>,
std::equal_to<EnumIntPair>>
EnumValuesByNumberMap;
// This is a map rather than a hash-map, since we use it to iterate
// through all the extensions that extend a given Descriptor, and an
// ordered data structure that implements lower_bound is convenient
@ -1268,8 +1290,8 @@ class FileDescriptorTables {
// as it will be used as a key in the symbols_by_parent_ map without copying.
bool AddAliasUnderParent(const void* parent, const std::string& name,
Symbol symbol);
bool AddFieldByNumber(const FieldDescriptor* field);
bool AddEnumValueByNumber(const EnumValueDescriptor* value);
bool AddFieldByNumber(FieldDescriptor* field);
bool AddEnumValueByNumber(EnumValueDescriptor* value);
// Adds the field to the lowercase_name and camelcase_name maps. Never
// fails because we allow duplicates; the first field by the name wins.
@ -1307,9 +1329,9 @@ class FileDescriptorTables {
mutable FieldsByNameMap fields_by_camelcase_name_;
std::unique_ptr<FieldsByNameMap> fields_by_camelcase_name_tmp_;
mutable internal::once_flag fields_by_camelcase_name_once_;
FieldsByNumberMap fields_by_number_; // Not including extensions.
EnumValuesByNumberMap enum_values_by_number_;
mutable EnumValuesByNumberMap unknown_enum_values_by_number_
FieldsByNumberSet fields_by_number_; // Not including extensions.
EnumValuesByNumberSet enum_values_by_number_;
mutable EnumValuesByNumberSet unknown_enum_values_by_number_
PROTOBUF_GUARDED_BY(unknown_enum_values_mu_);
// Populated on first request to save space, hence constness games.
@ -1459,7 +1481,19 @@ inline const FileDescriptor* DescriptorPool::Tables::FindFile(
inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
const Descriptor* parent, int number) const {
return FindPtrOrNull(fields_by_number_, std::make_pair(parent, number));
// If `number` is within the sequential range, just index into the parent
// without doing a table lookup.
if (parent != nullptr && //
1 <= number && number <= parent->sequential_field_limit_) {
return parent->field(number - 1);
}
Symbol::QueryKey query;
query.parent = parent;
query.field_number = number;
auto it = fields_by_number_.find(Symbol(&query));
return it == fields_by_number_.end() ? nullptr : it->field_descriptor();
}
const void* FileDescriptorTables::FindParentForFieldsByMap(
@ -1481,12 +1515,12 @@ void FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic(
}
void FileDescriptorTables::FieldsByLowercaseNamesLazyInitInternal() const {
for (FieldsByNumberMap::const_iterator it = fields_by_number_.begin();
it != fields_by_number_.end(); it++) {
PointerStringPair lowercase_key(FindParentForFieldsByMap(it->second),
it->second->lowercase_name().c_str());
InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key,
it->second);
for (Symbol symbol : symbols_by_parent_) {
const FieldDescriptor* field = symbol.field_descriptor();
if (!field) continue;
PointerStringPair lowercase_key(FindParentForFieldsByMap(field),
field->lowercase_name().c_str());
InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key, field);
}
}
@ -1505,12 +1539,12 @@ void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic(
}
void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitInternal() const {
for (FieldsByNumberMap::const_iterator it = fields_by_number_.begin();
it != fields_by_number_.end(); it++) {
PointerStringPair camelcase_key(FindParentForFieldsByMap(it->second),
it->second->camelcase_name().c_str());
InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key,
it->second);
for (Symbol symbol : symbols_by_parent_) {
const FieldDescriptor* field = symbol.field_descriptor();
if (!field) continue;
PointerStringPair camelcase_key(FindParentForFieldsByMap(field),
field->camelcase_name().c_str());
InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key, field);
}
}
@ -1525,8 +1559,21 @@ inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
const EnumDescriptor* parent, int number) const {
return FindPtrOrNull(enum_values_by_number_,
std::make_pair(parent, number));
// If `number` is within the sequential range, just index into the parent
// without doing a table lookup.
const int base = parent->value(0)->number();
if (base <= number &&
number <= static_cast<int64_t>(base) + parent->sequential_value_limit_) {
return parent->value(number - base);
}
Symbol::QueryKey query;
query.parent = parent;
query.field_number = number;
auto it = enum_values_by_number_.find(Symbol(&query));
return it == enum_values_by_number_.end() ? nullptr
: it->enum_value_descriptor();
}
inline const EnumValueDescriptor*
@ -1534,29 +1581,33 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
const EnumDescriptor* parent, int number) const {
// First try, with map of compiled-in values.
{
const EnumValueDescriptor* desc = FindPtrOrNull(
enum_values_by_number_, std::make_pair(parent, number));
if (desc != nullptr) {
return desc;
const auto* value = FindEnumValueByNumber(parent, number);
if (value != nullptr) {
return value;
}
}
Symbol::QueryKey query;
query.parent = parent;
query.field_number = number;
// Second try, with reader lock held on unknown enum values: common case.
{
ReaderMutexLock l(&unknown_enum_values_mu_);
const EnumValueDescriptor* desc = FindPtrOrNull(
unknown_enum_values_by_number_, std::make_pair(parent, number));
if (desc != nullptr) {
return desc;
auto it = unknown_enum_values_by_number_.find(Symbol(&query));
if (it != unknown_enum_values_by_number_.end() &&
it->enum_value_descriptor() != nullptr) {
return it->enum_value_descriptor();
}
}
// If not found, try again with writer lock held, and create new descriptor if
// necessary.
{
WriterMutexLock l(&unknown_enum_values_mu_);
const EnumValueDescriptor* desc = FindPtrOrNull(
unknown_enum_values_by_number_, std::make_pair(parent, number));
if (desc != nullptr) {
return desc;
auto it = unknown_enum_values_by_number_.find(Symbol(&query));
if (it != unknown_enum_values_by_number_.end() &&
it->enum_value_descriptor() != nullptr) {
return it->enum_value_descriptor();
}
// Create an EnumValueDescriptor dynamically. We don't insert it into the
@ -1565,17 +1616,21 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
// later.
std::string enum_value_name = StringPrintf("UNKNOWN_ENUM_VALUE_%s_%d",
parent->name().c_str(), number);
DescriptorPool::Tables* tables = const_cast<DescriptorPool::Tables*>(
DescriptorPool::generated_pool()->tables_.get());
EnumValueDescriptor* result = tables->Allocate<EnumValueDescriptor>();
result->all_names_ = tables->AllocateStringArray(
enum_value_name,
StrCat(parent->full_name(), ".", enum_value_name));
auto* pool = DescriptorPool::generated_pool();
auto* tables = const_cast<DescriptorPool::Tables*>(pool->tables_.get());
EnumValueDescriptor* result;
{
// Must lock the pool because we will do allocations in the shared arena.
MutexLockMaybe l2(pool->mutex_);
result = tables->Allocate<EnumValueDescriptor>();
result->all_names_ = tables->AllocateStringArray(
enum_value_name,
StrCat(parent->full_name(), ".", enum_value_name));
}
result->number_ = number;
result->type_ = parent;
result->options_ = &EnumValueOptions::default_instance();
InsertIfNotPresent(&unknown_enum_values_by_number_,
std::make_pair(parent, number), result);
unknown_enum_values_by_number_.insert(Symbol::EnumValue(result, 0));
return result;
}
}
@ -1611,8 +1666,8 @@ bool DescriptorPool::Tables::AddSymbol(const std::string& full_name,
bool FileDescriptorTables::AddAliasUnderParent(const void* parent,
const std::string& name,
Symbol symbol) {
GOOGLE_DCHECK_EQ(name, symbol.parent_key().second);
GOOGLE_DCHECK_EQ(parent, symbol.parent_key().first);
GOOGLE_DCHECK_EQ(name, symbol.parent_name_key().second);
GOOGLE_DCHECK_EQ(parent, symbol.parent_name_key().first);
return symbols_by_parent_.insert(symbol).second;
}
@ -1659,15 +1714,30 @@ void FileDescriptorTables::AddFieldByStylizedNames(
}
}
bool FileDescriptorTables::AddFieldByNumber(const FieldDescriptor* field) {
DescriptorIntPair key(field->containing_type(), field->number());
return InsertIfNotPresent(&fields_by_number_, key, field);
bool FileDescriptorTables::AddFieldByNumber(FieldDescriptor* field) {
// Skip fields that are at the start of the sequence.
if (field->containing_type() != nullptr && field->number() >= 1 &&
field->number() <= field->containing_type()->sequential_field_limit_) {
if (field->is_extension()) {
// Conflicts with the field that already exists in the sequential range.
return false;
}
// Only return true if the field at that index matches. Otherwise it
// conflicts with the existing field in the sequential range.
return field->containing_type()->field(field->number() - 1) == field;
}
return fields_by_number_.insert(Symbol(field)).second;
}
bool FileDescriptorTables::AddEnumValueByNumber(
const EnumValueDescriptor* value) {
EnumIntPair key(value->type(), value->number());
return InsertIfNotPresent(&enum_values_by_number_, key, value);
bool FileDescriptorTables::AddEnumValueByNumber(EnumValueDescriptor* value) {
// Skip values that are at the start of the sequence.
const int base = value->type()->value(0)->number();
if (base <= value->number() &&
value->number() <=
static_cast<int64_t>(base) + value->type()->sequential_value_limit_)
return true;
return enum_values_by_number_.insert(Symbol::EnumValue(value, 0)).second;
}
bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) {
@ -2489,25 +2559,18 @@ std::string FieldDescriptor::DefaultValueAsString(
switch (cpp_type()) {
case CPPTYPE_INT32:
return StrCat(default_value_int32_t());
break;
case CPPTYPE_INT64:
return StrCat(default_value_int64_t());
break;
case CPPTYPE_UINT32:
return StrCat(default_value_uint32_t());
break;
case CPPTYPE_UINT64:
return StrCat(default_value_uint64_t());
break;
case CPPTYPE_FLOAT:
return SimpleFtoa(default_value_float());
break;
case CPPTYPE_DOUBLE:
return SimpleDtoa(default_value_double());
break;
case CPPTYPE_BOOL:
return default_value_bool() ? "true" : "false";
break;
case CPPTYPE_STRING:
if (quote_string_type) {
return "\"" + CEscape(default_value_string()) + "\"";
@ -2518,10 +2581,8 @@ std::string FieldDescriptor::DefaultValueAsString(
return default_value_string();
}
}
break;
case CPPTYPE_ENUM:
return default_value_enum()->name();
break;
case CPPTYPE_MESSAGE:
GOOGLE_LOG(DFATAL) << "Messages can't have default values!";
break;
@ -4457,6 +4518,8 @@ Symbol DescriptorPool::NewPlaceholderWithMutexHeld(
// Enums must have at least one value.
placeholder_enum->value_count_ = 1;
placeholder_enum->values_ = tables_->AllocateArray<EnumValueDescriptor>(1);
// Disable fast-path lookup for this enum.
placeholder_enum->sequential_value_limit_ = -1;
EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0];
memset(static_cast<void*>(placeholder_value), 0,
@ -5131,6 +5194,19 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
result->well_known_type_ = it->second;
}
// Calculate the continuous sequence of fields.
// These can be fast-path'd during lookup and don't need to be added to the
// tables.
// We use uint16_t to save space for sequential_field_limit_, so stop before
// overflowing it. Worst case, we are not taking full advantage on huge
// messages, but it is unlikely.
result->sequential_field_limit_ = 0;
for (int i = 0; i < std::numeric_limits<uint16_t>::max() &&
i < proto.field_size() && proto.field(i).number() == i + 1;
++i) {
result->sequential_field_limit_ = i + 1;
}
// Build oneofs first so that fields and extension ranges can refer to them.
BUILD_ARRAY(proto, result, oneof_decl, BuildOneof, result);
BUILD_ARRAY(proto, result, field, BuildField, result);
@ -5693,6 +5769,21 @@ void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
"Enums must contain at least one value.");
}
// Calculate the continuous sequence of the labels.
// These can be fast-path'd during lookup and don't need to be added to the
// tables.
// We use uint16_t to save space for sequential_value_limit_, so stop before
// overflowing it. Worst case, we are not taking full advantage on huge
// enums, but it is unlikely.
for (int i = 0;
i < std::numeric_limits<uint16_t>::max() && i < proto.value_size() &&
// We do the math in int64_t to avoid overflows.
proto.value(i).number() ==
static_cast<int64_t>(i) + proto.value(0).number();
++i) {
result->sequential_value_limit_ = i;
}
BUILD_ARRAY(proto, result, value, BuildEnumValue, result);
BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result);

@ -542,8 +542,18 @@ class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase {
bool is_placeholder_ : 1;
// True if this is a placeholder and the type name wasn't fully-qualified.
bool is_unqualified_placeholder_ : 1;
// Well known type. Stored as char to conserve space.
char well_known_type_;
// Well known type. Stored like this to conserve space.
uint8_t well_known_type_ : 5;
// This points to the last field _number_ that is part of the sequence
// starting at 1, where
// `desc->field(i)->number() == i + 1`
// A value of `0` means no field matches. That is, there are no fields or the
// first field is not field `1`.
// Uses 16-bit to avoid extra padding. Unlikely to have more than 2^16
// sequentially numbered fields in a message.
uint16_t sequential_field_limit_;
int field_count_;
// all_names_ = [name, full_name]
@ -581,6 +591,7 @@ class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase {
friend class DescriptorPool;
friend class EnumDescriptor;
friend class FieldDescriptor;
friend class FileDescriptorTables;
friend class OneofDescriptor;
friend class MethodDescriptor;
friend class FileDescriptor;
@ -1145,6 +1156,9 @@ class PROTOBUF_EXPORT EnumDescriptor : private internal::SymbolBase {
friend class io::Printer;
friend class compiler::cpp::Formatter;
// Allow access to FindValueByNumberCreatingIfUnknown.
friend class descriptor_unittest::DescriptorTest;
// Looks up a value by number. If the value does not exist, dynamically
// creates a new EnumValueDescriptor for that value, assuming that it was
// unknown. If a new descriptor is created, this is done in a thread-safe way,
@ -1165,9 +1179,18 @@ class PROTOBUF_EXPORT EnumDescriptor : private internal::SymbolBase {
void GetLocationPath(std::vector<int>* output) const;
// True if this is a placeholder for an unknown type.
bool is_placeholder_;
bool is_placeholder_ : 1;
// True if this is a placeholder and the type name wasn't fully-qualified.
bool is_unqualified_placeholder_;
bool is_unqualified_placeholder_ : 1;
// This points to the last value _index_ that is part of the sequence starting
// with the first label, where
// `enum->value(i)->number() == enum->value(0)->number() + i`
// We measure relative to the first label to adapt to enum labels starting at
// 0 or 1.
// Uses 16-bit to avoid extra padding. Unlikely to have more than 2^15
// sequentially numbered labels in an enum.
int16_t sequential_value_limit_;
int value_count_;
@ -1192,6 +1215,7 @@ class PROTOBUF_EXPORT EnumDescriptor : private internal::SymbolBase {
friend class DescriptorBuilder;
friend class Descriptor;
friend class FieldDescriptor;
friend class FileDescriptorTables;
friend class EnumValueDescriptor;
friend class FileDescriptor;
friend class DescriptorPool;

@ -3226,7 +3226,7 @@ ExtensionRangeOptions::ExtensionRangeOptions(const ExtensionRangeOptions& from)
: ::PROTOBUF_NAMESPACE_ID::Message(),
uninterpreted_option_(from.uninterpreted_option_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
// @@protoc_insertion_point(copy_constructor:google.protobuf.ExtensionRangeOptions)
}
@ -3378,7 +3378,7 @@ void ExtensionRangeOptions::MergeFrom(const ExtensionRangeOptions& from) {
(void) cached_has_bits;
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
}
@ -6135,7 +6135,7 @@ FileOptions::FileOptions(const FileOptions& from)
_has_bits_(from._has_bits_),
uninterpreted_option_(from.uninterpreted_option_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
java_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
java_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
@ -7049,7 +7049,7 @@ void FileOptions::MergeFrom(const FileOptions& from) {
}
_has_bits_[0] |= cached_has_bits;
}
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
}
@ -7178,7 +7178,7 @@ MessageOptions::MessageOptions(const MessageOptions& from)
_has_bits_(from._has_bits_),
uninterpreted_option_(from.uninterpreted_option_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
::memcpy(&message_set_wire_format_, &from.message_set_wire_format_,
static_cast<size_t>(reinterpret_cast<char*>(&map_entry_) -
reinterpret_cast<char*>(&message_set_wire_format_)) + sizeof(map_entry_));
@ -7443,7 +7443,7 @@ void MessageOptions::MergeFrom(const MessageOptions& from) {
}
_has_bits_[0] |= cached_has_bits;
}
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
}
@ -7524,7 +7524,7 @@ FieldOptions::FieldOptions(const FieldOptions& from)
_has_bits_(from._has_bits_),
uninterpreted_option_(from.uninterpreted_option_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
::memcpy(&ctype_, &from.ctype_,
static_cast<size_t>(reinterpret_cast<char*>(&jstype_) -
reinterpret_cast<char*>(&ctype_)) + sizeof(jstype_));
@ -7850,7 +7850,7 @@ void FieldOptions::MergeFrom(const FieldOptions& from) {
}
_has_bits_[0] |= cached_has_bits;
}
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
}
@ -7911,7 +7911,7 @@ OneofOptions::OneofOptions(const OneofOptions& from)
: ::PROTOBUF_NAMESPACE_ID::Message(),
uninterpreted_option_(from.uninterpreted_option_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
// @@protoc_insertion_point(copy_constructor:google.protobuf.OneofOptions)
}
@ -8063,7 +8063,7 @@ void OneofOptions::MergeFrom(const OneofOptions& from) {
(void) cached_has_bits;
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
}
@ -8125,7 +8125,7 @@ EnumOptions::EnumOptions(const EnumOptions& from)
_has_bits_(from._has_bits_),
uninterpreted_option_(from.uninterpreted_option_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
::memcpy(&allow_alias_, &from.allow_alias_,
static_cast<size_t>(reinterpret_cast<char*>(&deprecated_) -
reinterpret_cast<char*>(&allow_alias_)) + sizeof(deprecated_));
@ -8344,7 +8344,7 @@ void EnumOptions::MergeFrom(const EnumOptions& from) {
}
_has_bits_[0] |= cached_has_bits;
}
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
}
@ -8410,7 +8410,7 @@ EnumValueOptions::EnumValueOptions(const EnumValueOptions& from)
_has_bits_(from._has_bits_),
uninterpreted_option_(from.uninterpreted_option_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
deprecated_ = from.deprecated_;
// @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueOptions)
}
@ -8593,7 +8593,7 @@ void EnumValueOptions::MergeFrom(const EnumValueOptions& from) {
if (from._internal_has_deprecated()) {
_internal_set_deprecated(from._internal_deprecated());
}
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
}
@ -8654,7 +8654,7 @@ ServiceOptions::ServiceOptions(const ServiceOptions& from)
_has_bits_(from._has_bits_),
uninterpreted_option_(from.uninterpreted_option_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
deprecated_ = from.deprecated_;
// @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceOptions)
}
@ -8837,7 +8837,7 @@ void ServiceOptions::MergeFrom(const ServiceOptions& from) {
if (from._internal_has_deprecated()) {
_internal_set_deprecated(from._internal_deprecated());
}
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
}
@ -8901,7 +8901,7 @@ MethodOptions::MethodOptions(const MethodOptions& from)
_has_bits_(from._has_bits_),
uninterpreted_option_(from.uninterpreted_option_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
::memcpy(&deprecated_, &from.deprecated_,
static_cast<size_t>(reinterpret_cast<char*>(&idempotency_level_) -
reinterpret_cast<char*>(&deprecated_)) + sizeof(idempotency_level_));
@ -9129,7 +9129,7 @@ void MethodOptions::MergeFrom(const MethodOptions& from) {
}
_has_bits_[0] |= cached_has_bits;
}
_extensions_.MergeFrom(from._extensions_);
_extensions_.MergeFrom(internal_default_instance(), from._extensions_);
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
}

File diff suppressed because it is too large Load Diff

@ -776,6 +776,11 @@ class DescriptorTest : public testing::Test {
message->CopyJsonNameTo(proto);
}
const EnumValueDescriptor* FindValueByNumberCreatingIfUnknown(
const EnumDescriptor* desc, int number) {
return desc->FindValueByNumberCreatingIfUnknown(number);
}
DescriptorPool pool_;
const FileDescriptor* foo_file_;
@ -2942,6 +2947,8 @@ TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) {
EXPECT_EQ("Qux", qux_type->name());
EXPECT_EQ("corge.Qux", qux_type->full_name());
EXPECT_TRUE(qux_type->is_placeholder());
// Placeholder enum values should not be findable.
EXPECT_EQ(qux_type->FindValueByNumber(0), nullptr);
// Placeholder types should not be findable.
EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name()));
@ -3142,6 +3149,7 @@ TEST(CustomOptions, OptionLocations) {
const FileDescriptor* file = message->file();
const FieldDescriptor* field = message->FindFieldByName("field1");
const OneofDescriptor* oneof = message->FindOneofByName("AnOneof");
const FieldDescriptor* map_field = message->FindFieldByName("map_field");
const EnumDescriptor* enm = message->FindEnumTypeByName("AnEnum");
// TODO(benjy): Support EnumValue options, once the compiler does.
const ServiceDescriptor* service =
@ -3157,6 +3165,8 @@ TEST(CustomOptions, OptionLocations) {
EXPECT_EQ(42, // Check that we get the default for an option we don't set.
field->options().GetExtension(protobuf_unittest::field_opt2));
EXPECT_EQ(-99, oneof->options().GetExtension(protobuf_unittest::oneof_opt1));
EXPECT_EQ(int64_t{12345},
map_field->options().GetExtension(protobuf_unittest::field_opt1));
EXPECT_EQ(-789, enm->options().GetExtension(protobuf_unittest::enum_opt1));
EXPECT_EQ(123, enm->value(1)->options().GetExtension(
protobuf_unittest::enum_value_opt1));

@ -139,11 +139,7 @@ class PROTOBUF_EXPORT Duration final :
// implements Message ----------------------------------------------
inline Duration* New() const final {
return new Duration();
}
Duration* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
Duration* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<Duration>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -167,6 +163,8 @@ class PROTOBUF_EXPORT Duration final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(Duration* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.Duration";

@ -246,7 +246,6 @@ class DynamicMessage : public Message {
// implements Message ----------------------------------------------
Message* New() const override;
Message* New(Arena* arena) const override;
int GetCachedSize() const override;
@ -645,8 +644,6 @@ void DynamicMessage::CrossLinkPrototypes() {
}
}
Message* DynamicMessage::New() const { return New(nullptr); }
Message* DynamicMessage::New(Arena* arena) const {
if (arena != nullptr) {
void* new_base = Arena::CreateArray<char>(arena, type_info_->size);
@ -747,9 +744,9 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
// hasbits.
type_info->has_bits_offset = size;
uint32_t* has_bits_indices = new uint32_t[type->field_count()];
for (int i = 0; i < type->field_count(); i++) {
for (int j = 0; j < type->field_count(); j++) {
// Initialize to -1, fields that need a hasbit will overwrite.
has_bits_indices[i] = static_cast<uint32_t>(-1);
has_bits_indices[j] = static_cast<uint32_t>(-1);
}
type_info->has_bits_indices.reset(has_bits_indices);
}

@ -139,11 +139,7 @@ class PROTOBUF_EXPORT Empty final :
// implements Message ----------------------------------------------
inline Empty* New() const final {
return new Empty();
}
Empty* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
Empty* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<Empty>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::CopyFrom;
@ -155,6 +151,8 @@ class PROTOBUF_EXPORT Empty final :
::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::MergeImpl(this, from);
}
public:
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.Empty";

@ -0,0 +1,91 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__
#define GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__
#include <stdint.h>
#include <utility>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
// clang-format off
#include <google/protobuf/port_def.inc>
// clang-format on
namespace google {
namespace protobuf {
namespace internal {
// Wraps a variable whose constructor and destructor are explicitly
// called. It is particularly useful for a global variable, without its
// constructor and destructor run on start and end of the program lifetime.
// This circumvents the initial construction order fiasco, while keeping
// the address of the empty string a compile time constant.
//
// Pay special attention to the initialization state of the object.
// 1. The object is "uninitialized" to begin with.
// 2. Call Construct() or DefaultConstruct() only if the object is
// uninitialized. After the call, the object becomes "initialized".
// 3. Call get() and get_mutable() only if the object is initialized.
// 4. Call Destruct() only if the object is initialized.
// After the call, the object becomes uninitialized.
template <typename T>
class ExplicitlyConstructed {
public:
void DefaultConstruct() { new (&union_) T(); }
template <typename... Args>
void Construct(Args&&... args) {
new (&union_) T(std::forward<Args>(args)...);
}
void Destruct() { get_mutable()->~T(); }
constexpr const T& get() const { return reinterpret_cast<const T&>(union_); }
T* get_mutable() { return reinterpret_cast<T*>(&union_); }
private:
union AlignedUnion {
alignas(T) char space[sizeof(T)];
int64_t align_to_int64;
void* align_to_ptr;
} union_;
};
} // namespace internal
} // namespace protobuf
} // namespace google
#include <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__

@ -969,7 +969,8 @@ size_t SizeOfUnion(ItX it_xs, ItX end_xs, ItY it_ys, ItY end_ys) {
}
} // namespace
void ExtensionSet::MergeFrom(const ExtensionSet& other) {
void ExtensionSet::MergeFrom(const MessageLite* extendee,
const ExtensionSet& other) {
if (PROTOBUF_PREDICT_TRUE(!is_large())) {
if (PROTOBUF_PREDICT_TRUE(!other.is_large())) {
GrowCapacity(SizeOfUnion(flat_begin(), flat_end(), other.flat_begin(),
@ -980,12 +981,13 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) {
other.map_.large->end()));
}
}
other.ForEach([this, &other](int number, const Extension& ext) {
this->InternalExtensionMergeFrom(number, ext, other.arena_);
other.ForEach([extendee, this, &other](int number, const Extension& ext) {
this->InternalExtensionMergeFrom(extendee, number, ext, other.arena_);
});
}
void ExtensionSet::InternalExtensionMergeFrom(int number,
void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee,
int number,
const Extension& other_extension,
Arena* other_arena) {
if (other_extension.is_repeated) {
@ -1084,6 +1086,7 @@ void ExtensionSet::InternalExtensionMergeFrom(int number,
extension->lazymessage_value =
other_extension.lazymessage_value->New(arena_);
extension->lazymessage_value->MergeFrom(
GetPrototypeForLazyMessage(extendee, number),
*other_extension.lazymessage_value, arena_);
} else {
extension->is_lazy = false;
@ -1099,6 +1102,7 @@ void ExtensionSet::InternalExtensionMergeFrom(int number,
if (other_extension.is_lazy) {
if (extension->is_lazy) {
extension->lazymessage_value->MergeFrom(
GetPrototypeForLazyMessage(extendee, number),
*other_extension.lazymessage_value, arena_);
} else {
extension->message_value->CheckTypeAndMergeFrom(
@ -1124,23 +1128,23 @@ void ExtensionSet::InternalExtensionMergeFrom(int number,
}
}
void ExtensionSet::Swap(ExtensionSet* x) {
void ExtensionSet::Swap(const MessageLite* extendee, ExtensionSet* other) {
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() != nullptr && GetArena() == x->GetArena()) {
if (GetArena() != nullptr && GetArena() == other->GetArena()) {
#else // PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() == x->GetArena()) {
if (GetArena() == other->GetArena()) {
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
InternalSwap(x);
InternalSwap(other);
} else {
// TODO(cfallin, rohananil): We maybe able to optimize a case where we are
// swapping from heap to arena-allocated extension set, by just Own()'ing
// the extensions.
ExtensionSet extension_set;
extension_set.MergeFrom(*x);
x->Clear();
x->MergeFrom(*this);
extension_set.MergeFrom(extendee, *other);
other->Clear();
other->MergeFrom(extendee, *this);
Clear();
MergeFrom(extension_set);
MergeFrom(extendee, extension_set);
}
}
@ -1152,7 +1156,8 @@ void ExtensionSet::InternalSwap(ExtensionSet* other) {
swap(map_, other->map_);
}
void ExtensionSet::SwapExtension(ExtensionSet* other, int number) {
void ExtensionSet::SwapExtension(const MessageLite* extendee,
ExtensionSet* other, int number) {
if (this == other) return;
if (GetArena() == other->GetArena()) {
@ -1172,19 +1177,22 @@ void ExtensionSet::SwapExtension(ExtensionSet* other, int number) {
// We do it this way to reuse the copy-across-arenas logic already
// implemented in ExtensionSet's MergeFrom.
ExtensionSet temp;
temp.InternalExtensionMergeFrom(number, *other_ext, other->GetArena());
temp.InternalExtensionMergeFrom(extendee, number, *other_ext,
other->GetArena());
Extension* temp_ext = temp.FindOrNull(number);
other_ext->Clear();
other->InternalExtensionMergeFrom(number, *this_ext, this->GetArena());
other->InternalExtensionMergeFrom(extendee, number, *this_ext,
this->GetArena());
this_ext->Clear();
InternalExtensionMergeFrom(number, *temp_ext, temp.GetArena());
InternalExtensionMergeFrom(extendee, number, *temp_ext, temp.GetArena());
} else if (this_ext == nullptr) {
InternalExtensionMergeFrom(number, *other_ext, other->GetArena());
InternalExtensionMergeFrom(extendee, number, *other_ext, other->GetArena());
if (other->GetArena() == nullptr) other_ext->Free();
other->Erase(number);
} else {
other->InternalExtensionMergeFrom(number, *this_ext, this->GetArena());
other->InternalExtensionMergeFrom(extendee, number, *this_ext,
this->GetArena());
if (GetArena() == nullptr) this_ext->Free();
Erase(number);
}

@ -289,12 +289,12 @@ class PROTOBUF_EXPORT ExtensionSet {
void UnsafeArenaSetAllocatedMessage(int number, FieldType type,
const FieldDescriptor* descriptor,
MessageLite* message);
PROTOBUF_MUST_USE_RESULT MessageLite* ReleaseMessage(
int number, const MessageLite& prototype);
PROTOBUF_NODISCARD MessageLite* ReleaseMessage(int number,
const MessageLite& prototype);
MessageLite* UnsafeArenaReleaseMessage(int number,
const MessageLite& prototype);
PROTOBUF_MUST_USE_RESULT MessageLite* ReleaseMessage(
PROTOBUF_NODISCARD MessageLite* ReleaseMessage(
const FieldDescriptor* descriptor, MessageFactory* factory);
MessageLite* UnsafeArenaReleaseMessage(const FieldDescriptor* descriptor,
MessageFactory* factory);
@ -364,7 +364,7 @@ class PROTOBUF_EXPORT ExtensionSet {
#undef desc
void RemoveLast(int number);
PROTOBUF_MUST_USE_RESULT MessageLite* ReleaseLast(int number);
PROTOBUF_NODISCARD MessageLite* ReleaseLast(int number);
MessageLite* UnsafeArenaReleaseLast(int number);
void SwapElements(int number, int index1, int index2);
@ -378,10 +378,11 @@ class PROTOBUF_EXPORT ExtensionSet {
// class, but providing them here helps keep the generated code size down.
void Clear();
void MergeFrom(const ExtensionSet& other);
void Swap(ExtensionSet* other);
void MergeFrom(const MessageLite* extendee, const ExtensionSet& other);
void Swap(const MessageLite* extendee, ExtensionSet* other);
void InternalSwap(ExtensionSet* other);
void SwapExtension(ExtensionSet* other, int number);
void SwapExtension(const MessageLite* extendee, ExtensionSet* other,
int number);
void UnsafeShallowSwapExtension(ExtensionSet* other, int number);
bool IsInitialized() const;
@ -583,7 +584,7 @@ class PROTOBUF_EXPORT ExtensionSet {
virtual void SetAllocatedMessage(MessageLite* message, Arena* arena) = 0;
virtual void UnsafeArenaSetAllocatedMessage(MessageLite* message,
Arena* arena) = 0;
virtual PROTOBUF_MUST_USE_RESULT MessageLite* ReleaseMessage(
PROTOBUF_NODISCARD virtual MessageLite* ReleaseMessage(
const MessageLite& prototype, Arena* arena) = 0;
virtual MessageLite* UnsafeArenaReleaseMessage(const MessageLite& prototype,
Arena* arena) = 0;
@ -595,13 +596,15 @@ class PROTOBUF_EXPORT ExtensionSet {
virtual size_t ByteSizeLong() const = 0;
virtual size_t SpaceUsedLong() const = 0;
virtual void MergeFrom(const LazyMessageExtension& other, Arena* arena) = 0;
virtual void MergeFrom(const MessageLite* prototype,
const LazyMessageExtension& other, Arena* arena) = 0;
virtual void MergeFromMessage(const MessageLite& msg, Arena* arena) = 0;
virtual void Clear() = 0;
virtual bool ReadMessage(const MessageLite& prototype,
io::CodedInputStream* input) = 0;
virtual const char* _InternalParse(const char* ptr, ParseContext* ctx) = 0;
virtual const char* _InternalParse(const Message& prototype, Arena* arena,
const char* ptr, ParseContext* ctx) = 0;
virtual uint8_t* WriteMessageToArray(
const MessageLite* prototype, int number, uint8_t* target,
io::EpsCopyOutputStream* stream) const = 0;
@ -770,7 +773,8 @@ class PROTOBUF_EXPORT ExtensionSet {
}
// Merges existing Extension from other_extension
void InternalExtensionMergeFrom(int number, const Extension& other_extension,
void InternalExtensionMergeFrom(const MessageLite* extendee, int number,
const Extension& other_extension,
Arena* other_arena);
// Returns true and fills field_number and extension if extension is found.
@ -1374,8 +1378,8 @@ class MessageTypeTraits {
ExtensionSet* set) {
set->UnsafeArenaSetAllocatedMessage(number, field_type, nullptr, message);
}
static inline PROTOBUF_MUST_USE_RESULT MutableType
Release(int number, FieldType /* field_type */, ExtensionSet* set) {
PROTOBUF_NODISCARD static inline MutableType Release(
int number, FieldType /* field_type */, ExtensionSet* set) {
return static_cast<Type*>(
set->ReleaseMessage(number, Type::default_instance()));
}

@ -139,11 +139,7 @@ class PROTOBUF_EXPORT FieldMask final :
// implements Message ----------------------------------------------
inline FieldMask* New() const final {
return new FieldMask();
}
FieldMask* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
FieldMask* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<FieldMask>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -167,6 +163,8 @@ class PROTOBUF_EXPORT FieldMask final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(FieldMask* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.FieldMask";

@ -995,6 +995,8 @@ void Reflection::SwapFieldsImpl(
GOOGLE_DCHECK(!unsafe_shallow_swap || message1->GetArenaForAllocation() ==
message2->GetArenaForAllocation());
const Message* prototype =
message_factory_->GetPrototype(message1->GetDescriptor());
for (const auto* field : fields) {
CheckInvalidAccess(schema_, field);
if (field->is_extension()) {
@ -1003,7 +1005,7 @@ void Reflection::SwapFieldsImpl(
MutableExtensionSet(message2), field->number());
} else {
MutableExtensionSet(message1)->SwapExtension(
MutableExtensionSet(message2), field->number());
prototype, MutableExtensionSet(message2), field->number());
}
} else {
if (schema_.InRealOneof(field)) {

@ -343,9 +343,6 @@ class RepeatedMessageTypeHandler {
typedef MessageLite Type;
typedef MessageLite WeakType;
static Arena* GetArena(Type* t) { return t->GetArena(); }
static void* GetMaybeArenaPointer(Type* t) {
return t->GetMaybeArenaPointer();
}
static inline Type* NewFromPrototype(const Type* prototype,
Arena* arena = nullptr) {
return prototype->New(arena);

@ -701,13 +701,13 @@ uint8_t* SerializeInternalToArray(const uint8_t* base,
// Special cases
case FieldMetadata::kSpecial: {
io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX);
io::CodedOutputStream output(&array_stream);
output.SetSerializationDeterministic(is_deterministic);
io::CodedOutputStream output_stream(&array_stream);
output_stream.SetSerializationDeterministic(is_deterministic);
func = reinterpret_cast<SpecialSerializer>(
const_cast<void*>(field_metadata.ptr));
func(base, field_metadata.offset, field_metadata.tag,
field_metadata.has_offset, &output);
array_output.ptr += output.ByteCount();
field_metadata.has_offset, &output_stream);
array_output.ptr += output_stream.ByteCount();
} break;
default:
// __builtin_unreachable()

@ -63,7 +63,6 @@ class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite {
std::string GetTypeName() const override { return ""; }
MessageLite* New() const override { return new ImplicitWeakMessage; }
MessageLite* New(Arena* arena) const override {
return Arena::CreateMessage<ImplicitWeakMessage>(arena);
}
@ -115,9 +114,6 @@ class ImplicitWeakTypeHandler {
static inline Arena* GetArena(MessageLite* value) {
return value->GetArena();
}
static inline void* GetMaybeArenaPointer(MessageLite* value) {
return value->GetArena();
}
static inline void Clear(MessageLite* value) { value->Clear(); }
static void Merge(const MessageLite& from, MessageLite* to) {
to->CheckTypeAndMergeFrom(from);

@ -202,9 +202,9 @@ class PROTOBUF_EXPORT InlinedStringField {
// 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_MUST_USE_RESULT std::string* Release(
const std::string* default_value, Arena* arena, bool donated);
PROTOBUF_MUST_USE_RESULT std::string* ReleaseNonDefault(
PROTOBUF_NODISCARD std::string* Release(const std::string* default_value,
Arena* arena, bool donated);
PROTOBUF_NODISCARD std::string* ReleaseNonDefault(
const std::string* default_value, Arena* arena);
std::string* ReleaseNonDefaultNoArena(const std::string* default_value);

@ -242,10 +242,10 @@ class PROTOBUF_EXPORT CodedInputStream {
// responsible for ensuring that the buffer has sufficient space.
// Read a 32-bit little-endian integer.
static const uint8_t* ReadLittleEndian32FromArray(const uint8_t* buffer,
uint32_t* value);
uint32_t* value);
// Read a 64-bit little-endian integer.
static const uint8_t* ReadLittleEndian64FromArray(const uint8_t* buffer,
uint64_t* value);
uint64_t* value);
// Read an unsigned integer with Varint encoding, truncating to 32 bits.
// Reading a 32-bit value is equivalent to reading a 64-bit one and casting
@ -315,7 +315,7 @@ class PROTOBUF_EXPORT CodedInputStream {
// was not.
PROTOBUF_ALWAYS_INLINE
static const uint8_t* ExpectTagFromArray(const uint8_t* buffer,
uint32_t expected);
uint32_t expected);
// Usually returns true if no more bytes can be read. Always returns false
// if more bytes can be read. If ExpectAtEnd() returns true, a subsequent
@ -688,7 +688,7 @@ class PROTOBUF_EXPORT EpsCopyOutputStream {
// After this it's guaranteed you can safely write kSlopBytes to ptr. This
// will never fail! The underlying stream can produce an error. Use HadError
// to check for errors.
PROTOBUF_MUST_USE_RESULT uint8_t* EnsureSpace(uint8_t* ptr) {
PROTOBUF_NODISCARD uint8_t* EnsureSpace(uint8_t* ptr) {
if (PROTOBUF_PREDICT_FALSE(ptr >= end_)) {
return EnsureSpaceFallback(ptr);
}
@ -715,7 +715,8 @@ class PROTOBUF_EXPORT EpsCopyOutputStream {
}
uint8_t* WriteStringMaybeAliased(uint32_t num, const std::string& s, uint8_t* ptr) {
uint8_t* WriteStringMaybeAliased(uint32_t num, const std::string& s,
uint8_t* ptr) {
std::ptrdiff_t size = s.size();
if (PROTOBUF_PREDICT_FALSE(
size >= 128 || end_ - ptr + 16 - TagSize(num << 3) - 1 < size)) {
@ -726,13 +727,14 @@ class PROTOBUF_EXPORT EpsCopyOutputStream {
std::memcpy(ptr, s.data(), size);
return ptr + size;
}
uint8_t* WriteBytesMaybeAliased(uint32_t num, const std::string& s, uint8_t* ptr) {
uint8_t* WriteBytesMaybeAliased(uint32_t num, const std::string& s,
uint8_t* ptr) {
return WriteStringMaybeAliased(num, s, ptr);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteString(uint32_t num, const T& s,
uint8_t* ptr) {
uint8_t* ptr) {
std::ptrdiff_t size = s.size();
if (PROTOBUF_PREDICT_FALSE(
size >= 128 || end_ - ptr + 16 - TagSize(num << 3) - 1 < size)) {
@ -749,44 +751,44 @@ class PROTOBUF_EXPORT EpsCopyOutputStream {
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteInt32Packed(int num, const T& r, int size,
uint8_t* ptr) {
PROTOBUF_ALWAYS_INLINE uint8_t* WriteInt32Packed(int num, const T& r,
int size, uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, Encode64);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteUInt32Packed(int num, const T& r, int size,
uint8_t* ptr) {
PROTOBUF_ALWAYS_INLINE uint8_t* WriteUInt32Packed(int num, const T& r,
int size, uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, Encode32);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteSInt32Packed(int num, const T& r, int size,
uint8_t* ptr) {
PROTOBUF_ALWAYS_INLINE uint8_t* WriteSInt32Packed(int num, const T& r,
int size, uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, ZigZagEncode32);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteInt64Packed(int num, const T& r, int size,
uint8_t* ptr) {
PROTOBUF_ALWAYS_INLINE uint8_t* WriteInt64Packed(int num, const T& r,
int size, uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, Encode64);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteUInt64Packed(int num, const T& r, int size,
uint8_t* ptr) {
PROTOBUF_ALWAYS_INLINE uint8_t* WriteUInt64Packed(int num, const T& r,
int size, uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, Encode64);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteSInt64Packed(int num, const T& r, int size,
uint8_t* ptr) {
PROTOBUF_ALWAYS_INLINE uint8_t* WriteSInt64Packed(int num, const T& r,
int size, uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, ZigZagEncode64);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteEnumPacked(int num, const T& r, int size,
uint8_t* ptr) {
uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, Encode64);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteFixedPacked(int num, const T& r,
uint8_t* ptr) {
uint8_t* ptr) {
ptr = EnsureSpace(ptr);
constexpr auto element_size = sizeof(typename T::value_type);
auto size = r.size() * element_size;
@ -857,13 +859,14 @@ class PROTOBUF_EXPORT EpsCopyOutputStream {
: 5;
}
PROTOBUF_ALWAYS_INLINE uint8_t* WriteTag(uint32_t num, uint32_t wt, uint8_t* ptr) {
PROTOBUF_ALWAYS_INLINE uint8_t* WriteTag(uint32_t num, uint32_t wt,
uint8_t* ptr) {
GOOGLE_DCHECK(ptr < end_); // NOLINT
return UnsafeVarint((num << 3) | wt, ptr);
}
PROTOBUF_ALWAYS_INLINE uint8_t* WriteLengthDelim(int num, uint32_t size,
uint8_t* ptr) {
uint8_t* ptr) {
ptr = WriteTag(num, 2, ptr);
return UnsafeWriteSize(size, ptr);
}
@ -873,12 +876,13 @@ class PROTOBUF_EXPORT EpsCopyOutputStream {
uint8_t* WriteAliasedRaw(const void* data, int size, uint8_t* ptr);
uint8_t* WriteStringMaybeAliasedOutline(uint32_t num, const std::string& s,
uint8_t* ptr);
uint8_t* ptr);
uint8_t* WriteStringOutline(uint32_t num, const std::string& s, uint8_t* ptr);
template <typename T, typename E>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteVarintPacked(int num, const T& r, int size,
uint8_t* ptr, const E& encode) {
PROTOBUF_ALWAYS_INLINE uint8_t* WriteVarintPacked(int num, const T& r,
int size, uint8_t* ptr,
const E& encode) {
ptr = EnsureSpace(ptr);
ptr = WriteLengthDelim(num, size, ptr);
auto it = r.data();
@ -926,7 +930,7 @@ class PROTOBUF_EXPORT EpsCopyOutputStream {
}
PROTOBUF_ALWAYS_INLINE static uint8_t* UnsafeWriteSize(uint32_t value,
uint8_t* ptr) {
uint8_t* ptr) {
while (PROTOBUF_PREDICT_FALSE(value >= 0x80)) {
*ptr = static_cast<uint8_t>(value | 0x80);
value >>= 7;
@ -977,14 +981,14 @@ class PROTOBUF_EXPORT EpsCopyOutputStream {
template <>
inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<1>(const void* data,
int size,
uint8_t* ptr) {
int size,
uint8_t* ptr) {
return WriteRaw(data, size, ptr);
}
template <>
inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<4>(const void* data,
int size,
uint8_t* ptr) {
int size,
uint8_t* ptr) {
#ifdef PROTOBUF_LITTLE_ENDIAN
return WriteRaw(data, size, ptr);
#else
@ -993,8 +997,8 @@ inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<4>(const void* data,
}
template <>
inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<8>(const void* data,
int size,
uint8_t* ptr) {
int size,
uint8_t* ptr) {
#ifdef PROTOBUF_LITTLE_ENDIAN
return WriteRaw(data, size, ptr);
#else
@ -1118,7 +1122,8 @@ class PROTOBUF_EXPORT CodedOutputStream {
// copy loops. Since this gets called by every field with string or bytes
// type, inlining may lead to a significant amount of code bloat, with only a
// minor performance gain.
static uint8_t* WriteRawToArray(const void* buffer, int size, uint8_t* target);
static uint8_t* WriteRawToArray(const void* buffer, int size,
uint8_t* target);
// Equivalent to WriteRaw(str.data(), str.size()).
void WriteString(const std::string& str);
@ -1126,7 +1131,7 @@ class PROTOBUF_EXPORT CodedOutputStream {
static uint8_t* WriteStringToArray(const std::string& str, uint8_t* target);
// Write the varint-encoded size of str followed by str.
static uint8_t* WriteStringWithSizeToArray(const std::string& str,
uint8_t* target);
uint8_t* target);
// Write a 32-bit little-endian integer.
@ -1150,9 +1155,10 @@ class PROTOBUF_EXPORT CodedOutputStream {
void WriteVarint32(uint32_t value);
// Like WriteVarint32() but writing directly to the target array.
static uint8_t* WriteVarint32ToArray(uint32_t value, uint8_t* target);
// Like WriteVarint32() but writing directly to the target array, and with the
// less common-case paths being out of line rather than inlined.
static uint8_t* WriteVarint32ToArrayOutOfLine(uint32_t value, uint8_t* target);
// Like WriteVarint32() but writing directly to the target array, and with
// the less common-case paths being out of line rather than inlined.
static uint8_t* WriteVarint32ToArrayOutOfLine(uint32_t value,
uint8_t* target);
// Write an unsigned integer with Varint encoding.
void WriteVarint64(uint64_t value);
// Like WriteVarint64() but writing directly to the target array.
@ -1162,7 +1168,8 @@ class PROTOBUF_EXPORT CodedOutputStream {
// in which case it must be sign-extended to a full 10 bytes.
void WriteVarint32SignExtended(int32_t value);
// Like WriteVarint32SignExtended() but writing directly to the target array.
static uint8_t* WriteVarint32SignExtendedToArray(int32_t value, uint8_t* target);
static uint8_t* WriteVarint32SignExtendedToArray(int32_t value,
uint8_t* target);
// This is identical to WriteVarint32(), but optimized for writing tags.
// In particular, if the input is a compile-time constant, this method
@ -1273,7 +1280,8 @@ class PROTOBUF_EXPORT CodedOutputStream {
default_serialization_deterministic_.store(true, std::memory_order_relaxed);
}
// REQUIRES: value >= 0x80, and that (value & 7f) has been written to *target.
static uint8_t* WriteVarint32ToArrayOutOfLineHelper(uint32_t value, uint8_t* target);
static uint8_t* WriteVarint32ToArrayOutOfLineHelper(uint32_t value,
uint8_t* target);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream);
};
@ -1342,13 +1350,13 @@ inline const uint8_t* CodedInputStream::ReadLittleEndian64FromArray(
return buffer + sizeof(*value);
#else
uint32_t part0 = (static_cast<uint32_t>(buffer[0])) |
(static_cast<uint32_t>(buffer[1]) << 8) |
(static_cast<uint32_t>(buffer[2]) << 16) |
(static_cast<uint32_t>(buffer[3]) << 24);
(static_cast<uint32_t>(buffer[1]) << 8) |
(static_cast<uint32_t>(buffer[2]) << 16) |
(static_cast<uint32_t>(buffer[3]) << 24);
uint32_t part1 = (static_cast<uint32_t>(buffer[4])) |
(static_cast<uint32_t>(buffer[5]) << 8) |
(static_cast<uint32_t>(buffer[6]) << 16) |
(static_cast<uint32_t>(buffer[7]) << 24);
(static_cast<uint32_t>(buffer[5]) << 8) |
(static_cast<uint32_t>(buffer[6]) << 16) |
(static_cast<uint32_t>(buffer[7]) << 24);
*value = static_cast<uint64_t>(part0) | (static_cast<uint64_t>(part1) << 32);
return buffer + sizeof(*value);
#endif
@ -1465,8 +1473,8 @@ inline bool CodedInputStream::ExpectTag(uint32_t expected) {
}
}
inline const uint8_t* CodedInputStream::ExpectTagFromArray(const uint8_t* buffer,
uint32_t expected) {
inline const uint8_t* CodedInputStream::ExpectTagFromArray(
const uint8_t* buffer, uint32_t expected) {
if (expected < (1 << 7)) {
if (buffer[0] == expected) {
return buffer + 1;
@ -1600,7 +1608,7 @@ inline bool CodedInputStream::Skip(int count) {
}
inline uint8_t* CodedOutputStream::WriteVarint32ToArray(uint32_t value,
uint8_t* target) {
uint8_t* target) {
return EpsCopyOutputStream::UnsafeVarint(value, target);
}
@ -1615,7 +1623,7 @@ inline uint8_t* CodedOutputStream::WriteVarint32ToArrayOutOfLine(
}
inline uint8_t* CodedOutputStream::WriteVarint64ToArray(uint64_t value,
uint8_t* target) {
uint8_t* target) {
return EpsCopyOutputStream::UnsafeVarint(value, target);
}
@ -1629,7 +1637,7 @@ inline uint8_t* CodedOutputStream::WriteVarint32SignExtendedToArray(
}
inline uint8_t* CodedOutputStream::WriteLittleEndian32ToArray(uint32_t value,
uint8_t* target) {
uint8_t* target) {
#if defined(PROTOBUF_LITTLE_ENDIAN)
memcpy(target, &value, sizeof(value));
#else
@ -1642,7 +1650,7 @@ inline uint8_t* CodedOutputStream::WriteLittleEndian32ToArray(uint32_t value,
}
inline uint8_t* CodedOutputStream::WriteLittleEndian64ToArray(uint64_t value,
uint8_t* target) {
uint8_t* target) {
#if defined(PROTOBUF_LITTLE_ENDIAN)
memcpy(target, &value, sizeof(value));
#else
@ -1716,7 +1724,8 @@ inline size_t CodedOutputStream::VarintSize32SignExtended(int32_t value) {
return VarintSize64(static_cast<uint64_t>(int64_t{value}));
}
inline size_t CodedOutputStream::VarintSize32SignExtendedPlusOne(int32_t value) {
inline size_t CodedOutputStream::VarintSize32SignExtendedPlusOne(
int32_t value) {
return VarintSize64PlusOne(static_cast<uint64_t>(int64_t{value}));
}
@ -1730,13 +1739,13 @@ inline void CodedOutputStream::WriteRawMaybeAliased(const void* data,
}
inline uint8_t* CodedOutputStream::WriteRawToArray(const void* data, int size,
uint8_t* target) {
uint8_t* target) {
memcpy(target, data, size);
return target + size;
}
inline uint8_t* CodedOutputStream::WriteStringToArray(const std::string& str,
uint8_t* target) {
uint8_t* target) {
return WriteRawToArray(str.data(), static_cast<int>(str.size()), target);
}

@ -286,11 +286,6 @@ class MapEntryImpl : public Base {
return ValueTypeHandler::IsInitialized(value_);
}
Base* New() const override {
Derived* entry = new Derived;
return entry;
}
Base* New(Arena* arena) const override {
Derived* entry = Arena::CreateMessage<Derived>(arena);
return entry;

@ -158,7 +158,7 @@ struct DescriptorTable;
class MapFieldBase;
class SwapFieldHelper;
class CachedSize;
}
} // namespace internal
class UnknownFieldSet; // unknown_field_set.h
namespace io {
class ZeroCopyInputStream; // zero_copy_stream.h
@ -169,7 +169,7 @@ class CodedOutputStream; // coded_stream.h
namespace python {
class MapReflectionFriend; // scalar_map_container.h
class MessageReflectionFriend;
}
} // namespace python
namespace expr {
class CelMapReflectionFriend; // field_backed_map_impl.cc
}
@ -244,18 +244,11 @@ class PROTOBUF_EXPORT Message : public MessageLite {
// Construct a new instance of the same type. Ownership is passed to the
// caller. (This is also defined in MessageLite, but is defined again here
// for return-type covariance.)
Message* New() const override = 0;
Message* New() const { return New(nullptr); }
// Construct a new instance on the arena. Ownership is passed to the caller
// if arena is a nullptr. Default implementation allows for API compatibility
// during the Arena transition.
Message* New(Arena* arena) const override {
Message* message = New();
if (arena != nullptr) {
arena->Own(message);
}
return message;
}
// if arena is a nullptr.
Message* New(Arena* arena) const override = 0;
// Make this message into a copy of the given message. The given message
// must have the same descriptor, but need not necessarily be the same class.
@ -507,8 +500,8 @@ class PROTOBUF_EXPORT Reflection final {
void RemoveLast(Message* message, const FieldDescriptor* field) const;
// Removes the last element of a repeated message field, and returns the
// pointer to the caller. Caller takes ownership of the returned pointer.
PROTOBUF_MUST_USE_RESULT Message* ReleaseLast(
Message* message, const FieldDescriptor* field) const;
PROTOBUF_NODISCARD Message* ReleaseLast(Message* message,
const FieldDescriptor* field) const;
// Similar to ReleaseLast() without internal safety and ownershp checks. This
// method should only be used when the objects are on the same arena or paired
@ -662,7 +655,7 @@ class PROTOBUF_EXPORT Reflection final {
// If the field existed (HasField() is true), then the returned pointer will
// be the same as the pointer returned by MutableMessage().
// This function has the same effect as ClearField().
PROTOBUF_MUST_USE_RESULT Message* ReleaseMessage(
PROTOBUF_NODISCARD Message* ReleaseMessage(
Message* message, const FieldDescriptor* field,
MessageFactory* factory = nullptr) const;

@ -195,14 +195,6 @@ template bool MergeFromImpl<true>(BoundedZCIS input, MessageLite* msg,
} // namespace internal
MessageLite* MessageLite::New(Arena* arena) const {
MessageLite* message = New();
if (arena != nullptr) {
arena->Own(message);
}
return message;
}
class ZeroCopyCodedInputStream : public io::ZeroCopyInputStream {
public:
ZeroCopyCodedInputStream(io::CodedInputStream* cis) : cis_(cis) {}

@ -46,13 +46,16 @@
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/arena.h>
#include <google/protobuf/explicitly_constructed.h>
#include <google/protobuf/metadata_lite.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/port.h>
#include <google/protobuf/stubs/strutil.h>
// clang-format off
#include <google/protobuf/port_def.inc>
// clang-format on
#ifdef SWIG
#error "You cannot SWIG proto headers"
@ -126,43 +129,6 @@ inline int ToIntSize(size_t size) {
return static_cast<int>(size);
}
// This type wraps a variable whose constructor and destructor are explicitly
// called. It is particularly useful for a global variable, without its
// constructor and destructor run on start and end of the program lifetime.
// This circumvents the initial construction order fiasco, while keeping
// the address of the empty string a compile time constant.
//
// Pay special attention to the initialization state of the object.
// 1. The object is "uninitialized" to begin with.
// 2. Call Construct() or DefaultConstruct() only if the object is
// uninitialized. After the call, the object becomes "initialized".
// 3. Call get() and get_mutable() only if the object is initialized.
// 4. Call Destruct() only if the object is initialized.
// After the call, the object becomes uninitialized.
template <typename T>
class ExplicitlyConstructed {
public:
void DefaultConstruct() { new (&union_) T(); }
template <typename... Args>
void Construct(Args&&... args) {
new (&union_) T(std::forward<Args>(args)...);
}
void Destruct() { get_mutable()->~T(); }
constexpr const T& get() const { return reinterpret_cast<const T&>(union_); }
T* get_mutable() { return reinterpret_cast<T*>(&union_); }
private:
// Prefer c++14 aligned_storage, but for compatibility this will do.
union AlignedUnion {
alignas(T) char space[sizeof(T)];
int64_t align_to_int64;
void* align_to_ptr;
} union_;
};
// Default empty string object. Don't use this directly. Instead, call
// GetEmptyString() to get the reference.
PROTOBUF_EXPORT extern ExplicitlyConstructed<std::string>
@ -215,28 +181,15 @@ class PROTOBUF_EXPORT MessageLite {
// Construct a new instance of the same type. Ownership is passed to the
// caller.
virtual MessageLite* New() const = 0;
MessageLite* New() const { return New(nullptr); }
// Construct a new instance on the arena. Ownership is passed to the caller
// if arena is a nullptr. Default implementation for backwards compatibility.
virtual MessageLite* New(Arena* arena) const;
// if arena is a nullptr.
virtual MessageLite* New(Arena* arena) const = 0;
// Same as GetOwningArena.
Arena* GetArena() const { return GetOwningArena(); }
// Get a pointer that may be equal to this message's arena, or may not be.
// If the value returned by this method is equal to some arena pointer, then
// this message is on that arena; however, if this message is on some arena,
// this method may or may not return that arena's pointer. As a tradeoff,
// this method may be more efficient than GetArena(). The intent is to allow
// underlying representations that use e.g. tagged pointers to sometimes
// store the arena pointer directly, and sometimes in a more indirect way,
// and allow a fastpath comparison against the arena pointer when it's easy
// to obtain.
void* GetMaybeArenaPointer() const {
return _internal_metadata_.raw_arena_ptr();
}
// Clear all fields of the message and set them to their default values.
// Clear() avoids freeing memory, assuming that any memory allocated
// to hold parts of the message will be needed again to hold the next

@ -41,5 +41,8 @@
#define UNITTEST_IMPORT ::protobuf_unittest_import
// Must include after the above macros.
// clang-format off
#include <google/protobuf/test_util.inc>
#include <google/protobuf/message_unittest.inc>
#include <google/protobuf/arena.h>
// clang-format on

@ -460,7 +460,6 @@ const char* PackedBoolParser(void* object, const char* ptr, ParseContext* ctx) {
template <typename T>
const char* FixedParser(void* object, const char* ptr, ParseContext* ctx) {
int size = ReadSize(&ptr);
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
return ctx->ReadPackedFixed(ptr, size,
static_cast<RepeatedField<T>*>(object));
}

@ -125,7 +125,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
}
// If return value is negative it's an error
PROTOBUF_MUST_USE_RESULT int PushLimit(const char* ptr, int limit) {
PROTOBUF_NODISCARD int PushLimit(const char* ptr, int limit) {
GOOGLE_DCHECK(limit >= 0 && limit <= INT_MAX - kSlopBytes);
// This add is safe due to the invariant above, because
// ptr - buffer_end_ <= kSlopBytes.
@ -136,7 +136,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
return old_limit - limit;
}
PROTOBUF_MUST_USE_RESULT bool PopLimit(int delta) {
PROTOBUF_NODISCARD bool PopLimit(int delta) {
if (PROTOBUF_PREDICT_FALSE(!EndedAtLimit())) return false;
limit_ = limit_ + delta;
// TODO(gerbens) We could remove this line and hoist the code to
@ -145,22 +145,22 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
return true;
}
PROTOBUF_MUST_USE_RESULT const char* Skip(const char* ptr, int size) {
PROTOBUF_NODISCARD const char* Skip(const char* ptr, int size) {
if (size <= buffer_end_ + kSlopBytes - ptr) {
return ptr + size;
}
return SkipFallback(ptr, size);
}
PROTOBUF_MUST_USE_RESULT const char* ReadString(const char* ptr, int size,
std::string* s) {
PROTOBUF_NODISCARD const char* ReadString(const char* ptr, int size,
std::string* s) {
if (size <= buffer_end_ + kSlopBytes - ptr) {
s->assign(ptr, size);
return ptr + size;
}
return ReadStringFallback(ptr, size, s);
}
PROTOBUF_MUST_USE_RESULT const char* AppendString(const char* ptr, int size,
std::string* s) {
PROTOBUF_NODISCARD const char* AppendString(const char* ptr, int size,
std::string* s) {
if (size <= buffer_end_ + kSlopBytes - ptr) {
s->append(ptr, size);
return ptr + size;
@ -168,22 +168,20 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
return AppendStringFallback(ptr, size, s);
}
// Implemented in arenastring.cc
PROTOBUF_MUST_USE_RESULT const char* ReadArenaString(const char* ptr,
ArenaStringPtr* s,
Arena* arena);
PROTOBUF_NODISCARD const char* ReadArenaString(const char* ptr,
ArenaStringPtr* s,
Arena* arena);
template <typename Tag, typename T>
PROTOBUF_MUST_USE_RESULT const char* ReadRepeatedFixed(const char* ptr,
Tag expected_tag,
RepeatedField<T>* out);
PROTOBUF_NODISCARD const char* ReadRepeatedFixed(const char* ptr,
Tag expected_tag,
RepeatedField<T>* out);
template <typename T>
PROTOBUF_MUST_USE_RESULT const char* ReadPackedFixed(const char* ptr,
int size,
RepeatedField<T>* out);
PROTOBUF_NODISCARD const char* ReadPackedFixed(const char* ptr, int size,
RepeatedField<T>* out);
template <typename Add>
PROTOBUF_MUST_USE_RESULT const char* ReadPackedVarint(const char* ptr,
Add add);
PROTOBUF_NODISCARD const char* ReadPackedVarint(const char* ptr, Add add);
uint32_t LastTag() const { return last_tag_minus_1_ + 1; }
bool ConsumeEndGroup(uint32_t start_tag) {
@ -364,8 +362,8 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
return end;
}
PROTOBUF_MUST_USE_RESULT const char* AppendString(const char* ptr,
std::string* str) {
PROTOBUF_NODISCARD const char* AppendString(const char* ptr,
std::string* str) {
return AppendUntilEnd(
ptr, [str](const char* p, ptrdiff_t s) { str->append(p, s); });
}
@ -407,10 +405,10 @@ class PROTOBUF_EXPORT ParseContext : public EpsCopyInputStream {
template <typename T,
typename std::enable_if<!std::is_base_of<MessageLite, T>::value,
bool>::type = true>
PROTOBUF_MUST_USE_RESULT const char* ParseMessage(T* msg, const char* ptr);
PROTOBUF_NODISCARD const char* ParseMessage(T* msg, const char* ptr);
template <typename T>
PROTOBUF_MUST_USE_RESULT PROTOBUF_NDEBUG_INLINE const char* ParseGroup(
PROTOBUF_NODISCARD PROTOBUF_NDEBUG_INLINE const char* ParseGroup(
T* msg, const char* ptr, uint32_t tag) {
if (--depth_ < 0) return nullptr;
group_depth_++;
@ -430,8 +428,8 @@ class PROTOBUF_EXPORT ParseContext : public EpsCopyInputStream {
// if (!ptr) return nullptr;
// int old = PushLimit(ptr, size);
// if (--depth_ < 0) return nullptr;
PROTOBUF_MUST_USE_RESULT const char* ReadSizeAndPushLimitAndDepth(
const char* ptr, int* old_limit);
PROTOBUF_NODISCARD const char* ReadSizeAndPushLimitAndDepth(const char* ptr,
int* old_limit);
// The context keeps an internal stack to keep track of the recursive
// part of the parse state.
@ -526,7 +524,7 @@ inline const char* VarintParseSlow(const char* p, uint32_t res, uint64_t* out) {
}
template <typename T>
PROTOBUF_MUST_USE_RESULT const char* VarintParse(const char* p, T* out) {
PROTOBUF_NODISCARD const char* VarintParse(const char* p, T* out) {
auto ptr = reinterpret_cast<const uint8_t*>(p);
uint32_t res = ptr[0];
if (!(res & 0x80)) {
@ -660,8 +658,8 @@ inline int32_t ReadVarintZigZag32(const char** p) {
template <typename T, typename std::enable_if<
!std::is_base_of<MessageLite, T>::value, bool>::type>
PROTOBUF_MUST_USE_RESULT const char* ParseContext::ParseMessage(
T* msg, const char* ptr) {
PROTOBUF_NODISCARD const char* ParseContext::ParseMessage(T* msg,
const char* ptr) {
int old;
ptr = ReadSizeAndPushLimitAndDepth(ptr, &old);
ptr = ptr ? msg->_InternalParse(ptr, this) : nullptr;
@ -682,9 +680,22 @@ const char* EpsCopyInputStream::ReadRepeatedFixed(const char* ptr,
return ptr;
}
// Add any of the following lines to debug which parse function is failing.
#define GOOGLE_PROTOBUF_ASSERT_RETURN(predicate, ret) \
if (!(predicate)) { \
/* ::raise(SIGINT); */ \
/* GOOGLE_LOG(ERROR) << "Parse failure"; */ \
return ret; \
}
#define GOOGLE_PROTOBUF_PARSER_ASSERT(predicate) \
GOOGLE_PROTOBUF_ASSERT_RETURN(predicate, nullptr)
template <typename T>
const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size,
RepeatedField<T>* out) {
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
int nbytes = buffer_end_ + kSlopBytes - ptr;
while (size > nbytes) {
int num = nbytes / sizeof(T);
@ -734,7 +745,7 @@ const char* ReadPackedVarintArray(const char* ptr, const char* end, Add add) {
template <typename Add>
const char* EpsCopyInputStream::ReadPackedVarint(const char* ptr, Add add) {
int size = ReadSize(&ptr);
if (ptr == nullptr) return nullptr;
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
int chunk_size = buffer_end_ - ptr;
while (size > chunk_size) {
ptr = ReadPackedVarintArray(ptr, buffer_end_, add);
@ -776,26 +787,13 @@ inline bool VerifyUTF8(const std::string* s, const char* field_name) {
}
// All the string parsers with or without UTF checking and for all CTypes.
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* InlineGreedyStringParser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* InlineGreedyStringParser(
std::string* s, const char* ptr, ParseContext* ctx);
// Add any of the following lines to debug which parse function is failing.
#define GOOGLE_PROTOBUF_ASSERT_RETURN(predicate, ret) \
if (!(predicate)) { \
/* ::raise(SIGINT); */ \
/* GOOGLE_LOG(ERROR) << "Parse failure"; */ \
return ret; \
}
#define GOOGLE_PROTOBUF_PARSER_ASSERT(predicate) \
GOOGLE_PROTOBUF_ASSERT_RETURN(predicate, nullptr)
template <typename T>
PROTOBUF_MUST_USE_RESULT const char* FieldParser(uint64_t tag, T& field_parser,
const char* ptr,
ParseContext* ctx) {
PROTOBUF_NODISCARD const char* FieldParser(uint64_t tag, T& field_parser,
const char* ptr, ParseContext* ctx) {
uint32_t number = tag >> 3;
GOOGLE_PROTOBUF_PARSER_ASSERT(number != 0);
using WireType = internal::WireFormatLite::WireType;
@ -840,9 +838,9 @@ PROTOBUF_MUST_USE_RESULT const char* FieldParser(uint64_t tag, T& field_parser,
}
template <typename T>
PROTOBUF_MUST_USE_RESULT const char* WireFormatParser(T& field_parser,
const char* ptr,
ParseContext* ctx) {
PROTOBUF_NODISCARD const char* WireFormatParser(T& field_parser,
const char* ptr,
ParseContext* ctx) {
while (!ctx->Done(&ptr)) {
uint32_t tag;
ptr = ReadTag(ptr, &tag);
@ -861,25 +859,27 @@ PROTOBUF_MUST_USE_RESULT const char* WireFormatParser(T& field_parser,
// corresponding field
// These are packed varints
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedInt32Parser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedInt32Parser(
void* object, const char* ptr, ParseContext* ctx);
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedUInt32Parser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedUInt32Parser(
void* object, const char* ptr, ParseContext* ctx);
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedInt64Parser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedInt64Parser(
void* object, const char* ptr, ParseContext* ctx);
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedUInt64Parser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedUInt64Parser(
void* object, const char* ptr, ParseContext* ctx);
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedSInt32Parser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedSInt32Parser(
void* object, const char* ptr, ParseContext* ctx);
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedSInt64Parser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedSInt64Parser(
void* object, const char* ptr, ParseContext* ctx);
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedEnumParser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedEnumParser(
void* object, const char* ptr, ParseContext* ctx);
template <typename T>
PROTOBUF_MUST_USE_RESULT const char* PackedEnumParser(
void* object, const char* ptr, ParseContext* ctx, bool (*is_valid)(int),
InternalMetadata* metadata, int field_num) {
PROTOBUF_NODISCARD const char* PackedEnumParser(void* object, const char* ptr,
ParseContext* ctx,
bool (*is_valid)(int),
InternalMetadata* metadata,
int field_num) {
return ctx->ReadPackedVarint(
ptr, [object, is_valid, metadata, field_num](uint64_t val) {
if (is_valid(val)) {
@ -891,7 +891,7 @@ PROTOBUF_MUST_USE_RESULT const char* PackedEnumParser(
}
template <typename T>
PROTOBUF_MUST_USE_RESULT const char* PackedEnumParserArg(
PROTOBUF_NODISCARD const char* PackedEnumParserArg(
void* object, const char* ptr, ParseContext* ctx,
bool (*is_valid)(const void*, int), const void* data,
InternalMetadata* metadata, int field_num) {
@ -905,28 +905,28 @@ PROTOBUF_MUST_USE_RESULT const char* PackedEnumParserArg(
});
}
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedBoolParser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedBoolParser(
void* object, const char* ptr, ParseContext* ctx);
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedFixed32Parser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedFixed32Parser(
void* object, const char* ptr, ParseContext* ctx);
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedSFixed32Parser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedSFixed32Parser(
void* object, const char* ptr, ParseContext* ctx);
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedFixed64Parser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedFixed64Parser(
void* object, const char* ptr, ParseContext* ctx);
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedSFixed64Parser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedSFixed64Parser(
void* object, const char* ptr, ParseContext* ctx);
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedFloatParser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedFloatParser(
void* object, const char* ptr, ParseContext* ctx);
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedDoubleParser(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* PackedDoubleParser(
void* object, const char* ptr, ParseContext* ctx);
// This is the only recursive parser.
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* UnknownGroupLiteParse(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* UnknownGroupLiteParse(
std::string* unknown, const char* ptr, ParseContext* ctx);
// This is a helper to for the UnknownGroupLiteParse but is actually also
// useful in the generated code. It uses overload on std::string* vs
// UnknownFieldSet* to make the generated code isomorphic between full and lite.
PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* UnknownFieldParse(
PROTOBUF_EXPORT PROTOBUF_NODISCARD const char* UnknownFieldParse(
uint32_t tag, std::string* unknown, const char* ptr, ParseContext* ctx);
} // namespace internal

@ -293,7 +293,12 @@
#ifdef PROTOBUF_SECTION_VARIABLE
#error PROTOBUF_SECTION_VARIABLE was previously defined
#endif
#define PROTOBUF_SECTION_VARIABLE(x)
#if (__has_attribute(section) || defined(__GNUC__)) && defined(__ELF__)
// Place a variable in the given ELF section.
# define PROTOBUF_SECTION_VARIABLE(x) __attribute__((section(#x)))
#else
# define PROTOBUF_SECTION_VARIABLE(x)
#endif
#if defined(PROTOBUF_DEPRECATED)
#error PROTOBUF_DEPRECATED was previously defined
@ -451,10 +456,16 @@
# define PROTOBUF_PREDICT_FALSE(x) (x)
#endif
#ifdef PROTOBUF_MUST_USE_RESULT
#error PROTOBUF_MUST_USE_RESULT was previously defined
#ifdef PROTOBUF_NODISCARD
#error PROTOBUF_NODISCARD was previously defined
#endif
#if __has_cpp_attribute(nodiscard)
#define PROTOBUF_NODISCARD [[nodiscard]]
#elif __has_attribute(warn_unused_result) || PROTOBUF_GNUC_MIN(4, 8)
#define PROTOBUF_NODISCARD __attribute__((warn_unused_result))
#else
#define PROTOBUF_NODISCARD
#endif
# define PROTOBUF_MUST_USE_RESULT
#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
#error PROTOBUF_FORCE_COPY_IN_RELEASE was previously defined
@ -646,8 +657,17 @@
# define PROTOBUF_MSAN 1
# endif
#elif PROTOBUF_GNUC_MIN(3, 0)
# define PROTOBUF_ASAN __SANITIZE_ADDRESS__
# define PROTOBUF_TSAN __SANITIZE_THREAD__
// Double-guard is needed for -Wundef:
# ifdef __SANITIZE_ADDRESS__
# if __SANITIZE_ADDRESS__
# define PROTOBUF_ASAN 1
# endif
# endif
# ifdef __SANITIZE_THREAD__
# if __SANITIZE_THREAD__
# define PROTOBUF_TSAN 1
# endif
# endif
#endif
// Tail call table-driven parsing can be enabled by defining
@ -773,7 +793,9 @@
// To silence the fact that we will pop this push from another file
#pragma warning(disable : 5031)
// Conditional expression is constant
#pragma warning(disable : 4127)
#pragma warning(disable: 4127)
// decimal digit terminates octal escape sequence
#pragma warning(disable: 4125)
#endif
// We don't want code outside port_def doing complex testing, so

@ -63,7 +63,7 @@
#undef PROTOBUF_FALLTHROUGH_INTENDED
#undef PROTOBUF_EXPORT
#undef PROTOC_EXPORT
#undef PROTOBUF_MUST_USE_RESULT
#undef PROTOBUF_NODISCARD
#undef PROTOBUF_FORCE_COPY_IN_RELEASE
#undef PROTOBUF_FORCE_COPY_IN_SWAP
#undef PROTOBUF_FORCE_COPY_IN_MOVE

@ -214,9 +214,9 @@ bool ReflectionOps::IsInitialized(const Message& message, bool check_fields,
reflection->GetMapData(message, field);
if (map_field->IsMapValid()) {
MapIterator it(const_cast<Message*>(&message), field);
MapIterator end(const_cast<Message*>(&message), field);
for (map_field->MapBegin(&it), map_field->MapEnd(&end);
it != end; ++it) {
MapIterator end_map(const_cast<Message*>(&message), field);
for (map_field->MapBegin(&it), map_field->MapEnd(&end_map);
it != end_map; ++it) {
if (!it.GetValueRef().GetMessageValue().IsInitialized()) {
return false;
}

@ -698,7 +698,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
void UnsafeArenaAddAllocated(typename TypeHandler::Type* value);
template <typename TypeHandler>
PROTOBUF_MUST_USE_RESULT typename TypeHandler::Type* ReleaseLast() {
PROTOBUF_NODISCARD typename TypeHandler::Type* ReleaseLast() {
typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t;
return ReleaseLastInternal<TypeHandler>(t);
}
@ -712,7 +712,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
void AddCleared(typename TypeHandler::Type* value);
template <typename TypeHandler>
PROTOBUF_MUST_USE_RESULT typename TypeHandler::Type* ReleaseCleared();
PROTOBUF_NODISCARD typename TypeHandler::Type* ReleaseCleared();
template <typename TypeHandler>
void AddAllocatedInternal(typename TypeHandler::Type* value, std::true_type);
@ -1084,7 +1084,7 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase {
// If this RepeatedPtrField is on an arena, an object copy is required to pass
// ownership back to the user (for compatible semantics). Use
// UnsafeArenaReleaseLast() if this behavior is undesired.
PROTOBUF_MUST_USE_RESULT Element* ReleaseLast();
PROTOBUF_NODISCARD Element* ReleaseLast();
// Add an already-allocated object, skipping arena-ownership checks. The user
// must guarantee that the given object is in the same arena as this
@ -1155,7 +1155,7 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase {
//
// This method cannot be called when the repeated field is on an arena; doing
// so will trigger a GOOGLE_DCHECK-failure.
PROTOBUF_MUST_USE_RESULT Element* ReleaseCleared();
PROTOBUF_NODISCARD Element* ReleaseCleared();
#endif // !PROTOBUF_FUTURE_BREAKING_CHANGES
// Removes the element referenced by position.

@ -139,11 +139,7 @@ class PROTOBUF_EXPORT SourceContext final :
// implements Message ----------------------------------------------
inline SourceContext* New() const final {
return new SourceContext();
}
SourceContext* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
SourceContext* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<SourceContext>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -167,6 +163,8 @@ class PROTOBUF_EXPORT SourceContext final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(SourceContext* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.SourceContext";
@ -197,7 +195,7 @@ class PROTOBUF_EXPORT SourceContext final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_file_name(ArgT0&& arg0, ArgT... args);
std::string* mutable_file_name();
PROTOBUF_MUST_USE_RESULT std::string* release_file_name();
PROTOBUF_NODISCARD std::string* release_file_name();
void set_allocated_file_name(std::string* file_name);
private:
const std::string& _internal_file_name() const;

@ -204,11 +204,7 @@ class PROTOBUF_EXPORT Struct final :
// implements Message ----------------------------------------------
inline Struct* New() const final {
return new Struct();
}
Struct* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
Struct* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<Struct>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -232,6 +228,8 @@ class PROTOBUF_EXPORT Struct final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(Struct* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.Struct";
@ -375,11 +373,7 @@ class PROTOBUF_EXPORT Value final :
// implements Message ----------------------------------------------
inline Value* New() const final {
return new Value();
}
Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<Value>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -403,6 +397,8 @@ class PROTOBUF_EXPORT Value final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(Value* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.Value";
@ -468,7 +464,7 @@ class PROTOBUF_EXPORT Value final :
template <typename ArgT0 = const std::string&, typename... ArgT>
void set_string_value(ArgT0&& arg0, ArgT... args);
std::string* mutable_string_value();
PROTOBUF_MUST_USE_RESULT std::string* release_string_value();
PROTOBUF_NODISCARD std::string* release_string_value();
void set_allocated_string_value(std::string* string_value);
private:
const std::string& _internal_string_value() const;
@ -496,7 +492,7 @@ class PROTOBUF_EXPORT Value final :
public:
void clear_struct_value();
const ::PROTOBUF_NAMESPACE_ID::Struct& struct_value() const;
PROTOBUF_MUST_USE_RESULT ::PROTOBUF_NAMESPACE_ID::Struct* release_struct_value();
PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::Struct* release_struct_value();
::PROTOBUF_NAMESPACE_ID::Struct* mutable_struct_value();
void set_allocated_struct_value(::PROTOBUF_NAMESPACE_ID::Struct* struct_value);
private:
@ -514,7 +510,7 @@ class PROTOBUF_EXPORT Value final :
public:
void clear_list_value();
const ::PROTOBUF_NAMESPACE_ID::ListValue& list_value() const;
PROTOBUF_MUST_USE_RESULT ::PROTOBUF_NAMESPACE_ID::ListValue* release_list_value();
PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::ListValue* release_list_value();
::PROTOBUF_NAMESPACE_ID::ListValue* mutable_list_value();
void set_allocated_list_value(::PROTOBUF_NAMESPACE_ID::ListValue* list_value);
private:
@ -634,11 +630,7 @@ class PROTOBUF_EXPORT ListValue final :
// implements Message ----------------------------------------------
inline ListValue* New() const final {
return new ListValue();
}
ListValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
ListValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
return CreateMaybeMessage<ListValue>(arena);
}
using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
@ -662,6 +654,8 @@ class PROTOBUF_EXPORT ListValue final :
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(ListValue* other);
private:
friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
return "google.protobuf.ListValue";

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

Loading…
Cancel
Save