Integrated internal changes from Google

This commit is contained in:
Adam Cozzette 2018-03-13 16:37:29 -07:00
parent 96b535cc2f
commit 0400cca323
282 changed files with 15373 additions and 14191 deletions

View File

@ -243,3 +243,4 @@ public class ProtoCaliperBenchmark {
}
}

View File

@ -115,3 +115,4 @@ class Benchmark:
if __name__ == "__main__":
for i in range(2, len(sys.argv)):
run_one_test(sys.argv[i])

View File

@ -79,20 +79,6 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field.h" inc
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\service.h" include\google\protobuf\service.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.pb.h" include\google\protobuf\source_context.pb.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.pb.h" include\google\protobuf\struct.pb.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomic_sequence_num.h" include\google\protobuf\stubs\atomic_sequence_num.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops.h" include\google\protobuf\stubs\atomicops.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm64_gcc.h" include\google\protobuf\stubs\atomicops_internals_arm64_gcc.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm_gcc.h" include\google\protobuf\stubs\atomicops_internals_arm_gcc.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm_qnx.h" include\google\protobuf\stubs\atomicops_internals_arm_qnx.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_generic_c11_atomic.h" include\google\protobuf\stubs\atomicops_internals_generic_c11_atomic.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_generic_gcc.h" include\google\protobuf\stubs\atomicops_internals_generic_gcc.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_mips_gcc.h" include\google\protobuf\stubs\atomicops_internals_mips_gcc.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_power.h" include\google\protobuf\stubs\atomicops_internals_power.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_ppc_gcc.h" include\google\protobuf\stubs\atomicops_internals_ppc_gcc.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_solaris.h" include\google\protobuf\stubs\atomicops_internals_solaris.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_tsan.h" include\google\protobuf\stubs\atomicops_internals_tsan.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_x86_gcc.h" include\google\protobuf\stubs\atomicops_internals_x86_gcc.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.h" include\google\protobuf\stubs\atomicops_internals_x86_msvc.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\bytestream.h" include\google\protobuf\stubs\bytestream.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\callback.h" include\google\protobuf\stubs\callback.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\casts.h" include\google\protobuf\stubs\casts.h
@ -105,8 +91,6 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\mutex.h" includ
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\once.h" include\google\protobuf\stubs\once.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\platform_macros.h" include\google\protobuf\stubs\platform_macros.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\port.h" include\google\protobuf\stubs\port.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\scoped_ptr.h" include\google\protobuf\stubs\scoped_ptr.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\shared_ptr.h" include\google\protobuf\stubs\shared_ptr.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\singleton.h" include\google\protobuf\stubs\singleton.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\status.h" include\google\protobuf\stubs\status.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stl_util.h" include\google\protobuf\stubs\stl_util.h

View File

@ -10,13 +10,10 @@ set(libprotobuf_lite_files
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
${protobuf_source_dir}/src/google/protobuf/message_lite.cc
${protobuf_source_dir}/src/google/protobuf/repeated_field.cc
${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc
${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc
${protobuf_source_dir}/src/google/protobuf/stubs/bytestream.cc
${protobuf_source_dir}/src/google/protobuf/stubs/common.cc
${protobuf_source_dir}/src/google/protobuf/stubs/int128.cc
${protobuf_source_dir}/src/google/protobuf/stubs/io_win32.cc
${protobuf_source_dir}/src/google/protobuf/stubs/once.cc
${protobuf_source_dir}/src/google/protobuf/stubs/status.cc
${protobuf_source_dir}/src/google/protobuf/stubs/statusor.cc
${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece.cc
@ -38,7 +35,6 @@ set(libprotobuf_lite_includes
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.h
${protobuf_source_dir}/src/google/protobuf/message_lite.h
${protobuf_source_dir}/src/google/protobuf/repeated_field.h
${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h
${protobuf_source_dir}/src/google/protobuf/stubs/bytestream.h
${protobuf_source_dir}/src/google/protobuf/stubs/common.h
${protobuf_source_dir}/src/google/protobuf/stubs/int128.h

View File

@ -155,7 +155,8 @@ set(tests_files
${protobuf_source_dir}/src/google/protobuf/preserve_unknown_enum_test.cc
${protobuf_source_dir}/src/google/protobuf/proto3_arena_lite_unittest.cc
${protobuf_source_dir}/src/google/protobuf/proto3_arena_unittest.cc
${protobuf_source_dir}/src/google/protobuf/proto3_lite_unittest.cc
# TODO(b/74491957) Make this unittest work
# ${protobuf_source_dir}/src/google/protobuf/proto3_lite_unittest.cc
${protobuf_source_dir}/src/google/protobuf/reflection_ops_unittest.cc
${protobuf_source_dir}/src/google/protobuf/repeated_field_reflection_unittest.cc
${protobuf_source_dir}/src/google/protobuf/repeated_field_unittest.cc
@ -163,7 +164,6 @@ set(tests_files
${protobuf_source_dir}/src/google/protobuf/stubs/common_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/int128_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/io_win32_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/once_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/status_test.cc
${protobuf_source_dir}/src/google/protobuf/stubs/statusor_test.cc
${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece_unittest.cc
@ -172,7 +172,6 @@ set(tests_files
${protobuf_source_dir}/src/google/protobuf/stubs/strutil_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/template_util_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/time_test.cc
${protobuf_source_dir}/src/google/protobuf/stubs/type_traits_unittest.cc
${protobuf_source_dir}/src/google/protobuf/text_format_unittest.cc
${protobuf_source_dir}/src/google/protobuf/unknown_field_set_unittest.cc
${protobuf_source_dir}/src/google/protobuf/util/delimited_message_util_test.cc

View File

@ -1910,6 +1910,10 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
{
TestAllTypesProto3 messageProto3;
TestAllTypesProto2 messageProto2;
//TODO(yilunchong): update this behavior when unknown field's behavior
// changed in open source. Also delete
// Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput
// from failure list of python_cpp python java
TestUnknownMessage(messageProto3, true);
TestUnknownMessage(messageProto2, false);
}

View File

@ -45,3 +45,4 @@ Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValu
Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput

View File

@ -19,3 +19,4 @@ Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_0
Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_1
Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_2
Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_3
Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput

View File

@ -52,3 +52,4 @@ Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32
Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64
Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32
Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64
Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput

View File

@ -124,6 +124,16 @@ public abstract class AbstractMessage
protected int memoizedSize = -1;
@Override
int getMemoizedSerializedSize() {
return memoizedSize;
}
@Override
void setMemoizedSerializedSize(int size) {
memoizedSize = size;
}
@Override
public int getSerializedSize() {
int size = memoizedSize;

View File

@ -99,6 +99,16 @@ public abstract class AbstractMessageLite<
codedOutput.flush();
}
// We'd like these to be abstract but some folks are extending this class directly. They shouldn't
// be doing that and they should feel bad.
int getMemoizedSerializedSize() {
throw new UnsupportedOperationException();
}
void setMemoizedSerializedSize(int size) {
throw new UnsupportedOperationException();
}
/**
* Package private helper method for AbstractParser to create

View File

@ -81,6 +81,18 @@ final class BooleanArrayList extends AbstractProtobufList<Boolean>
this.size = size;
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
ensureIsMutable();
if (toIndex < fromIndex) {
throw new IndexOutOfBoundsException("toIndex < fromIndex");
}
System.arraycopy(array, toIndex, array, fromIndex, size - toIndex);
size -= (toIndex - fromIndex);
modCount++;
}
@Override
public boolean equals(Object o) {
if (this == o) {
@ -246,7 +258,9 @@ final class BooleanArrayList extends AbstractProtobufList<Boolean>
ensureIsMutable();
ensureIndexInRange(index);
boolean value = array[index];
System.arraycopy(array, index + 1, array, index, size - index);
if (index < size - 1) {
System.arraycopy(array, index + 1, array, index, size - index);
}
size--;
modCount++;
return value;

View File

@ -66,11 +66,9 @@ public abstract class CodedInputStream {
/**
* Whether to enable our custom UTF-8 decode codepath which does not use {@link StringCoding}.
* Enabled by default, disable by setting
* {@code -Dcom.google.protobuf.enableCustomutf8Decode=false} in JVM args.
* Currently disabled.
*/
private static final boolean ENABLE_CUSTOM_UTF8_DECODE
= !"false".equals(System.getProperty("com.google.protobuf.enableCustomUtf8Decode"));
private static final boolean ENABLE_CUSTOM_UTF8_DECODE = false;
/** Visible for subclasses. See setRecursionLimit() */
int recursionDepth;

View File

@ -377,6 +377,7 @@ public abstract class CodedOutputStream extends ByteOutput {
public abstract void writeMessage(final int fieldNumber, final MessageLite value)
throws IOException;
/**
* Write a MessageSet extension field to the stream. For historical reasons,
* the wire format differs from normal fields.
@ -481,6 +482,7 @@ public abstract class CodedOutputStream extends ByteOutput {
// Abstract to avoid overhead of additional virtual method calls.
public abstract void writeMessageNoTag(final MessageLite value) throws IOException;
//=================================================================
@ExperimentalApi
@ -666,6 +668,7 @@ public abstract class CodedOutputStream extends ByteOutput {
return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* MessageSet extension to the stream. For historical reasons,
@ -913,6 +916,7 @@ public abstract class CodedOutputStream extends ByteOutput {
return computeLengthDelimitedFieldSize(value.getSerializedSize());
}
static int computeLengthDelimitedFieldSize(int fieldLength) {
return computeUInt32SizeNoTag(fieldLength) + fieldLength;
}
@ -1049,6 +1053,7 @@ public abstract class CodedOutputStream extends ByteOutput {
writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
}
/**
* Write a {@code group} field to the stream.
*
@ -1059,6 +1064,7 @@ public abstract class CodedOutputStream extends ByteOutput {
value.writeTo(this);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code group} field, including tag.
@ -1070,6 +1076,7 @@ public abstract class CodedOutputStream extends ByteOutput {
return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code group} field.
@ -1079,6 +1086,7 @@ public abstract class CodedOutputStream extends ByteOutput {
return value.getSerializedSize();
}
/**
* Encode and write a varint. {@code value} is treated as
* unsigned, so it won't be sign-extended if negative.
@ -1273,6 +1281,7 @@ public abstract class CodedOutputStream extends ByteOutput {
writeMessageNoTag(value);
}
@Override
public final void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
throws IOException {
@ -1297,6 +1306,7 @@ public abstract class CodedOutputStream extends ByteOutput {
value.writeTo(this);
}
@Override
public final void write(byte value) throws IOException {
try {
@ -1608,6 +1618,7 @@ public abstract class CodedOutputStream extends ByteOutput {
writeMessageNoTag(value);
}
@Override
public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
throws IOException {
@ -1632,6 +1643,7 @@ public abstract class CodedOutputStream extends ByteOutput {
value.writeTo(this);
}
@Override
public void write(byte value) throws IOException {
try {
@ -1928,6 +1940,7 @@ public abstract class CodedOutputStream extends ByteOutput {
writeMessageNoTag(value);
}
@Override
public void writeMessageSetExtension(int fieldNumber, MessageLite value) throws IOException {
writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
@ -1950,6 +1963,7 @@ public abstract class CodedOutputStream extends ByteOutput {
value.writeTo(this);
}
@Override
public void write(byte value) throws IOException {
if (position >= limit) {
@ -2456,6 +2470,7 @@ public abstract class CodedOutputStream extends ByteOutput {
writeMessageNoTag(value);
}
@Override
public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
throws IOException {
@ -2480,6 +2495,7 @@ public abstract class CodedOutputStream extends ByteOutput {
value.writeTo(this);
}
@Override
public void write(byte value) throws IOException {
if (position == limit) {
@ -2759,6 +2775,7 @@ public abstract class CodedOutputStream extends ByteOutput {
writeMessageNoTag(value);
}
@Override
public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
throws IOException {
@ -2783,6 +2800,7 @@ public abstract class CodedOutputStream extends ByteOutput {
value.writeTo(this);
}
@Override
public void write(byte value) throws IOException {
if (position == limit) {

View File

@ -81,6 +81,18 @@ final class DoubleArrayList extends AbstractProtobufList<Double>
this.size = size;
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
ensureIsMutable();
if (toIndex < fromIndex) {
throw new IndexOutOfBoundsException("toIndex < fromIndex");
}
System.arraycopy(array, toIndex, array, fromIndex, size - toIndex);
size -= (toIndex - fromIndex);
modCount++;
}
@Override
public boolean equals(Object o) {
if (this == o) {
@ -247,7 +259,9 @@ final class DoubleArrayList extends AbstractProtobufList<Double>
ensureIsMutable();
ensureIndexInRange(index);
double value = array[index];
System.arraycopy(array, index + 1, array, index, size - index);
if (index < size - 1) {
System.arraycopy(array, index + 1, array, index, size - index);
}
size--;
modCount++;
return value;

View File

@ -339,6 +339,20 @@ public final class DynamicMessage extends AbstractMessage {
this.fields = FieldSet.newFieldSet();
this.unknownFields = UnknownFieldSet.getDefaultInstance();
this.oneofCases = new FieldDescriptor[type.toProto().getOneofDeclCount()];
// A MapEntry has all of its fields present at all times.
if (type.getOptions().getMapEntry()) {
populateMapEntry();
}
}
private void populateMapEntry() {
for (FieldDescriptor field : type.getFields()) {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
fields.setField(field, getDefaultInstance(field.getMessageType()));
} else {
fields.setField(field, field.getDefaultValue());
}
}
}
// ---------------------------------------------------------------
@ -351,6 +365,10 @@ public final class DynamicMessage extends AbstractMessage {
} else {
fields.clear();
}
// A MapEntry has all of its fields present at all times.
if (type.getOptions().getMapEntry()) {
populateMapEntry();
}
unknownFields = UnknownFieldSet.getDefaultInstance();
return this;
}

View File

@ -81,6 +81,18 @@ final class FloatArrayList extends AbstractProtobufList<Float>
this.size = size;
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
ensureIsMutable();
if (toIndex < fromIndex) {
throw new IndexOutOfBoundsException("toIndex < fromIndex");
}
System.arraycopy(array, toIndex, array, fromIndex, size - toIndex);
size -= (toIndex - fromIndex);
modCount++;
}
@Override
public boolean equals(Object o) {
if (this == o) {
@ -246,7 +258,9 @@ final class FloatArrayList extends AbstractProtobufList<Float>
ensureIsMutable();
ensureIndexInRange(index);
float value = array[index];
System.arraycopy(array, index + 1, array, index, size - index);
if (index < size - 1) {
System.arraycopy(array, index + 1, array, index, size - index);
}
size--;
modCount++;
return value;

View File

@ -230,9 +230,13 @@ public abstract class GeneratedMessageLite<
* Called by subclasses to complete parsing. For use by generated code only.
*/
protected void makeImmutable() {
// BEGIN REGULAR
dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
unknownFields.makeImmutable();
// END REGULAR
// BEGIN EXPERIMENTAL
// Protobuf.getInstance().schemaFor(this).makeImmutable(this);
// END EXPERIMENTAL
}
protected final <
@ -269,15 +273,15 @@ public abstract class GeneratedMessageLite<
* For use by generated code only.
*/
public static enum MethodToInvoke {
IS_INITIALIZED,
// BEGIN REGULAR
IS_INITIALIZED,
VISIT,
MERGE_FROM_STREAM,
MAKE_IMMUTABLE,
// END REGULAR
// Rely on/modify instance state
GET_MEMOIZED_IS_INITIALIZED,
SET_MEMOIZED_IS_INITIALIZED,
MERGE_FROM_STREAM,
MAKE_IMMUTABLE,
// Rely on static state
NEW_MUTABLE_INSTANCE,
@ -339,6 +343,16 @@ public abstract class GeneratedMessageLite<
}
// END REGULAR
@Override
int getMemoizedSerializedSize() {
return memoizedSerializedSize;
}
@Override
void setMemoizedSerializedSize(int size) {
memoizedSerializedSize = size;
}
/**
@ -448,6 +462,28 @@ public abstract class GeneratedMessageLite<
return defaultInstance;
}
@Override
public BuilderType mergeFrom(byte[] input, int offset, int length)
throws InvalidProtocolBufferException {
// BEGIN REGULAR
return super.mergeFrom(input, offset, length);
// END REGULAR
// BEGIN EXPERIMENTAL
// copyOnWrite();
// try {
// Protobuf.getInstance().schemaFor(instance).mergeFrom(
// instance, input, offset, offset + length, new ArrayDecoders.Registers());
// } catch (InvalidProtocolBufferException e) {
// throw e;
// } catch (IndexOutOfBoundsException e) {
// throw InvalidProtocolBufferException.truncatedMessage();
// } catch (IOException e) {
// throw new RuntimeException("Reading from byte array should not throw IOException.", e);
// }
// return (BuilderType) this;
// END EXPERIMENTAL
}
@Override
public BuilderType mergeFrom(
com.google.protobuf.CodedInputStream input,
@ -455,7 +491,13 @@ public abstract class GeneratedMessageLite<
throws IOException {
copyOnWrite();
try {
// BEGIN REGULAR
instance.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
// END REGULAR
// BEGIN EXPERIMENTAL
// Protobuf.getInstance().schemaFor(instance).mergeFrom(
// instance, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
// END EXPERIMENTAL
} catch (RuntimeException e) {
if (e.getCause() instanceof IOException) {
throw (IOException) e.getCause();
@ -576,9 +618,7 @@ public abstract class GeneratedMessageLite<
return parseUnknownField(tag, input);
}
if (extensions.isImmutable()) {
extensions = extensions.clone();
}
ensureExtensionsAreMutable();
if (packed) {
int length = input.readRawVarint32();
@ -794,10 +834,18 @@ public abstract class GeneratedMessageLite<
if (subBuilder == null) {
subBuilder = extension.getMessageDefaultInstance().newBuilderForType();
}
rawBytes.newCodedInput().readMessage(subBuilder, extensionRegistry);
subBuilder.mergeFrom(rawBytes, extensionRegistry);
MessageLite value = subBuilder.build();
extensions.setField(extension.descriptor, extension.singularToFieldSetType(value));
ensureExtensionsAreMutable().setField(
extension.descriptor, extension.singularToFieldSetType(value));
}
private FieldSet<ExtensionDescriptor> ensureExtensionsAreMutable() {
if (extensions.isImmutable()) {
extensions = extensions.clone();
}
return extensions;
}
private void verifyExtensionContainingType(
@ -869,10 +917,12 @@ public abstract class GeneratedMessageLite<
@Override
protected final void makeImmutable() {
super.makeImmutable();
// BEGIN REGULAR
extensions.makeImmutable();
// END REGULAR
}
/**
* Used by subclasses to serialize extensions. Extension ranges may be
* interleaved with field numbers, but we must write them in canonical
@ -1468,8 +1518,13 @@ public abstract class GeneratedMessageLite<
if (memoizedIsInitialized == 0) {
return false;
}
// BEGIN EXPERIMENTAL
// boolean isInitialized = Protobuf.getInstance().schemaFor(message).isInitialized(message);
// END EXPERIMENTAL
// BEGIN REGULAR
boolean isInitialized =
message.dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.FALSE) != null;
// END REGULAR
if (shouldMemoize) {
message.dynamicMethod(
MethodToInvoke.SET_MEMOIZED_IS_INITIALIZED, isInitialized ? message : null);
@ -1477,10 +1532,6 @@ public abstract class GeneratedMessageLite<
return isInitialized;
}
protected static final <T extends GeneratedMessageLite<T, ?>> void makeImmutable(T message) {
message.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
}
protected static IntList emptyIntList() {
return IntArrayList.emptyList();
}
@ -1560,6 +1611,11 @@ public abstract class GeneratedMessageLite<
throws InvalidProtocolBufferException {
return GeneratedMessageLite.parsePartialFrom(defaultInstance, input, extensionRegistry);
}
@Override
public T parsePartialFrom(byte[] input) throws InvalidProtocolBufferException {
return GeneratedMessageLite.parsePartialFrom(defaultInstance, input);
}
}
/**
@ -1573,8 +1629,21 @@ public abstract class GeneratedMessageLite<
@SuppressWarnings("unchecked") // Guaranteed by protoc
T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
try {
// BEGIN REGULAR
result.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
// END REGULAR
// BEGIN EXPERIMENTAL
// Protobuf.getInstance().schemaFor(result).mergeFrom(
// result, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
// END EXPERIMENTAL
result.makeImmutable();
// BEGIN EXPERIMENTAL
// } catch (IOException e) {
// if (e.getCause() instanceof InvalidProtocolBufferException) {
// throw (InvalidProtocolBufferException) e.getCause();
// }
// throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result);
// END EXPERIMENTAL
} catch (RuntimeException e) {
if (e.getCause() instanceof InvalidProtocolBufferException) {
throw (InvalidProtocolBufferException) e.getCause();
@ -1584,6 +1653,34 @@ public abstract class GeneratedMessageLite<
return result;
}
/** A static helper method for parsing a partial from byte array. */
static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(T instance, byte[] input)
throws InvalidProtocolBufferException {
// BEGIN REGULAR
return parsePartialFrom(instance, input, ExtensionRegistryLite.getEmptyRegistry());
// END REGULAR
// BEGIN EXPERIMENTAL
// @SuppressWarnings("unchecked") // Guaranteed by protoc
// T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
// try {
// Protobuf.getInstance().schemaFor(result).mergeFrom(
// result, input, 0, input.length, new ArrayDecoders.Registers());
// result.makeImmutable();
// if (result.memoizedHashCode != 0) {
// throw new RuntimeException();
// }
// } catch (IOException e) {
// if (e.getCause() instanceof InvalidProtocolBufferException) {
// throw (InvalidProtocolBufferException) e.getCause();
// }
// throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result);
// } catch (IndexOutOfBoundsException e) {
// throw InvalidProtocolBufferException.truncatedMessage().setUnfinishedMessage(result);
// }
// return result;
// END EXPERIMENTAL
}
protected static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
T defaultInstance,
CodedInputStream input)
@ -1680,8 +1777,7 @@ public abstract class GeneratedMessageLite<
protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
T defaultInstance, byte[] data)
throws InvalidProtocolBufferException {
return checkMessageInitialized(
parsePartialFrom(defaultInstance, data, ExtensionRegistryLite.getEmptyRegistry()));
return checkMessageInitialized(parsePartialFrom(defaultInstance, data));
}
// Validates last tag.

View File

@ -81,6 +81,18 @@ final class IntArrayList extends AbstractProtobufList<Integer>
this.size = size;
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
ensureIsMutable();
if (toIndex < fromIndex) {
throw new IndexOutOfBoundsException("toIndex < fromIndex");
}
System.arraycopy(array, toIndex, array, fromIndex, size - toIndex);
size -= (toIndex - fromIndex);
modCount++;
}
@Override
public boolean equals(Object o) {
if (this == o) {
@ -246,7 +258,9 @@ final class IntArrayList extends AbstractProtobufList<Integer>
ensureIsMutable();
ensureIndexInRange(index);
int value = array[index];
System.arraycopy(array, index + 1, array, index, size - index);
if (index < size - 1) {
System.arraycopy(array, index + 1, array, index, size - index);
}
size--;
modCount++;
return value;

View File

@ -81,6 +81,18 @@ final class LongArrayList extends AbstractProtobufList<Long>
this.size = size;
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
ensureIsMutable();
if (toIndex < fromIndex) {
throw new IndexOutOfBoundsException("toIndex < fromIndex");
}
System.arraycopy(array, toIndex, array, fromIndex, size - toIndex);
size -= (toIndex - fromIndex);
modCount++;
}
@Override
public boolean equals(Object o) {
if (this == o) {
@ -246,7 +258,9 @@ final class LongArrayList extends AbstractProtobufList<Long>
ensureIsMutable();
ensureIndexInRange(index);
long value = array[index];
System.arraycopy(array, index + 1, array, index, size - index);
if (index < size - 1) {
System.arraycopy(array, index + 1, array, index, size - index);
}
size--;
modCount++;
return value;

View File

@ -31,6 +31,7 @@
package com.google.protobuf;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@ -38,20 +39,18 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/**
* Helps generate {@link String} representations of {@link MessageLite} protos.
*/
// TODO(dweis): Fix map fields.
/** Helps generate {@link String} representations of {@link MessageLite} protos. */
final class MessageLiteToString {
private static final String LIST_SUFFIX = "List";
private static final String BUILDER_LIST_SUFFIX = "OrBuilderList";
private static final String MAP_SUFFIX = "Map";
private static final String BYTES_SUFFIX = "Bytes";
/**
* Returns a {@link String} representation of the {@link MessageLite} object. The first line of
* Returns a {@link String} representation of the {@link MessageLite} object. The first line of
* the {@code String} representation representation includes a comment string to uniquely identify
* the objcet instance. This acts as an indicator that this should not be relied on for
* the object instance. This acts as an indicator that this should not be relied on for
* comparisons.
*
* <p>For use by generated code only.
@ -71,8 +70,9 @@ final class MessageLiteToString {
*/
private static void reflectivePrintWithIndent(
MessageLite messageLite, StringBuilder buffer, int indent) {
// Build a map of method name to method. We're looking for methods like getFoo(), hasFoo(), and
// getFooList() which might be useful for building an object's string representation.
// Build a map of method name to method. We're looking for methods like getFoo(), hasFoo(),
// getFooList() and getFooMap() which might be useful for building an object's string
// representation.
Map<String, Method> nameToNoArgMethod = new HashMap<String, Method>();
Map<String, Method> nameToMethod = new HashMap<String, Method>();
Set<String> getters = new TreeSet<String>();
@ -89,12 +89,16 @@ final class MessageLiteToString {
for (String getter : getters) {
String suffix = getter.replaceFirst("get", "");
if (suffix.endsWith(LIST_SUFFIX) && !suffix.endsWith(BUILDER_LIST_SUFFIX)) {
String camelCase = suffix.substring(0, 1).toLowerCase()
+ suffix.substring(1, suffix.length() - LIST_SUFFIX.length());
if (suffix.endsWith(LIST_SUFFIX)
&& !suffix.endsWith(BUILDER_LIST_SUFFIX)
// Sometimes people have fields named 'list' that aren't repeated.
&& !suffix.equals(LIST_SUFFIX)) {
String camelCase =
suffix.substring(0, 1).toLowerCase()
+ suffix.substring(1, suffix.length() - LIST_SUFFIX.length());
// Try to reflectively get the value and toString() the field as if it were repeated. This
// only works if the method names have not be proguarded out or renamed.
Method listMethod = nameToNoArgMethod.get("get" + suffix);
// only works if the method names have not been proguarded out or renamed.
Method listMethod = nameToNoArgMethod.get(getter);
if (listMethod != null && listMethod.getReturnType().equals(List.class)) {
printField(
buffer,
@ -104,6 +108,30 @@ final class MessageLiteToString {
continue;
}
}
if (suffix.endsWith(MAP_SUFFIX)
// Sometimes people have fields named 'map' that aren't maps.
&& !suffix.equals(MAP_SUFFIX)) {
String camelCase =
suffix.substring(0, 1).toLowerCase()
+ suffix.substring(1, suffix.length() - MAP_SUFFIX.length());
// Try to reflectively get the value and toString() the field as if it were a map. This only
// works if the method names have not been proguarded out or renamed.
Method mapMethod = nameToNoArgMethod.get(getter);
if (mapMethod != null
&& mapMethod.getReturnType().equals(Map.class)
// Skip the deprecated getter method with no prefix "Map" when the field name ends with
// "map".
&& !mapMethod.isAnnotationPresent(Deprecated.class)
// Skip the internal mutable getter method.
&& Modifier.isPublic(mapMethod.getModifiers())) {
printField(
buffer,
indent,
camelCaseToSnakeCase(camelCase),
GeneratedMessageLite.invokeOrDie(mapMethod, messageLite));
continue;
}
}
Method setter = nameToMethod.get("set" + suffix);
if (setter == null) {
@ -119,22 +147,19 @@ final class MessageLiteToString {
String camelCase = suffix.substring(0, 1).toLowerCase() + suffix.substring(1);
// Try to reflectively get the value and toString() the field as if it were optional. This
// only works if the method names have not be proguarded out or renamed.
// only works if the method names have not been proguarded out or renamed.
Method getMethod = nameToNoArgMethod.get("get" + suffix);
Method hasMethod = nameToNoArgMethod.get("has" + suffix);
// TODO(dweis): Fix proto3 semantics.
if (getMethod != null) {
Object value = GeneratedMessageLite.invokeOrDie(getMethod, messageLite);
final boolean hasValue = hasMethod == null
? !isDefaultValue(value)
: (Boolean) GeneratedMessageLite.invokeOrDie(hasMethod, messageLite);
// TODO(dweis): This doesn't stop printing oneof case twice: value and enum style.
final boolean hasValue =
hasMethod == null
? !isDefaultValue(value)
: (Boolean) GeneratedMessageLite.invokeOrDie(hasMethod, messageLite);
// TODO(dweis): This doesn't stop printing oneof case twice: value and enum style.
if (hasValue) {
printField(
buffer,
indent,
camelCaseToSnakeCase(camelCase),
value);
printField(buffer, indent, camelCaseToSnakeCase(camelCase), value);
}
continue;
}
@ -153,7 +178,7 @@ final class MessageLiteToString {
((GeneratedMessageLite<?, ?>) messageLite).unknownFields.printWithIndent(buffer, indent);
}
}
private static boolean isDefaultValue(Object o) {
if (o instanceof Boolean) {
return !((Boolean) o);
@ -179,7 +204,7 @@ final class MessageLiteToString {
if (o instanceof java.lang.Enum<?>) { // Catches oneof enums.
return ((java.lang.Enum<?>) o).ordinal() == 0;
}
return false;
}
@ -201,6 +226,13 @@ final class MessageLiteToString {
}
return;
}
if (object instanceof Map<?, ?>) {
Map<?, ?> map = (Map<?, ?>) object;
for (Map.Entry<?, ?> entry : map.entrySet()) {
printField(buffer, indent, name, entry);
}
return;
}
buffer.append('\n');
for (int i = 0; i < indent; i++) {
@ -220,11 +252,21 @@ final class MessageLiteToString {
buffer.append(' ');
}
buffer.append("}");
} else if (object instanceof Map.Entry<?, ?>) {
buffer.append(" {");
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
printField(buffer, indent + 2, "key", entry.getKey());
printField(buffer, indent + 2, "value", entry.getValue());
buffer.append("\n");
for (int i = 0; i < indent; i++) {
buffer.append(' ');
}
buffer.append("}");
} else {
buffer.append(": ").append(object.toString());
}
}
private static final String camelCaseToSnakeCase(String camelCase) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < camelCase.length(); i++) {

View File

@ -987,7 +987,7 @@ public final class TextFormat {
nextToken();
return false;
} else {
throw parseException("Expected \"true\" or \"false\".");
throw parseException("Expected \"true\" or \"false\". Found \"" + currentToken + "\".");
}
}
@ -1311,13 +1311,17 @@ public final class TextFormat {
}
private final boolean allowUnknownFields;
private final boolean allowUnknownEnumValues;
private final SingularOverwritePolicy singularOverwritePolicy;
private TextFormatParseInfoTree.Builder parseInfoTreeBuilder;
private Parser(
boolean allowUnknownFields, SingularOverwritePolicy singularOverwritePolicy,
boolean allowUnknownFields,
boolean allowUnknownEnumValues,
SingularOverwritePolicy singularOverwritePolicy,
TextFormatParseInfoTree.Builder parseInfoTreeBuilder) {
this.allowUnknownFields = allowUnknownFields;
this.allowUnknownEnumValues = allowUnknownEnumValues;
this.singularOverwritePolicy = singularOverwritePolicy;
this.parseInfoTreeBuilder = parseInfoTreeBuilder;
}
@ -1334,6 +1338,7 @@ public final class TextFormat {
*/
public static class Builder {
private boolean allowUnknownFields = false;
private boolean allowUnknownEnumValues = false;
private SingularOverwritePolicy singularOverwritePolicy =
SingularOverwritePolicy.ALLOW_SINGULAR_OVERWRITES;
private TextFormatParseInfoTree.Builder parseInfoTreeBuilder = null;
@ -1355,7 +1360,10 @@ public final class TextFormat {
public Parser build() {
return new Parser(
allowUnknownFields, singularOverwritePolicy, parseInfoTreeBuilder);
allowUnknownFields,
allowUnknownEnumValues,
singularOverwritePolicy,
parseInfoTreeBuilder);
}
}
@ -1419,7 +1427,7 @@ public final class TextFormat {
return text;
}
// Check both unknown fields and unknown extensions and log warming messages
// Check both unknown fields and unknown extensions and log warning messages
// or throw exceptions according to the flag.
private void checkUnknownFields(final List<String> unknownFields)
throws ParseException {
@ -1737,17 +1745,40 @@ public final class TextFormat {
final int number = tokenizer.consumeInt32();
value = enumType.findValueByNumber(number);
if (value == null) {
throw tokenizer.parseExceptionPreviousToken(
"Enum type \"" + enumType.getFullName()
+ "\" has no value with number " + number + '.');
String unknownValueMsg =
"Enum type \""
+ enumType.getFullName()
+ "\" has no value with number "
+ number
+ '.';
if (allowUnknownEnumValues) {
logger.warning(unknownValueMsg);
return;
} else {
throw tokenizer.parseExceptionPreviousToken(
"Enum type \""
+ enumType.getFullName()
+ "\" has no value with number "
+ number
+ '.');
}
}
} else {
final String id = tokenizer.consumeIdentifier();
value = enumType.findValueByName(id);
if (value == null) {
throw tokenizer.parseExceptionPreviousToken(
"Enum type \"" + enumType.getFullName()
+ "\" has no value named \"" + id + "\".");
String unknownValueMsg =
"Enum type \""
+ enumType.getFullName()
+ "\" has no value named \""
+ id
+ "\".";
if (allowUnknownEnumValues) {
logger.warning(unknownValueMsg);
return;
} else {
throw tokenizer.parseExceptionPreviousToken(unknownValueMsg);
}
}
}

View File

@ -295,14 +295,30 @@ public final class UnknownFieldSetLite {
return true;
}
private static int hashCode(int[] tags, int count) {
int hashCode = 17;
for (int i = 0; i < count; ++i) {
hashCode = 31 * hashCode + tags[i];
}
return hashCode;
}
private static int hashCode(Object[] objects, int count) {
int hashCode = 17;
for (int i = 0; i < count; ++i) {
hashCode = 31 * hashCode + objects[i].hashCode();
}
return hashCode;
}
@Override
public int hashCode() {
int hashCode = 17;
hashCode = 31 * hashCode + count;
hashCode = 31 * hashCode + Arrays.hashCode(tags);
hashCode = 31 * hashCode + Arrays.deepHashCode(objects);
hashCode = 31 * hashCode + hashCode(tags, count);
hashCode = 31 * hashCode + hashCode(objects, count);
return hashCode;
}

View File

@ -33,6 +33,7 @@ package com.google.protobuf;
import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.logging.Level;
@ -83,6 +84,7 @@ final class UnsafeUtil {
return HAS_UNSAFE_BYTEBUFFER_OPERATIONS;
}
static long objectFieldOffset(Field field) {
return MEMORY_ACCESSOR.objectFieldOffset(field);
}
@ -287,7 +289,7 @@ final class UnsafeUtil {
/**
* Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this platform.
*/
private static sun.misc.Unsafe getUnsafe() {
static sun.misc.Unsafe getUnsafe() {
sun.misc.Unsafe unsafe = null;
try {
unsafe =
@ -367,6 +369,10 @@ final class UnsafeUtil {
clazz.getMethod("objectFieldOffset", Field.class);
clazz.getMethod("getLong", Object.class, long.class);
if (bufferAddressField() == null) {
return false;
}
clazz.getMethod("getByte", long.class);
clazz.getMethod("putByte", long.class, byte.class);
clazz.getMethod("getInt", long.class);
@ -387,12 +393,14 @@ final class UnsafeUtil {
/** Finds the address field within a direct {@link Buffer}. */
private static Field bufferAddressField() {
return field(Buffer.class, "address", long.class);
Field field = field(Buffer.class, "address");
return field != null && field.getType() == long.class ? field : null;
}
/** Finds the value field within a {@link String}. */
private static Field stringValueField() {
return field(String.class, "value", char[].class);
Field field = field(String.class, "value");
return field != null && field.getType() == char[].class ? field : null;
}
/**
@ -407,14 +415,11 @@ final class UnsafeUtil {
* Gets the field with the given name within the class, or {@code null} if not found. If found,
* the field is made accessible.
*/
private static Field field(Class<?> clazz, String fieldName, Class<?> expectedType) {
private static Field field(Class<?> clazz, String fieldName) {
Field field;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
if (!field.getType().equals(expectedType)) {
return null;
}
} catch (Throwable t) {
// Failed to access the fields.
field = null;

View File

@ -32,6 +32,7 @@ package com.google.protobuf;
import static java.util.Arrays.asList;
import com.google.protobuf.Internal.BooleanList;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
@ -297,6 +298,20 @@ public class BooleanArrayListTest extends TestCase {
}
}
public void testRemoveEndOfCapacity() {
BooleanList toRemove = BooleanArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addBoolean(true);
toRemove.remove(0);
assertEquals(0, toRemove.size());
}
public void testSublistRemoveEndOfCapacity() {
BooleanList toRemove = BooleanArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addBoolean(true);
toRemove.subList(0, 1).clear();
assertEquals(0, toRemove.size());
}
private void assertImmutable(BooleanArrayList list) {
try {

View File

@ -34,7 +34,7 @@ import proto2_test_check_utf8.TestCheckUtf8.BytesWrapper;
import proto2_test_check_utf8.TestCheckUtf8.StringWrapper;
import proto2_test_check_utf8_size.TestCheckUtf8Size.BytesWrapperSize;
import proto2_test_check_utf8_size.TestCheckUtf8Size.StringWrapperSize;
import java.io.ByteArrayInputStream;
import junit.framework.TestCase;
/**
@ -90,14 +90,9 @@ public class CheckUtf8Test extends TestCase {
}
public void testParseRequiredStringWithBadUtf8() throws Exception {
ByteString serialized =
BytesWrapper.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString();
try {
StringWrapper.parser().parseFrom(serialized);
fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
} catch (InvalidProtocolBufferException exception) {
assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
}
byte[] serialized =
BytesWrapper.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteArray();
assertParseBadUtf8(StringWrapper.getDefaultInstance(), serialized);
}
public void testBuildRequiredStringWithBadUtf8Size() throws Exception {
@ -128,14 +123,36 @@ public class CheckUtf8Test extends TestCase {
}
public void testParseRequiredStringWithBadUtf8Size() throws Exception {
ByteString serialized =
BytesWrapperSize.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString();
byte[] serialized =
BytesWrapperSize.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteArray();
assertParseBadUtf8(StringWrapperSize.getDefaultInstance(), serialized);
}
private void assertParseBadUtf8(MessageLite defaultInstance, byte[] data) throws Exception {
// Check combinations of (parser vs. builder) x (byte[] vs. InputStream)
try {
StringWrapperSize.parser().parseFrom(serialized);
defaultInstance.getParserForType().parseFrom(data);
fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
} catch (InvalidProtocolBufferException exception) {
assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
}
try {
defaultInstance.newBuilderForType().mergeFrom(data);
fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
} catch (InvalidProtocolBufferException exception) {
assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
}
try {
defaultInstance.getParserForType().parseFrom(new ByteArrayInputStream(data));
fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
} catch (InvalidProtocolBufferException exception) {
assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
}
try {
defaultInstance.newBuilderForType().mergeFrom(new ByteArrayInputStream(data));
fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
} catch (InvalidProtocolBufferException exception) {
assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
}
}
}

View File

@ -32,6 +32,7 @@ package com.google.protobuf;
import static java.util.Arrays.asList;
import com.google.protobuf.Internal.DoubleList;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
@ -297,6 +298,20 @@ public class DoubleArrayListTest extends TestCase {
}
}
public void testRemoveEndOfCapacity() {
DoubleList toRemove = DoubleArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addDouble(3);
toRemove.remove(0);
assertEquals(0, toRemove.size());
}
public void testSublistRemoveEndOfCapacity() {
DoubleList toRemove = DoubleArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addDouble(3);
toRemove.subList(0, 1).clear();
assertEquals(0, toRemove.size());
}
private void assertImmutable(DoubleArrayList list) {
if (list.contains(1D)) {
throw new RuntimeException("Cannot test the immutability of lists that contain 1.");

View File

@ -32,6 +32,7 @@ package com.google.protobuf;
import static java.util.Arrays.asList;
import com.google.protobuf.Internal.FloatList;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
@ -297,6 +298,20 @@ public class FloatArrayListTest extends TestCase {
}
}
public void testRemoveEndOfCapacity() {
FloatList toRemove = FloatArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addFloat(3);
toRemove.remove(0);
assertEquals(0, toRemove.size());
}
public void testSublistRemoveEndOfCapacity() {
FloatList toRemove = FloatArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addFloat(3);
toRemove.subList(0, 1).clear();
assertEquals(0, toRemove.size());
}
private void assertImmutable(FloatArrayList list) {
if (list.contains(1F)) {
throw new RuntimeException("Cannot test the immutability of lists that contain 1.");

View File

@ -32,6 +32,7 @@ package com.google.protobuf;
import static java.util.Arrays.asList;
import com.google.protobuf.Internal.IntList;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
@ -297,6 +298,20 @@ public class IntArrayListTest extends TestCase {
}
}
public void testRemoveEndOfCapacity() {
IntList toRemove = IntArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addInt(3);
toRemove.remove(0);
assertEquals(0, toRemove.size());
}
public void testSublistRemoveEndOfCapacity() {
IntList toRemove = IntArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addInt(3);
toRemove.subList(0, 1).clear();
assertEquals(0, toRemove.size());
}
private void assertImmutable(IntArrayList list) {
if (list.contains(1)) {
throw new RuntimeException("Cannot test the immutability of lists that contain 1.");

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,7 @@ package com.google.protobuf;
import static java.util.Arrays.asList;
import com.google.protobuf.Internal.LongList;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
@ -297,6 +298,20 @@ public class LongArrayListTest extends TestCase {
}
}
public void testRemoveEndOfCapacity() {
LongList toRemove = LongArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addLong(3);
toRemove.remove(0);
assertEquals(0, toRemove.size());
}
public void testSublistRemoveEndOfCapacity() {
LongList toRemove = LongArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addLong(3);
toRemove.subList(0, 1).clear();
assertEquals(0, toRemove.size());
}
private void assertImmutable(LongArrayList list) {
if (list.contains(1L)) {
throw new RuntimeException("Cannot test the immutability of lists that contain 1.");

View File

@ -788,6 +788,24 @@ public class MapForProto2Test extends TestCase {
assertEquals(message.hashCode(), dynamicMessage.hashCode());
}
// Check that DynamicMessage handles map field serialization the same way as generated code
// regarding unset key and value field in a map entry.
public void testDynamicMessageUnsetKeyAndValue() throws Exception {
FieldDescriptor field = f("int32_to_int32_field");
Message dynamicDefaultInstance =
DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
Message.Builder builder = dynamicDefaultInstance.newBuilderForType();
// Add an entry without key and value.
builder.addRepeatedField(field, builder.newBuilderForField(field).build());
Message message = builder.build();
ByteString bytes = message.toByteString();
// Parse it back to the same generated type.
Message generatedMessage = TestMap.parseFrom(bytes);
// Assert the serialized bytes are equivalent.
assertEquals(generatedMessage.toByteString(), bytes);
}
public void testReflectionEqualsAndHashCode() throws Exception {
// Test that generated equals() and hashCode() will disregard the order
// of map entries when comparing/hashing map fields.

View File

@ -893,6 +893,24 @@ public class MapTest extends TestCase {
assertEquals(message.hashCode(), dynamicMessage.hashCode());
}
// Check that DynamicMessage handles map field serialization the same way as generated code
// regarding unset key and value field in a map entry.
public void testDynamicMessageUnsetKeyAndValue() throws Exception {
FieldDescriptor field = f("int32_to_int32_field");
Message dynamicDefaultInstance =
DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
Message.Builder builder = dynamicDefaultInstance.newBuilderForType();
// Add an entry without key and value.
builder.addRepeatedField(field, builder.newBuilderForField(field).build());
Message message = builder.build();
ByteString bytes = message.toByteString();
// Parse it back to the same generated type.
Message generatedMessage = TestMap.parseFrom(bytes);
// Assert the serialized bytes are equivalent.
assertEquals(generatedMessage.toByteString(), bytes);
}
public void testReflectionEqualsAndHashCode() throws Exception {
// Test that generated equals() and hashCode() will disregard the order
// of map entries when comparing/hashing map fields.

View File

@ -61,12 +61,11 @@ import junit.framework.TestCase;
public class TextFormatTest extends TestCase {
// A basic string with different escapable characters for testing.
private final static String kEscapeTestString =
"\"A string with ' characters \n and \r newlines and \t tabs and \001 "
+ "slashes \\";
private static final String ESCAPE_TEST_STRING =
"\"A string with ' characters \n and \r newlines and \t tabs and \001 " + "slashes \\";
// A representation of the above string with all the characters escaped.
private final static String kEscapeTestStringEscaped =
private static final String ESCAPE_TEST_STRING_ESCAPED =
"\\\"A string with \\' characters \\n and \\r newlines "
+ "and \\t tabs and \\001 slashes \\\\";
@ -576,10 +575,10 @@ public class TextFormatTest extends TestCase {
"integer: 82301481290849012385230157",
"optional_int32: 82301481290849012385230157");
assertParseError(
"1:16: Expected \"true\" or \"false\".",
"1:16: Expected \"true\" or \"false\". Found \"maybe\".",
"optional_bool: maybe");
assertParseError(
"1:16: Expected \"true\" or \"false\".",
"1:16: Expected \"true\" or \"false\". Found \"2\".",
"optional_bool: 2");
assertParseError(
"1:18: Expected string.",
@ -643,10 +642,8 @@ public class TextFormatTest extends TestCase {
TextFormat.unescapeBytes("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
assertEquals("\0\001\007\b\f\n\r\t\013\\\'\"",
TextFormat.unescapeText("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
assertEquals(kEscapeTestStringEscaped,
TextFormat.escapeText(kEscapeTestString));
assertEquals(kEscapeTestString,
TextFormat.unescapeText(kEscapeTestStringEscaped));
assertEquals(ESCAPE_TEST_STRING_ESCAPED, TextFormat.escapeText(ESCAPE_TEST_STRING));
assertEquals(ESCAPE_TEST_STRING, TextFormat.unescapeText(ESCAPE_TEST_STRING_ESCAPED));
// Invariant
assertEquals("hello",

View File

@ -30,6 +30,8 @@
package com.google.protobuf;
import static junit.framework.TestCase.assertEquals;
import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
import com.google.protobuf.UnittestLite.TestAllTypesLite;
import protobuf_unittest.UnittestProto;
@ -133,6 +135,25 @@ public class UnknownFieldSetLiteTest extends TestCase {
assertEquals(foo.toByteString().size(), instance.getSerializedSize());
}
public void testHashCodeAfterDeserialization() throws IOException {
Foo foo = Foo.newBuilder()
.setValue(2)
.build();
Foo fooDeserialized = Foo.parseFrom(foo.toByteArray());
assertEquals(fooDeserialized, foo);
assertEquals(foo.hashCode(), fooDeserialized.hashCode());
}
public void testNewInstanceHashCode() {
UnknownFieldSetLite emptyFieldSet = UnknownFieldSetLite.getDefaultInstance();
UnknownFieldSetLite paddedFieldSet = UnknownFieldSetLite.newInstance();
assertEquals(emptyFieldSet, paddedFieldSet);
assertEquals(emptyFieldSet.hashCode(), paddedFieldSet.hashCode());
}
public void testMergeVarintField() throws IOException {
UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
unknownFields.mergeVarintField(10, 2);

View File

@ -36,6 +36,7 @@ import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
import protobuf_unittest.UnittestProto;
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestExtensionInsideTable;
import protobuf_unittest.UnittestProto.TestFieldOrderings;
import protobuf_unittest.UnittestProto.TestOneof2;
import protobuf_unittest.UnittestProto.TestOneofBackwardsCompatible;
@ -235,6 +236,26 @@ public class WireFormatTest extends TestCase {
getTestFieldOrderingsRegistry());
assertEquals(source, dest);
}
private static ExtensionRegistry getTestExtensionInsideTableRegistry() {
ExtensionRegistry result = ExtensionRegistry.newInstance();
result.add(UnittestProto.testExtensionInsideTableExtension);
return result;
}
public void testExtensionInsideTable() throws Exception {
// Make sure the extension within the range of table is parsed correctly in experimental
// runtime.
TestExtensionInsideTable source =
TestExtensionInsideTable.newBuilder()
.setField1(1)
.setExtension(UnittestProto.testExtensionInsideTableExtension, 23)
.build();
TestExtensionInsideTable dest =
TestExtensionInsideTable.parseFrom(source.toByteString(),
getTestExtensionInsideTableRegistry());
assertEquals(source, dest);
}
public void testParseMultipleExtensionRangesDynamic() throws Exception {
// Same as above except with DynamicMessage.

View File

@ -60,14 +60,25 @@ goog.forwardDeclare('jsproto.BinaryExtension');
/**
* Base interface class for all const messages. Does __not__ define any
* methods, as doing so on a widely-used interface defeats dead-code
* elimination.
* Base interface class for all const messages.
* @interface
*/
jspb.ConstBinaryMessage = function() {};
/**
* Generate a debug string for this proto that is in proto2 text format.
* @return {string} The debug string.
*/
jspb.ConstBinaryMessage.prototype.toDebugString;
/**
* Helper to generate a debug string for this proto at some indent level. The
* first line is not indented.
* @param {number} indentLevel The number of spaces by which to indent lines.
* @return {string} The debug string.
* @protected
*/
jspb.ConstBinaryMessage.prototype.toDebugStringInternal;
/**
* Base interface class for all messages. Does __not__ define any methods, as
@ -97,6 +108,7 @@ jspb.ScalarFieldType;
* A repeated field in jspb is an array of scalars, blobs, or messages.
* @typedef {!Array<jspb.ScalarFieldType>|
!Array<!Uint8Array>|
!Array<!jspb.ConstBinaryMessage>|
!Array<!jspb.BinaryMessage>}
*/
jspb.RepeatedFieldType;
@ -108,6 +120,7 @@ jspb.RepeatedFieldType;
* @typedef {jspb.ScalarFieldType|
jspb.RepeatedFieldType|
!Uint8Array|
!jspb.ConstBinaryMessage|
!jspb.BinaryMessage|
!jsproto.BinaryExtension}
*/

View File

@ -986,7 +986,7 @@ jspb.BinaryDecoder.prototype.readString = function(length) {
codeUnits.push(high, low);
}
// Avoid exceeding the maximum stack size when calling {@code apply}.
// Avoid exceeding the maximum stack size when calling `apply`.
if (codeUnits.length >= 8192) {
result += String.fromCharCode.apply(null, codeUnits);
codeUnits.length = 0;

View File

@ -236,10 +236,12 @@ jspb.BinaryWriter.prototype.getResultBuffer = function() {
/**
* Converts the encoded data into a base64-encoded string.
* @param {boolean=} opt_webSafe True indicates we should use a websafe
* alphabet, which does not require escaping for use in URLs.
* @return {string}
*/
jspb.BinaryWriter.prototype.getResultBase64String = function() {
return goog.crypt.base64.encodeByteArray(this.getResultBuffer());
jspb.BinaryWriter.prototype.getResultBase64String = function(opt_webSafe) {
return goog.crypt.base64.encodeByteArray(this.getResultBuffer(), opt_webSafe);
};

View File

@ -118,4 +118,16 @@ describe('binaryWriterTest', function() {
var buffer = writer.getResultBuffer();
assertEquals(expected, goog.crypt.byteArrayToHex(buffer));
});
/**
* Tests websafe encodings for base64 strings.
*/
it('testWebSafeOption', function() {
var writer = new jspb.BinaryWriter();
writer.writeBytes(1, new Uint8Array([127]));
assertEquals('CgF/', writer.getResultBase64String());
assertEquals('CgF/', writer.getResultBase64String(false));
assertEquals('CgF_', writer.getResultBase64String(true));
});
});

View File

@ -42,7 +42,7 @@ goog.require('jspb.Message');
/**
* Turns a proto into a human readable object that can i.e. be written to the
* console: {@code console.log(jspb.debug.dump(myProto))}.
* console: `console.log(jspb.debug.dump(myProto))`.
* This function makes a best effort and may not work in all cases. It will not
* work in obfuscated and or optimized code.
* Use this in environments where {@see jspb.Message.prototype.toObject} is

View File

@ -48,9 +48,9 @@ goog.forwardDeclare('jspb.BinaryWriter');
*
* @template K, V
*
* @param {!Array<!Array<!Object>>} arr
* @param {!Array<!Array<?>>} arr
*
* @param {?function(new:V)|function(new:V,?)=} opt_valueCtor
* @param {?function(new:V, ?=)=} opt_valueCtor
* The constructor for type V, if type V is a message type.
*
* @constructor
@ -118,7 +118,7 @@ jspb.Map.prototype.toArray = function() {
strKeys.sort();
for (var i = 0; i < strKeys.length; i++) {
var entry = this.map_[strKeys[i]];
var valueWrapper = /** @type {!Object} */ (entry.valueWrapper);
var valueWrapper = /** @type {?jspb.Message} */ (entry.valueWrapper);
if (valueWrapper) {
valueWrapper.toArray();
}
@ -165,7 +165,7 @@ jspb.Map.prototype.toObject = function(includeInstance, valueToObject) {
*
* @template K, V
* @param {!Array<!Array<!Object>>} entries
* @param {!function(new:V)|function(new:V,?)} valueCtor
* @param {!function(new:V,?=)} valueCtor
* The constructor for type V.
* @param {!function(!Object):V} valueFromObject
* The fromObject function for type V.
@ -432,7 +432,8 @@ jspb.Map.prototype.serializeBinary = function(
valueWriterFn.call(writer, 2, this.wrapEntry_(entry),
opt_valueWriterCallback);
} else {
valueWriterFn.call(writer, 2, entry.value);
/** @type {function(this:jspb.BinaryWriter,number,?)} */ (valueWriterFn)
.call(writer, 2, entry.value);
}
writer.endSubMessage();
}
@ -475,10 +476,13 @@ jspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn,
} else if (field == 2) {
// Value.
if (map.valueCtor_) {
goog.asserts.assert(opt_valueReaderCallback);
value = new map.valueCtor_();
valueReaderFn.call(reader, value, opt_valueReaderCallback);
} else {
value = valueReaderFn.call(reader);
value =
(/** @type {function(this:jspb.BinaryReader):?} */ (valueReaderFn))
.call(reader);
}
}
}

View File

@ -215,17 +215,6 @@ goog.define('jspb.Message.ASSUME_LOCAL_ARRAYS', false);
goog.define('jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS', true);
/**
* @define {boolean} Turning on this flag does NOT change the behavior of JSPB
* and only affects private internal state. It may, however, break some
* tests that use naive deeply-equals algorithms, because using a proto
* mutates its internal state.
* Projects are advised to turn this flag always on.
*/
goog.define('jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS', true);
// TODO(b/19419436): Delete this flag.
/**
* Does this JavaScript environment support Uint8Aray typed arrays?
* @type {boolean}
@ -369,7 +358,7 @@ jspb.Message.getFieldNumber_ = function(msg, index) {
*/
jspb.Message.initialize = function(
msg, data, messageId, suggestedPivot, repeatedFields, opt_oneofFields) {
msg.wrappers_ = jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ? null : {};
msg.wrappers_ = null;
if (!data) {
data = messageId ? [messageId] : [];
}
@ -394,17 +383,12 @@ jspb.Message.initialize = function(
var fieldNumber = repeatedFields[i];
if (fieldNumber < msg.pivot_) {
var index = jspb.Message.getIndex_(msg, fieldNumber);
msg.array[index] = msg.array[index] ||
(jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ?
jspb.Message.EMPTY_LIST_SENTINEL_ :
[]);
msg.array[index] =
msg.array[index] || jspb.Message.EMPTY_LIST_SENTINEL_;
} else {
jspb.Message.maybeInitEmptyExtensionObject_(msg);
msg.extensionObject_[fieldNumber] =
msg.extensionObject_[fieldNumber] ||
(jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ?
jspb.Message.EMPTY_LIST_SENTINEL_ :
[]);
msg.extensionObject_[fieldNumber] = msg.extensionObject_[fieldNumber] ||
jspb.Message.EMPTY_LIST_SENTINEL_;
}
}
}
@ -517,8 +501,7 @@ jspb.Message.toObjectList = function(field, toObjectFn, opt_includeInstance) {
// And not using it here to avoid a function call.
var result = [];
for (var i = 0; i < field.length; i++) {
result[i] = toObjectFn.call(field[i], opt_includeInstance,
/** @type {!jspb.Message} */ (field[i]));
result[i] = toObjectFn.call(field[i], opt_includeInstance, field[i]);
}
return result;
};
@ -551,10 +534,11 @@ jspb.Message.toObjectExtension = function(proto, obj, extensions,
} else {
if (fieldInfo.isRepeated) {
obj[name] = jspb.Message.toObjectList(
/** @type {!Array<jspb.Message>} */ (value),
/** @type {!Array<!jspb.Message>} */ (value),
fieldInfo.toObjectFn, opt_includeInstance);
} else {
obj[name] = fieldInfo.toObjectFn(opt_includeInstance, value);
obj[name] = fieldInfo.toObjectFn(
opt_includeInstance, /** @type {!jspb.Message} */ (value));
}
}
}
@ -1419,7 +1403,7 @@ jspb.Message.prototype.setExtension = function(fieldInfo, value) {
if (fieldInfo.isMessageType()) {
self.wrappers_[fieldNumber] = value;
self.extensionObject_[fieldNumber] = goog.array.map(
/** @type {Array<jspb.Message>} */ (value), function(msg) {
/** @type {!Array<!jspb.Message>} */ (value), function(msg) {
return msg.toArray();
});
} else {
@ -1428,7 +1412,8 @@ jspb.Message.prototype.setExtension = function(fieldInfo, value) {
} else {
if (fieldInfo.isMessageType()) {
self.wrappers_[fieldNumber] = value;
self.extensionObject_[fieldNumber] = value ? value.toArray() : value;
self.extensionObject_[fieldNumber] =
value ? /** @type {!jspb.Message} */ (value).toArray() : value;
} else {
self.extensionObject_[fieldNumber] = value;
}
@ -1530,9 +1515,15 @@ jspb.Message.compareFields = function(field1, field2) {
// If the fields are trivially equal, they're equal.
if (field1 == field2) return true;
// If the fields aren't trivially equal and one of them isn't an object,
// they can't possibly be equal.
if (!goog.isObject(field1) || !goog.isObject(field2)) {
// NaN != NaN so we cover this case.
if ((goog.isNumber(field1) && isNaN(field1)) ||
(goog.isNumber(field2) && isNaN(field2))) {
// One of the fields might be a string 'NaN'.
return String(field1) == String(field2);
}
// If the fields aren't trivially equal and one of them isn't an object,
// they can't possibly be equal.
return false;
}
@ -1555,24 +1546,26 @@ jspb.Message.compareFields = function(field1, field2) {
// If they're both Arrays, compare them element by element except for the
// optional extension objects at the end, which we compare separately.
if (field1.constructor === Array) {
var typedField1 = /** @type {!Array<?>} */ (field1);
var typedField2 = /** @type {!Array<?>} */ (field2);
var extension1 = undefined;
var extension2 = undefined;
var length = Math.max(field1.length, field2.length);
var length = Math.max(typedField1.length, typedField2.length);
for (var i = 0; i < length; i++) {
var val1 = field1[i];
var val2 = field2[i];
var val1 = typedField1[i];
var val2 = typedField2[i];
if (val1 && (val1.constructor == Object)) {
goog.asserts.assert(extension1 === undefined);
goog.asserts.assert(i === field1.length - 1);
goog.asserts.assert(i === typedField1.length - 1);
extension1 = val1;
val1 = undefined;
}
if (val2 && (val2.constructor == Object)) {
goog.asserts.assert(extension2 === undefined);
goog.asserts.assert(i === field2.length - 1);
goog.asserts.assert(i === typedField2.length - 1);
extension2 = val2;
val2 = undefined;
}
@ -1695,8 +1688,13 @@ jspb.Message.clone_ = function(obj) {
var clonedArray = new Array(obj.length);
// Use array iteration where possible because it is faster than for-in.
for (var i = 0; i < obj.length; i++) {
if ((o = obj[i]) != null) {
clonedArray[i] = typeof o == 'object' ? jspb.Message.clone_(o) : o;
o = obj[i];
if (o != null) {
// NOTE:redundant null check existing for NTI compatibility.
// see b/70515949
clonedArray[i] = (typeof o == 'object') ?
jspb.Message.clone_(goog.asserts.assert(o)) :
o;
}
}
return clonedArray;
@ -1706,8 +1704,13 @@ jspb.Message.clone_ = function(obj) {
}
var clone = {};
for (var key in obj) {
if ((o = obj[key]) != null) {
clone[key] = typeof o == 'object' ? jspb.Message.clone_(o) : o;
o = obj[key];
if (o != null) {
// NOTE:redundant null check existing for NTI compatibility.
// see b/70515949
clone[key] = (typeof o == 'object') ?
jspb.Message.clone_(goog.asserts.assert(o)) :
o;
}
}
return clone;
@ -1723,6 +1726,9 @@ jspb.Message.registerMessageType = function(id, constructor) {
jspb.Message.registry_[id] = constructor;
// This is needed so we can later access messageId directly on the contructor,
// otherwise it is not available due to 'property collapsing' by the compiler.
/**
* @suppress {strictMissingProperties} messageId is not defined on Function
*/
constructor.messageId = id;
};

View File

@ -418,6 +418,18 @@ describe('Message test suite', function() {
['hi',,, {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
});
it('testEqualsNonFinite', function() {
assertTrue(jspb.Message.compareFields(NaN, NaN));
assertTrue(jspb.Message.compareFields(NaN, 'NaN'));
assertTrue(jspb.Message.compareFields('NaN', NaN));
assertTrue(jspb.Message.compareFields(Infinity, Infinity));
assertTrue(jspb.Message.compareFields(Infinity, 'Infinity'));
assertTrue(jspb.Message.compareFields('-Infinity', -Infinity));
assertTrue(jspb.Message.compareFields([NaN], ['NaN']));
assertFalse(jspb.Message.compareFields(undefined, NaN));
assertFalse(jspb.Message.compareFields(NaN, undefined));
});
it('testToMap', function() {
var p1 = new proto.jspb.test.Simple1(['k', ['v']]);
var p2 = new proto.jspb.test.Simple1(['k1', ['v1', 'v2']]);

View File

@ -34,6 +34,7 @@ file, in types that make this information accessible in Python.
__author__ = 'robinson@google.com (Will Robinson)'
import threading
import six
from google.protobuf.internal import api_implementation
@ -72,6 +73,24 @@ else:
DescriptorMetaclass = type
class _Lock(object):
"""Wrapper class of threading.Lock(), which is allowed by 'with'."""
def __new__(cls):
self = object.__new__(cls)
self._lock = threading.Lock() # pylint: disable=protected-access
return self
def __enter__(self):
self._lock.acquire()
def __exit__(self, exc_type, exc_value, exc_tb):
self._lock.release()
_lock = threading.Lock()
class DescriptorBase(six.with_metaclass(DescriptorMetaclass)):
"""Descriptors base class.
@ -92,16 +111,17 @@ class DescriptorBase(six.with_metaclass(DescriptorMetaclass)):
# subclasses" of this descriptor class.
_C_DESCRIPTOR_CLASS = ()
def __init__(self, options, options_class_name):
def __init__(self, options, serialized_options, options_class_name):
"""Initialize the descriptor given its options message and the name of the
class of the options message. The name of the class is required in case
the options message is None and has to be created.
"""
self._options = options
self._options_class_name = options_class_name
self._serialized_options = serialized_options
# Does this descriptor have non-default options?
self.has_options = options is not None
self.has_options = (options is not None) or (serialized_options is not None)
def _SetOptions(self, options, options_class_name):
"""Sets the descriptor's options
@ -123,14 +143,23 @@ class DescriptorBase(six.with_metaclass(DescriptorMetaclass)):
"""
if self._options:
return self._options
from google.protobuf import descriptor_pb2
try:
options_class = getattr(descriptor_pb2, self._options_class_name)
options_class = getattr(descriptor_pb2,
self._options_class_name)
except AttributeError:
raise RuntimeError('Unknown options class name %s!' %
(self._options_class_name))
self._options = options_class()
return self._options
with _lock:
if self._serialized_options is None:
self._options = options_class()
else:
self._options = _ParseOptions(options_class(),
self._serialized_options)
return self._options
class _NestedDescriptorBase(DescriptorBase):
@ -138,7 +167,7 @@ class _NestedDescriptorBase(DescriptorBase):
def __init__(self, options, options_class_name, name, full_name,
file, containing_type, serialized_start=None,
serialized_end=None):
serialized_end=None, serialized_options=None):
"""Constructor.
Args:
@ -157,9 +186,10 @@ class _NestedDescriptorBase(DescriptorBase):
file.serialized_pb that describes this descriptor.
serialized_end: The end index (exclusive) in block in the
file.serialized_pb that describes this descriptor.
serialized_options: Protocol message serilized options or None.
"""
super(_NestedDescriptorBase, self).__init__(
options, options_class_name)
options, serialized_options, options_class_name)
self.name = name
# TODO(falk): Add function to calculate full_name instead of having it in
@ -250,6 +280,7 @@ class Descriptor(_NestedDescriptorBase):
def __new__(cls, name, full_name, filename, containing_type, fields,
nested_types, enum_types, extensions, options=None,
serialized_options=None,
is_extendable=True, extension_ranges=None, oneofs=None,
file=None, serialized_start=None, serialized_end=None, # pylint: disable=redefined-builtin
syntax=None):
@ -261,6 +292,7 @@ class Descriptor(_NestedDescriptorBase):
# name of the argument.
def __init__(self, name, full_name, filename, containing_type, fields,
nested_types, enum_types, extensions, options=None,
serialized_options=None,
is_extendable=True, extension_ranges=None, oneofs=None,
file=None, serialized_start=None, serialized_end=None, # pylint: disable=redefined-builtin
syntax=None):
@ -273,7 +305,7 @@ class Descriptor(_NestedDescriptorBase):
super(Descriptor, self).__init__(
options, 'MessageOptions', name, full_name, file,
containing_type, serialized_start=serialized_start,
serialized_end=serialized_end)
serialized_end=serialized_end, serialized_options=serialized_options)
# We have fields in addition to fields_by_name and fields_by_number,
# so that:
@ -492,8 +524,9 @@ class FieldDescriptor(DescriptorBase):
def __new__(cls, name, full_name, index, number, type, cpp_type, label,
default_value, message_type, enum_type, containing_type,
is_extension, extension_scope, options=None,
serialized_options=None,
has_default_value=True, containing_oneof=None, json_name=None,
file=None):
file=None): # pylint: disable=redefined-builtin
_message.Message._CheckCalledFromGeneratedFile()
if is_extension:
return _message.default_pool.FindExtensionByName(full_name)
@ -503,8 +536,9 @@ class FieldDescriptor(DescriptorBase):
def __init__(self, name, full_name, index, number, type, cpp_type, label,
default_value, message_type, enum_type, containing_type,
is_extension, extension_scope, options=None,
serialized_options=None,
has_default_value=True, containing_oneof=None, json_name=None,
file=None):
file=None): # pylint: disable=redefined-builtin
"""The arguments are as described in the description of FieldDescriptor
attributes above.
@ -512,7 +546,8 @@ class FieldDescriptor(DescriptorBase):
(to deal with circular references between message types, for example).
Likewise for extension_scope.
"""
super(FieldDescriptor, self).__init__(options, 'FieldOptions')
super(FieldDescriptor, self).__init__(
options, serialized_options, 'FieldOptions')
self.name = name
self.full_name = full_name
self.file = file
@ -598,13 +633,15 @@ class EnumDescriptor(_NestedDescriptorBase):
_C_DESCRIPTOR_CLASS = _message.EnumDescriptor
def __new__(cls, name, full_name, filename, values,
containing_type=None, options=None, file=None,
containing_type=None, options=None,
serialized_options=None, file=None, # pylint: disable=redefined-builtin
serialized_start=None, serialized_end=None):
_message.Message._CheckCalledFromGeneratedFile()
return _message.default_pool.FindEnumTypeByName(full_name)
def __init__(self, name, full_name, filename, values,
containing_type=None, options=None, file=None,
containing_type=None, options=None,
serialized_options=None, file=None, # pylint: disable=redefined-builtin
serialized_start=None, serialized_end=None):
"""Arguments are as described in the attribute description above.
@ -614,7 +651,7 @@ class EnumDescriptor(_NestedDescriptorBase):
super(EnumDescriptor, self).__init__(
options, 'EnumOptions', name, full_name, file,
containing_type, serialized_start=serialized_start,
serialized_end=serialized_end)
serialized_end=serialized_end, serialized_options=serialized_options)
self.values = values
for value in self.values:
@ -650,7 +687,9 @@ class EnumValueDescriptor(DescriptorBase):
if _USE_C_DESCRIPTORS:
_C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor
def __new__(cls, name, index, number, type=None, options=None):
def __new__(cls, name, index, number,
type=None, # pylint: disable=redefined-builtin
options=None, serialized_options=None):
_message.Message._CheckCalledFromGeneratedFile()
# There is no way we can build a complete EnumValueDescriptor with the
# given parameters (the name of the Enum is not known, for example).
@ -658,9 +697,12 @@ class EnumValueDescriptor(DescriptorBase):
# constructor, which will ignore it, so returning None is good enough.
return None
def __init__(self, name, index, number, type=None, options=None):
def __init__(self, name, index, number,
type=None, # pylint: disable=redefined-builtin
options=None, serialized_options=None):
"""Arguments are as described in the attribute description above."""
super(EnumValueDescriptor, self).__init__(options, 'EnumValueOptions')
super(EnumValueDescriptor, self).__init__(
options, serialized_options, 'EnumValueOptions')
self.name = name
self.index = index
self.number = number
@ -685,14 +727,17 @@ class OneofDescriptor(DescriptorBase):
_C_DESCRIPTOR_CLASS = _message.OneofDescriptor
def __new__(
cls, name, full_name, index, containing_type, fields, options=None):
cls, name, full_name, index, containing_type, fields, options=None,
serialized_options=None):
_message.Message._CheckCalledFromGeneratedFile()
return _message.default_pool.FindOneofByName(full_name)
def __init__(
self, name, full_name, index, containing_type, fields, options=None):
self, name, full_name, index, containing_type, fields, options=None,
serialized_options=None):
"""Arguments are as described in the attribute description above."""
super(OneofDescriptor, self).__init__(options, 'OneofOptions')
super(OneofDescriptor, self).__init__(
options, serialized_options, 'OneofOptions')
self.name = name
self.full_name = full_name
self.index = index
@ -721,17 +766,19 @@ class ServiceDescriptor(_NestedDescriptorBase):
if _USE_C_DESCRIPTORS:
_C_DESCRIPTOR_CLASS = _message.ServiceDescriptor
def __new__(cls, name, full_name, index, methods, options=None, file=None, # pylint: disable=redefined-builtin
def __new__(cls, name, full_name, index, methods, options=None,
serialized_options=None, file=None, # pylint: disable=redefined-builtin
serialized_start=None, serialized_end=None):
_message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access
return _message.default_pool.FindServiceByName(full_name)
def __init__(self, name, full_name, index, methods, options=None, file=None,
def __init__(self, name, full_name, index, methods, options=None,
serialized_options=None, file=None, # pylint: disable=redefined-builtin
serialized_start=None, serialized_end=None):
super(ServiceDescriptor, self).__init__(
options, 'ServiceOptions', name, full_name, file,
None, serialized_start=serialized_start,
serialized_end=serialized_end)
serialized_end=serialized_end, serialized_options=serialized_options)
self.index = index
self.methods = methods
self.methods_by_name = dict((m.name, m) for m in methods)
@ -772,18 +819,19 @@ class MethodDescriptor(DescriptorBase):
_C_DESCRIPTOR_CLASS = _message.MethodDescriptor
def __new__(cls, name, full_name, index, containing_service,
input_type, output_type, options=None):
input_type, output_type, options=None, serialized_options=None):
_message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access
return _message.default_pool.FindMethodByName(full_name)
def __init__(self, name, full_name, index, containing_service,
input_type, output_type, options=None):
input_type, output_type, options=None, serialized_options=None):
"""The arguments are as described in the description of MethodDescriptor
attributes above.
Note that containing_service may be None, and may be set later if necessary.
"""
super(MethodDescriptor, self).__init__(options, 'MethodOptions')
super(MethodDescriptor, self).__init__(
options, serialized_options, 'MethodOptions')
self.name = name
self.full_name = full_name
self.index = index
@ -818,7 +866,8 @@ class FileDescriptor(DescriptorBase):
if _USE_C_DESCRIPTORS:
_C_DESCRIPTOR_CLASS = _message.FileDescriptor
def __new__(cls, name, package, options=None, serialized_pb=None,
def __new__(cls, name, package, options=None,
serialized_options=None, serialized_pb=None,
dependencies=None, public_dependencies=None,
syntax=None, pool=None):
# FileDescriptor() is called from various places, not only from generated
@ -830,11 +879,13 @@ class FileDescriptor(DescriptorBase):
else:
return super(FileDescriptor, cls).__new__(cls)
def __init__(self, name, package, options=None, serialized_pb=None,
def __init__(self, name, package, options=None,
serialized_options=None, serialized_pb=None,
dependencies=None, public_dependencies=None,
syntax=None, pool=None):
"""Constructor."""
super(FileDescriptor, self).__init__(options, 'FileOptions')
super(FileDescriptor, self).__init__(
options, serialized_options, 'FileOptions')
if pool is None:
from google.protobuf import descriptor_pool

View File

@ -37,8 +37,8 @@ argument tuples.
A simple example:
class AdditionExample(parameterized.ParameterizedTestCase):
@parameterized.Parameters(
class AdditionExample(parameterized.TestCase):
@parameterized.parameters(
(1, 2, 3),
(4, 5, 9),
(1, 1, 3))
@ -54,8 +54,8 @@ fail due to an assertion error (1 + 1 != 3).
Parameters for invididual test cases can be tuples (with positional parameters)
or dictionaries (with named parameters):
class AdditionExample(parameterized.ParameterizedTestCase):
@parameterized.Parameters(
class AdditionExample(parameterized.TestCase):
@parameterized.parameters(
{'op1': 1, 'op2': 2, 'result': 3},
{'op1': 4, 'op2': 5, 'result': 9},
)
@ -77,13 +77,13 @@ stay the same across several invocations, object representations like
'<__main__.Foo object at 0x23d8610>'
are turned into '<__main__.Foo>'. For even more descriptive names,
especially in test logs, you can use the NamedParameters decorator. In
especially in test logs, you can use the named_parameters decorator. In
this case, only tuples are supported, and the first parameters has to
be a string (or an object that returns an apt name when converted via
str()):
class NamedExample(parameterized.ParameterizedTestCase):
@parameterized.NamedParameters(
class NamedExample(parameterized.TestCase):
@parameterized.named_parameters(
('Normal', 'aa', 'aaa', True),
('EmptyPrefix', '', 'abc', True),
('BothEmpty', '', '', True))
@ -103,13 +103,13 @@ from the command line:
Parameterized Classes
=====================
If invocation arguments are shared across test methods in a single
ParameterizedTestCase class, instead of decorating all test methods
TestCase class, instead of decorating all test methods
individually, the class itself can be decorated:
@parameterized.Parameters(
@parameterized.parameters(
(1, 2, 3)
(4, 5, 9))
class ArithmeticTest(parameterized.ParameterizedTestCase):
class ArithmeticTest(parameterized.TestCase):
def testAdd(self, arg1, arg2, result):
self.assertEqual(arg1 + arg2, result)
@ -122,8 +122,8 @@ If parameters should be shared across several test cases, or are dynamically
created from other sources, a single non-tuple iterable can be passed into
the decorator. This iterable will be used to obtain the test cases:
class AdditionExample(parameterized.ParameterizedTestCase):
@parameterized.Parameters(
class AdditionExample(parameterized.TestCase):
@parameterized.parameters(
c.op1, c.op2, c.result for c in testcases
)
def testAddition(self, op1, op2, result):
@ -135,8 +135,8 @@ Single-Argument Test Methods
If a test method takes only one argument, the single argument does not need to
be wrapped into a tuple:
class NegativeNumberExample(parameterized.ParameterizedTestCase):
@parameterized.Parameters(
class NegativeNumberExample(parameterized.TestCase):
@parameterized.parameters(
-1, -3, -4, -5
)
def testIsNegative(self, arg):
@ -212,7 +212,7 @@ class _ParameterizedTestIter(object):
def __call__(self, *args, **kwargs):
raise RuntimeError('You appear to be running a parameterized test case '
'without having inherited from parameterized.'
'ParameterizedTestCase. This is bad because none of '
'TestCase. This is bad because none of '
'your test cases are actually being run.')
def __iter__(self):
@ -306,7 +306,7 @@ def _ParameterDecorator(naming_type, testcases):
return _Apply
def Parameters(*testcases):
def parameters(*testcases): # pylint: disable=invalid-name
"""A decorator for creating parameterized tests.
See the module docstring for a usage example.
@ -321,7 +321,7 @@ def Parameters(*testcases):
return _ParameterDecorator(_ARGUMENT_REPR, testcases)
def NamedParameters(*testcases):
def named_parameters(*testcases): # pylint: disable=invalid-name
"""A decorator for creating parameterized tests.
See the module docstring for a usage example. The first element of
@ -348,7 +348,7 @@ class TestGeneratorMetaclass(type):
up as tests by the unittest framework.
In general, it is supposed to be used in conjunction with the
Parameters decorator.
parameters decorator.
"""
def __new__(mcs, class_name, bases, dct):
@ -385,8 +385,8 @@ def _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator):
id_suffix[new_name] = getattr(func, '__x_extra_id__', '')
class ParameterizedTestCase(unittest.TestCase):
"""Base class for test cases using the Parameters decorator."""
class TestCase(unittest.TestCase):
"""Base class for test cases using the parameters decorator."""
__metaclass__ = TestGeneratorMetaclass
def _OriginalName(self):
@ -409,10 +409,10 @@ class ParameterizedTestCase(unittest.TestCase):
self._id_suffix.get(self._testMethodName, ''))
def CoopParameterizedTestCase(other_base_class):
def CoopTestCase(other_base_class):
"""Returns a new base class with a cooperative metaclass base.
This enables the ParameterizedTestCase to be used in combination
This enables the TestCase to be used in combination
with other base classes that have custom metaclasses, such as
mox.MoxTestBase.
@ -425,7 +425,7 @@ def CoopParameterizedTestCase(other_base_class):
from google3.testing.pybase import parameterized
class ExampleTest(parameterized.CoopParameterizedTestCase(mox.MoxTestBase)):
class ExampleTest(parameterized.CoopTestCase(mox.MoxTestBase)):
...
Args:
@ -439,5 +439,5 @@ def CoopParameterizedTestCase(other_base_class):
(other_base_class.__metaclass__,
TestGeneratorMetaclass), {})
return metaclass(
'CoopParameterizedTestCase',
(other_base_class, ParameterizedTestCase), {})
'CoopTestCase',
(other_base_class, TestCase), {})

View File

@ -66,10 +66,13 @@ if _api_version < 0: # Still unspecified?
from google.protobuf.internal import use_pure_python
del use_pure_python # Avoids a pylint error and namespace pollution.
except ImportError:
if _proto_extension_modules_exist_in_build:
if sys.version_info[0] >= 3: # Python 3 defaults to C++ impl v2.
_api_version = 2
# TODO(b/17427486): Make Python 2 default to C++ impl v2.
# TODO(b/74017912): It's unsafe to enable :use_fast_cpp_protos by default;
# it can cause data loss if you have any Python-only extensions to any
# message passed back and forth with C++ code.
#
# TODO(b/17427486): Once that bug is fixed, we want to make both Python 2
# and Python 3 default to `_api_version = 2` (C++ implementation V2).
pass
_default_implementation_type = (
'python' if _api_version <= 0 else 'cpp')

View File

@ -372,7 +372,7 @@ def MapSizer(field_descriptor, is_message_map):
def _VarintEncoder():
"""Return an encoder for a basic varint value (does not include tag)."""
def EncodeVarint(write, value, unused_deterministic):
def EncodeVarint(write, value, unused_deterministic=None):
bits = value & 0x7f
value >>= 7
while value:
@ -388,7 +388,7 @@ def _SignedVarintEncoder():
"""Return an encoder for a basic signed varint value (does not include
tag)."""
def EncodeSignedVarint(write, value, unused_deterministic):
def EncodeSignedVarint(write, value, unused_deterministic=None):
if value < 0:
value += (1 << 64)
bits = value & 0x7f
@ -524,14 +524,14 @@ def _StructPackEncoder(wire_type, format):
return EncodePackedField
elif is_repeated:
tag_bytes = TagBytes(field_number, wire_type)
def EncodeRepeatedField(write, value, unused_deterministic):
def EncodeRepeatedField(write, value, unused_deterministic=None):
for element in value:
write(tag_bytes)
write(local_struct_pack(format, element))
return EncodeRepeatedField
else:
tag_bytes = TagBytes(field_number, wire_type)
def EncodeField(write, value, unused_deterministic):
def EncodeField(write, value, unused_deterministic=None):
write(tag_bytes)
return write(local_struct_pack(format, value))
return EncodeField
@ -595,7 +595,7 @@ def _FloatingPointEncoder(wire_type, format):
return EncodePackedField
elif is_repeated:
tag_bytes = TagBytes(field_number, wire_type)
def EncodeRepeatedField(write, value, unused_deterministic):
def EncodeRepeatedField(write, value, unused_deterministic=None):
for element in value:
write(tag_bytes)
try:
@ -605,7 +605,7 @@ def _FloatingPointEncoder(wire_type, format):
return EncodeRepeatedField
else:
tag_bytes = TagBytes(field_number, wire_type)
def EncodeField(write, value, unused_deterministic):
def EncodeField(write, value, unused_deterministic=None):
write(tag_bytes)
try:
write(local_struct_pack(format, value))
@ -662,7 +662,7 @@ def BoolEncoder(field_number, is_repeated, is_packed):
return EncodePackedField
elif is_repeated:
tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
def EncodeRepeatedField(write, value, unused_deterministic):
def EncodeRepeatedField(write, value, unused_deterministic=None):
for element in value:
write(tag_bytes)
if element:
@ -672,7 +672,7 @@ def BoolEncoder(field_number, is_repeated, is_packed):
return EncodeRepeatedField
else:
tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
def EncodeField(write, value, unused_deterministic):
def EncodeField(write, value, unused_deterministic=None):
write(tag_bytes)
if value:
return write(true_byte)

View File

@ -983,6 +983,18 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual('{\n"int32Value": 12345\n}',
json_format.MessageToJson(message, indent=0))
def testFormatEnumsAsInts(self):
message = json_format_proto3_pb2.TestMessage()
message.enum_value = json_format_proto3_pb2.BAR
message.repeated_enum_value.append(json_format_proto3_pb2.FOO)
message.repeated_enum_value.append(json_format_proto3_pb2.BAR)
self.assertEqual(json.loads('{\n'
' "enumValue": 1,\n'
' "repeatedEnumValue": [0, 1]\n'
'}\n'),
json.loads(json_format.MessageToJson(
message, use_integers_for_enums=True)))
def testParseDict(self):
expected = 12345
js_dict = {'int32Value': expected}

View File

@ -99,7 +99,7 @@ def IsNegInf(val):
BaseTestCase = testing_refleaks.BaseTestCase
@_parameterized.NamedParameters(
@_parameterized.named_parameters(
('_proto2', unittest_pb2),
('_proto3', unittest_proto3_arena_pb2))
class MessageTest(BaseTestCase):
@ -1694,6 +1694,33 @@ class Proto3Test(BaseTestCase):
with self.assertRaises(TypeError):
del msg2.map_int32_foreign_message['']
def testMapMergeFrom(self):
msg = map_unittest_pb2.TestMap()
msg.map_int32_int32[12] = 34
msg.map_int32_int32[56] = 78
msg.map_int64_int64[22] = 33
msg.map_int32_foreign_message[111].c = 5
msg.map_int32_foreign_message[222].c = 10
msg2 = map_unittest_pb2.TestMap()
msg2.map_int32_int32[12] = 55
msg2.map_int64_int64[88] = 99
msg2.map_int32_foreign_message[222].c = 15
msg2.map_int32_foreign_message[222].d = 20
msg2.map_int32_int32.MergeFrom(msg.map_int32_int32)
self.assertEqual(34, msg2.map_int32_int32[12])
self.assertEqual(78, msg2.map_int32_int32[56])
msg2.map_int64_int64.MergeFrom(msg.map_int64_int64)
self.assertEqual(33, msg2.map_int64_int64[22])
self.assertEqual(99, msg2.map_int64_int64[88])
msg2.map_int32_foreign_message.MergeFrom(msg.map_int32_foreign_message)
self.assertEqual(5, msg2.map_int32_foreign_message[111].c)
self.assertEqual(10, msg2.map_int32_foreign_message[222].c)
self.assertFalse(msg2.map_int32_foreign_message[222].HasField('d'))
def testMergeFromBadType(self):
msg = map_unittest_pb2.TestMap()
with self.assertRaisesRegexp(

View File

@ -0,0 +1,12 @@
syntax = "proto2";
option py_api_version = 2;
enum NoPackageEnum {
NO_PACKAGE_VALUE_0 = 0;
NO_PACKAGE_VALUE_1 = 1;
}
message NoPackageMessage {
optional NoPackageEnum no_package_enum = 1;
}

View File

@ -48,6 +48,7 @@ except ImportError:
from google.protobuf.internal import _parameterized
from google.protobuf import any_pb2
from google.protobuf import any_test_pb2
from google.protobuf import map_unittest_pb2
from google.protobuf import unittest_mset_pb2
@ -99,7 +100,7 @@ class TextFormatBase(unittest.TestCase):
return text
@_parameterized.Parameters((unittest_pb2), (unittest_proto3_arena_pb2))
@_parameterized.parameters((unittest_pb2), (unittest_proto3_arena_pb2))
class TextFormatTest(TextFormatBase):
def testPrintExotic(self, message_module):
@ -369,6 +370,7 @@ class TextFormatTest(TextFormatBase):
def testParseRepeatedScalarShortFormat(self, message_module):
message = message_module.TestAllTypes()
text = ('repeated_int64: [100, 200];\n'
'repeated_int64: []\n'
'repeated_int64: 300,\n'
'repeated_string: ["one", "two"];\n')
text_format.Parse(text, message)
@ -524,20 +526,68 @@ class OnlyWorksWithProto2RightNowTests(TextFormatBase):
def testPrintInIndexOrder(self):
message = unittest_pb2.TestFieldOrderings()
message.my_string = '115'
# Fields are listed in index order instead of field number.
message.my_string = 'str'
message.my_int = 101
message.my_float = 111
message.optional_nested_message.oo = 0
message.optional_nested_message.bb = 1
message.Extensions[unittest_pb2.my_extension_string] = 'ext_str0'
# Extensions are listed based on the order of extension number.
# Extension number 12.
message.Extensions[unittest_pb2.TestExtensionOrderings2.
test_ext_orderings2].my_string = 'ext_str2'
# Extension number 13.
message.Extensions[unittest_pb2.TestExtensionOrderings1.
test_ext_orderings1].my_string = 'ext_str1'
# Extension number 14.
message.Extensions[
unittest_pb2.TestExtensionOrderings2.TestExtensionOrderings3.
test_ext_orderings3].my_string = 'ext_str3'
# Print in index order.
self.CompareToGoldenText(
self.RemoveRedundantZeros(text_format.MessageToString(
message, use_index_order=True)),
'my_string: \"115\"\nmy_int: 101\nmy_float: 111\n'
'optional_nested_message {\n oo: 0\n bb: 1\n}\n')
self.RemoveRedundantZeros(
text_format.MessageToString(message, use_index_order=True)),
'my_string: "str"\n'
'my_int: 101\n'
'my_float: 111\n'
'optional_nested_message {\n'
' oo: 0\n'
' bb: 1\n'
'}\n'
'[protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] {\n'
' my_string: "ext_str2"\n'
'}\n'
'[protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1] {\n'
' my_string: "ext_str1"\n'
'}\n'
'[protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3'
'.test_ext_orderings3] {\n'
' my_string: "ext_str3"\n'
'}\n'
'[protobuf_unittest.my_extension_string]: "ext_str0"\n')
# By default, print in field number order.
self.CompareToGoldenText(
self.RemoveRedundantZeros(text_format.MessageToString(message)),
'my_int: 101\nmy_string: \"115\"\nmy_float: 111\n'
'optional_nested_message {\n bb: 1\n oo: 0\n}\n')
'my_int: 101\n'
'my_string: "str"\n'
'[protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] {\n'
' my_string: "ext_str2"\n'
'}\n'
'[protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1] {\n'
' my_string: "ext_str1"\n'
'}\n'
'[protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3'
'.test_ext_orderings3] {\n'
' my_string: "ext_str3"\n'
'}\n'
'[protobuf_unittest.my_extension_string]: "ext_str0"\n'
'my_float: 111\n'
'optional_nested_message {\n'
' bb: 1\n'
' oo: 0\n'
'}\n')
def testMergeLinesGolden(self):
opened = self.ReadGolden('text_format_unittest_data_oneof_implemented.txt')
@ -970,15 +1020,26 @@ class Proto2Tests(TextFormatBase):
'"protobuf_unittest.optional_int32_extension" extensions.'),
text_format.Parse, text, message)
def testParseDuplicateNestedMessageScalars(self):
def testParseDuplicateMessages(self):
message = unittest_pb2.TestAllTypes()
text = ('optional_nested_message { bb: 1 } '
'optional_nested_message { bb: 2 }')
six.assertRaisesRegex(self, text_format.ParseError, (
'1:65 : Message type "protobuf_unittest.TestAllTypes.NestedMessage" '
'should not have multiple "bb" fields.'), text_format.Parse, text,
'1:59 : Message type "protobuf_unittest.TestAllTypes" '
'should not have multiple "optional_nested_message" fields.'),
text_format.Parse, text,
message)
def testParseDuplicateExtensionMessages(self):
message = unittest_pb2.TestAllExtensions()
text = ('[protobuf_unittest.optional_nested_message_extension]: {} '
'[protobuf_unittest.optional_nested_message_extension]: {}')
six.assertRaisesRegex(self, text_format.ParseError, (
'1:114 : Message type "protobuf_unittest.TestAllExtensions" '
'should not have multiple '
'"protobuf_unittest.optional_nested_message_extension" extensions.'),
text_format.Parse, text, message)
def testParseDuplicateScalars(self):
message = unittest_pb2.TestAllTypes()
text = ('optional_int32: 42 ' 'optional_int32: 67')
@ -1065,6 +1126,14 @@ class Proto3Tests(unittest.TestCase):
' }\n'
'}\n')
def testTopAnyMessage(self):
packed_msg = unittest_pb2.OneString()
msg = any_pb2.Any()
msg.Pack(packed_msg)
text = text_format.MessageToString(msg)
other_msg = text_format.Parse(text, any_pb2.Any())
self.assertEqual(msg, other_msg)
def testPrintMessageExpandAnyRepeated(self):
packed_message = unittest_pb2.OneString()
message = any_test_pb2.TestAny()
@ -1489,7 +1558,7 @@ class TokenizerTest(unittest.TestCase):
# Tests for pretty printer functionality.
@_parameterized.Parameters((unittest_pb2), (unittest_proto3_arena_pb2))
@_parameterized.parameters((unittest_pb2), (unittest_proto3_arena_pb2))
class PrettyPrinterTest(TextFormatBase):
def testPrettyPrintNoMatch(self, message_module):

View File

@ -375,6 +375,9 @@ def _CheckDurationValid(seconds, nanos):
raise Error(
'Duration is not valid: Nanos {0} must be in range '
'[-999999999, 999999999].'.format(nanos))
if (nanos < 0 and seconds > 0) or (nanos > 0 and seconds < 0):
raise Error(
'Duration is not valid: Sign mismatch.')
def _RoundTowardZero(value, divider):
@ -649,9 +652,10 @@ def _MergeMessage(
raise ValueError('Error: Field {0} in message {1} is not a singular '
'message field and cannot have sub-fields.'.format(
name, source_descriptor.full_name))
_MergeMessage(
child, getattr(source, name), getattr(destination, name),
replace_message, replace_repeated)
if source.HasField(name):
_MergeMessage(
child, getattr(source, name), getattr(destination, name),
replace_message, replace_repeated)
continue
if field.label == FieldDescriptor.LABEL_REPEATED:
if replace_repeated:

View File

@ -345,6 +345,12 @@ class TimeUtilTest(TimeUtilTestBase):
r'Duration is not valid\: Nanos 1000000000 must be in range'
r' \[-999999999\, 999999999\].',
message.ToJsonString)
message.seconds = -1
message.nanos = 1
self.assertRaisesRegexp(
well_known_types.Error,
r'Duration is not valid\: Sign mismatch.',
message.ToJsonString)
class FieldMaskTest(unittest.TestCase):
@ -599,6 +605,16 @@ class FieldMaskTest(unittest.TestCase):
self.assertEqual(1, len(nested_dst.payload.repeated_int32))
self.assertEqual(1234, nested_dst.payload.repeated_int32[0])
# Test Merge oneof field.
new_msg = unittest_pb2.TestOneof2()
dst = unittest_pb2.TestOneof2()
dst.foo_message.qux_int = 1
mask = field_mask_pb2.FieldMask()
mask.FromJsonString('fooMessage,fooLazyMessage.quxInt')
mask.MergeMessage(new_msg, dst)
self.assertTrue(dst.HasField('foo_message'))
self.assertFalse(dst.HasField('foo_lazy_message'))
def testMergeErrors(self):
src = unittest_pb2.TestAllTypes()
dst = unittest_pb2.TestAllTypes()

View File

@ -42,21 +42,28 @@ Simple usage example:
__author__ = 'jieluo@google.com (Jie Luo)'
# pylint: disable=g-statement-before-imports,g-import-not-at-top
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict #PY26
from ordereddict import OrderedDict # PY26
# pylint: enable=g-statement-before-imports,g-import-not-at-top
import base64
import json
import math
import re
import six
import sys
from operator import methodcaller
import re
import sys
import six
from google.protobuf import descriptor
from google.protobuf import symbol_database
_TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S'
_INT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT32,
descriptor.FieldDescriptor.CPPTYPE_UINT32,
@ -93,7 +100,8 @@ def MessageToJson(message,
including_default_value_fields=False,
preserving_proto_field_name=False,
indent=2,
sort_keys=False):
sort_keys=False,
use_integers_for_enums=False):
"""Converts protobuf message to JSON format.
Args:
@ -108,18 +116,21 @@ def MessageToJson(message,
indent: The JSON object will be pretty-printed with this indent level.
An indent level of 0 or negative will only insert newlines.
sort_keys: If True, then the output will be sorted by field names.
use_integers_for_enums: If true, print integers instead of enum names.
Returns:
A string containing the JSON formatted protocol buffer message.
"""
printer = _Printer(including_default_value_fields,
preserving_proto_field_name)
preserving_proto_field_name,
use_integers_for_enums)
return printer.ToJsonString(message, indent, sort_keys)
def MessageToDict(message,
including_default_value_fields=False,
preserving_proto_field_name=False):
preserving_proto_field_name=False,
use_integers_for_enums=False):
"""Converts protobuf message to a dictionary.
When the dictionary is encoded to JSON, it conforms to proto3 JSON spec.
@ -133,12 +144,14 @@ def MessageToDict(message,
preserving_proto_field_name: If True, use the original proto field
names as defined in the .proto file. If False, convert the field
names to lowerCamelCase.
use_integers_for_enums: If true, print integers instead of enum names.
Returns:
A dict representation of the protocol buffer message.
"""
printer = _Printer(including_default_value_fields,
preserving_proto_field_name)
preserving_proto_field_name,
use_integers_for_enums)
# pylint: disable=protected-access
return printer._MessageToJsonObject(message)
@ -154,9 +167,11 @@ class _Printer(object):
def __init__(self,
including_default_value_fields=False,
preserving_proto_field_name=False):
preserving_proto_field_name=False,
use_integers_for_enums=False):
self.including_default_value_fields = including_default_value_fields
self.preserving_proto_field_name = preserving_proto_field_name
self.use_integers_for_enums = use_integers_for_enums
def ToJsonString(self, message, indent, sort_keys):
js = self._MessageToJsonObject(message)
@ -247,6 +262,8 @@ class _Printer(object):
if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
return self._MessageToJsonObject(value)
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
if self.use_integers_for_enums:
return value
enum_value = field.enum_type.values_by_number.get(value, None)
if enum_value is not None:
return enum_value.name

View File

@ -188,38 +188,35 @@ const FileDescriptor* GetFileDescriptor(const MethodDescriptor* descriptor) {
// Always returns a new reference.
template<class DescriptorClass>
static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
// Options (and their extensions) are completely resolved in the proto file
// containing the descriptor.
PyDescriptorPool* pool = GetDescriptorPool_FromPool(
GetFileDescriptor(descriptor)->pool());
hash_map<const void*, PyObject*>* descriptor_options =
pool->descriptor_options;
// Options are cached in the pool that owns the descriptor.
// First search in the cache.
PyDescriptorPool* caching_pool = GetDescriptorPool_FromPool(
GetFileDescriptor(descriptor)->pool());
hash_map<const void*, PyObject*>* descriptor_options =
caching_pool->descriptor_options;
if (descriptor_options->find(descriptor) != descriptor_options->end()) {
PyObject *value = (*descriptor_options)[descriptor];
Py_INCREF(value);
return value;
}
// Similar to the C++ implementation, we return an Options object from the
// default (generated) factory, so that client code know that they can use
// extensions from generated files:
// d.GetOptions().Extensions[some_pb2.extension]
//
// The consequence is that extensions not defined in the default pool won't
// be available. If needed, we could add an optional 'message_factory'
// parameter to the GetOptions() function.
PyMessageFactory* message_factory =
GetDefaultDescriptorPool()->py_message_factory;
// Build the Options object: get its Python class, and make a copy of the C++
// read-only instance.
const Message& options(descriptor->options());
const Descriptor *message_type = options.GetDescriptor();
PyMessageFactory* message_factory = pool->py_message_factory;
CMessageClass* message_class = message_factory::GetMessageClass(
CMessageClass* message_class = message_factory::GetOrCreateMessageClass(
message_factory, message_type);
if (message_class == NULL) {
// The Options message was not found in the current DescriptorPool.
// This means that the pool cannot contain any extensions to the Options
// message either, so falling back to the basic pool we can only increase
// the chances of successfully parsing the options.
PyErr_Clear();
pool = GetDefaultDescriptorPool();
message_factory = pool->py_message_factory;
message_class = message_factory::GetMessageClass(
message_factory, message_type);
}
if (message_class == NULL) {
PyErr_Format(PyExc_TypeError, "Could not retrieve class for Options: %s",
message_type->full_name().c_str());
@ -248,7 +245,8 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
options.SerializeToString(&serialized);
io::CodedInputStream input(
reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
input.SetExtensionRegistry(pool->pool, message_factory->message_factory);
input.SetExtensionRegistry(message_factory->pool->pool,
message_factory->message_factory);
bool success = cmsg->message->MergePartialFromCodedStream(&input);
if (!success) {
PyErr_Format(PyExc_ValueError, "Error parsing Options message");
@ -564,6 +562,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
return CheckCalledFromGeneratedFile("_options");
}
static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
void *closure) {
return CheckCalledFromGeneratedFile("_serialized_options");
}
static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
return CopyToPythonProto<DescriptorProto>(_GetDescriptor(self), target);
}
@ -623,6 +626,8 @@ static PyGetSetDef Getters[] = {
{ "is_extendable", (getter)IsExtendable, (setter)NULL},
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
{ "_options", (getter)NULL, (setter)SetOptions, "Options"},
{ "_serialized_options", (getter)NULL, (setter)SetSerializedOptions,
"Serialized Options"},
{ "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"},
{NULL}
};
@ -785,7 +790,7 @@ static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) {
break;
}
case FieldDescriptor::CPPTYPE_STRING: {
string value = _GetDescriptor(self)->default_value_string();
const string& value = _GetDescriptor(self)->default_value_string();
result = ToStringObject(_GetDescriptor(self), value);
break;
}
@ -897,6 +902,10 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
return CheckCalledFromGeneratedFile("_options");
}
static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
void *closure) {
return CheckCalledFromGeneratedFile("_serialized_options");
}
static PyGetSetDef Getters[] = {
{ "full_name", (getter)GetFullName, NULL, "Full name"},
@ -926,6 +935,8 @@ static PyGetSetDef Getters[] = {
"Containing oneof"},
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
{ "_options", (getter)NULL, (setter)SetOptions, "Options"},
{ "_serialized_options", (getter)NULL, (setter)SetSerializedOptions,
"Serialized Options"},
{NULL}
};
@ -1055,6 +1066,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
return CheckCalledFromGeneratedFile("_options");
}
static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
void *closure) {
return CheckCalledFromGeneratedFile("_serialized_options");
}
static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
return CopyToPythonProto<EnumDescriptorProto>(_GetDescriptor(self), target);
}
@ -1079,6 +1095,8 @@ static PyGetSetDef Getters[] = {
"Containing type"},
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
{ "_options", (getter)NULL, (setter)SetOptions, "Options"},
{ "_serialized_options", (getter)NULL, (setter)SetSerializedOptions,
"Serialized Options"},
{NULL}
};
@ -1179,6 +1197,10 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
return CheckCalledFromGeneratedFile("_options");
}
static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
void *closure) {
return CheckCalledFromGeneratedFile("_serialized_options");
}
static PyGetSetDef Getters[] = {
{ "name", (getter)GetName, NULL, "name"},
@ -1188,6 +1210,8 @@ static PyGetSetDef Getters[] = {
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
{ "_options", (getter)NULL, (setter)SetOptions, "Options"},
{ "_serialized_options", (getter)NULL, (setter)SetSerializedOptions,
"Serialized Options"},
{NULL}
};
@ -1330,6 +1354,11 @@ static int SetOptions(PyFileDescriptor *self, PyObject *value,
return CheckCalledFromGeneratedFile("_options");
}
static int SetSerializedOptions(PyFileDescriptor *self, PyObject *value,
void *closure) {
return CheckCalledFromGeneratedFile("_serialized_options");
}
static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) {
return PyString_InternFromString(
FileDescriptor::SyntaxName(_GetDescriptor(self)->syntax()));
@ -1355,6 +1384,8 @@ static PyGetSetDef Getters[] = {
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
{ "_options", (getter)NULL, (setter)SetOptions, "Options"},
{ "_serialized_options", (getter)NULL, (setter)SetSerializedOptions,
"Serialized Options"},
{ "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"},
{NULL}
};
@ -1500,6 +1531,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
return CheckCalledFromGeneratedFile("_options");
}
static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
void *closure) {
return CheckCalledFromGeneratedFile("_serialized_options");
}
static PyGetSetDef Getters[] = {
{ "name", (getter)GetName, NULL, "Name"},
{ "full_name", (getter)GetFullName, NULL, "Full name"},
@ -1508,6 +1544,8 @@ static PyGetSetDef Getters[] = {
{ "containing_type", (getter)GetContainingType, NULL, "Containing type"},
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
{ "_options", (getter)NULL, (setter)SetOptions, "Options"},
{ "_serialized_options", (getter)NULL, (setter)SetSerializedOptions,
"Serialized Options"},
{ "fields", (getter)GetFields, NULL, "Fields"},
{NULL}
};

View File

@ -149,7 +149,8 @@ static PyObject* New(PyTypeObject* type,
PyDescriptorPool_NewWithDatabase(database));
}
static void Dealloc(PyDescriptorPool* self) {
static void Dealloc(PyObject* pself) {
PyDescriptorPool* self = reinterpret_cast<PyDescriptorPool*>(pself);
descriptor_pool_map.erase(self->pool);
Py_CLEAR(self->py_message_factory);
for (hash_map<const void*, PyObject*>::iterator it =
@ -163,7 +164,7 @@ static void Dealloc(PyDescriptorPool* self) {
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}
PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) {
static PyObject* FindMessageByName(PyObject* self, PyObject* arg) {
Py_ssize_t name_size;
char* name;
if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
@ -171,7 +172,8 @@ PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) {
}
const Descriptor* message_descriptor =
self->pool->FindMessageTypeByName(string(name, name_size));
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindMessageTypeByName(
string(name, name_size));
if (message_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find message %.200s", name);
@ -184,7 +186,7 @@ PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) {
PyObject* FindFileByName(PyDescriptorPool* self, PyObject* arg) {
static PyObject* FindFileByName(PyObject* self, PyObject* arg) {
Py_ssize_t name_size;
char* name;
if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
@ -192,7 +194,8 @@ PyObject* FindFileByName(PyDescriptorPool* self, PyObject* arg) {
}
const FileDescriptor* file_descriptor =
self->pool->FindFileByName(string(name, name_size));
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindFileByName(
string(name, name_size));
if (file_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find file %.200s", name);
return NULL;
@ -218,6 +221,10 @@ PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) {
return PyFieldDescriptor_FromDescriptor(field_descriptor);
}
static PyObject* FindFieldByNameMethod(PyObject* self, PyObject* arg) {
return FindFieldByName(reinterpret_cast<PyDescriptorPool*>(self), arg);
}
PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) {
Py_ssize_t name_size;
char* name;
@ -235,6 +242,10 @@ PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) {
return PyFieldDescriptor_FromDescriptor(field_descriptor);
}
static PyObject* FindExtensionByNameMethod(PyObject* self, PyObject* arg) {
return FindExtensionByName(reinterpret_cast<PyDescriptorPool*>(self), arg);
}
PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) {
Py_ssize_t name_size;
char* name;
@ -252,6 +263,10 @@ PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) {
return PyEnumDescriptor_FromDescriptor(enum_descriptor);
}
static PyObject* FindEnumTypeByNameMethod(PyObject* self, PyObject* arg) {
return FindEnumTypeByName(reinterpret_cast<PyDescriptorPool*>(self), arg);
}
PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) {
Py_ssize_t name_size;
char* name;
@ -269,7 +284,11 @@ PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) {
return PyOneofDescriptor_FromDescriptor(oneof_descriptor);
}
PyObject* FindServiceByName(PyDescriptorPool* self, PyObject* arg) {
static PyObject* FindOneofByNameMethod(PyObject* self, PyObject* arg) {
return FindOneofByName(reinterpret_cast<PyDescriptorPool*>(self), arg);
}
static PyObject* FindServiceByName(PyObject* self, PyObject* arg) {
Py_ssize_t name_size;
char* name;
if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
@ -277,7 +296,8 @@ PyObject* FindServiceByName(PyDescriptorPool* self, PyObject* arg) {
}
const ServiceDescriptor* service_descriptor =
self->pool->FindServiceByName(string(name, name_size));
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindServiceByName(
string(name, name_size));
if (service_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find service %.200s", name);
return NULL;
@ -286,7 +306,7 @@ PyObject* FindServiceByName(PyDescriptorPool* self, PyObject* arg) {
return PyServiceDescriptor_FromDescriptor(service_descriptor);
}
PyObject* FindMethodByName(PyDescriptorPool* self, PyObject* arg) {
static PyObject* FindMethodByName(PyObject* self, PyObject* arg) {
Py_ssize_t name_size;
char* name;
if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
@ -294,7 +314,8 @@ PyObject* FindMethodByName(PyDescriptorPool* self, PyObject* arg) {
}
const MethodDescriptor* method_descriptor =
self->pool->FindMethodByName(string(name, name_size));
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindMethodByName(
string(name, name_size));
if (method_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find method %.200s", name);
return NULL;
@ -303,7 +324,7 @@ PyObject* FindMethodByName(PyDescriptorPool* self, PyObject* arg) {
return PyMethodDescriptor_FromDescriptor(method_descriptor);
}
PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) {
static PyObject* FindFileContainingSymbol(PyObject* self, PyObject* arg) {
Py_ssize_t name_size;
char* name;
if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
@ -311,7 +332,8 @@ PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) {
}
const FileDescriptor* file_descriptor =
self->pool->FindFileContainingSymbol(string(name, name_size));
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindFileContainingSymbol(
string(name, name_size));
if (file_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find symbol %.200s", name);
return NULL;
@ -320,7 +342,7 @@ PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) {
return PyFileDescriptor_FromDescriptor(file_descriptor);
}
PyObject* FindExtensionByNumber(PyDescriptorPool* self, PyObject* args) {
static PyObject* FindExtensionByNumber(PyObject* self, PyObject* args) {
PyObject* message_descriptor;
int number;
if (!PyArg_ParseTuple(args, "Oi", &message_descriptor, &number)) {
@ -333,7 +355,8 @@ PyObject* FindExtensionByNumber(PyDescriptorPool* self, PyObject* args) {
}
const FieldDescriptor* extension_descriptor =
self->pool->FindExtensionByNumber(descriptor, number);
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindExtensionByNumber(
descriptor, number);
if (extension_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find extension %d", number);
return NULL;
@ -342,14 +365,15 @@ PyObject* FindExtensionByNumber(PyDescriptorPool* self, PyObject* args) {
return PyFieldDescriptor_FromDescriptor(extension_descriptor);
}
PyObject* FindAllExtensions(PyDescriptorPool* self, PyObject* arg) {
static PyObject* FindAllExtensions(PyObject* self, PyObject* arg) {
const Descriptor* descriptor = PyMessageDescriptor_AsDescriptor(arg);
if (descriptor == NULL) {
return NULL;
}
std::vector<const FieldDescriptor*> extensions;
self->pool->FindAllExtensions(descriptor, &extensions);
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindAllExtensions(
descriptor, &extensions);
ScopedPyObjectPtr result(PyList_New(extensions.size()));
if (result == NULL) {
@ -374,14 +398,15 @@ PyObject* FindAllExtensions(PyDescriptorPool* self, PyObject* arg) {
// call a function that will just be a no-op?
// TODO(amauryfa): Need to investigate further.
PyObject* AddFileDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
static PyObject* AddFileDescriptor(PyObject* self, PyObject* descriptor) {
const FileDescriptor* file_descriptor =
PyFileDescriptor_AsDescriptor(descriptor);
if (!file_descriptor) {
return NULL;
}
if (file_descriptor !=
self->pool->FindFileByName(file_descriptor->name())) {
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindFileByName(
file_descriptor->name())) {
PyErr_Format(PyExc_ValueError,
"The file descriptor %s does not belong to this pool",
file_descriptor->name().c_str());
@ -390,14 +415,15 @@ PyObject* AddFileDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
Py_RETURN_NONE;
}
PyObject* AddDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
static PyObject* AddDescriptor(PyObject* self, PyObject* descriptor) {
const Descriptor* message_descriptor =
PyMessageDescriptor_AsDescriptor(descriptor);
if (!message_descriptor) {
return NULL;
}
if (message_descriptor !=
self->pool->FindMessageTypeByName(message_descriptor->full_name())) {
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindMessageTypeByName(
message_descriptor->full_name())) {
PyErr_Format(PyExc_ValueError,
"The message descriptor %s does not belong to this pool",
message_descriptor->full_name().c_str());
@ -406,14 +432,15 @@ PyObject* AddDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
Py_RETURN_NONE;
}
PyObject* AddEnumDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
static PyObject* AddEnumDescriptor(PyObject* self, PyObject* descriptor) {
const EnumDescriptor* enum_descriptor =
PyEnumDescriptor_AsDescriptor(descriptor);
if (!enum_descriptor) {
return NULL;
}
if (enum_descriptor !=
self->pool->FindEnumTypeByName(enum_descriptor->full_name())) {
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindEnumTypeByName(
enum_descriptor->full_name())) {
PyErr_Format(PyExc_ValueError,
"The enum descriptor %s does not belong to this pool",
enum_descriptor->full_name().c_str());
@ -422,14 +449,15 @@ PyObject* AddEnumDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
Py_RETURN_NONE;
}
PyObject* AddExtensionDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
static PyObject* AddExtensionDescriptor(PyObject* self, PyObject* descriptor) {
const FieldDescriptor* extension_descriptor =
PyFieldDescriptor_AsDescriptor(descriptor);
if (!extension_descriptor) {
return NULL;
}
if (extension_descriptor !=
self->pool->FindExtensionByName(extension_descriptor->full_name())) {
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindExtensionByName(
extension_descriptor->full_name())) {
PyErr_Format(PyExc_ValueError,
"The extension descriptor %s does not belong to this pool",
extension_descriptor->full_name().c_str());
@ -438,14 +466,15 @@ PyObject* AddExtensionDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
Py_RETURN_NONE;
}
PyObject* AddServiceDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
static PyObject* AddServiceDescriptor(PyObject* self, PyObject* descriptor) {
const ServiceDescriptor* service_descriptor =
PyServiceDescriptor_AsDescriptor(descriptor);
if (!service_descriptor) {
return NULL;
}
if (service_descriptor !=
self->pool->FindServiceByName(service_descriptor->full_name())) {
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindServiceByName(
service_descriptor->full_name())) {
PyErr_Format(PyExc_ValueError,
"The service descriptor %s does not belong to this pool",
service_descriptor->full_name().c_str());
@ -481,7 +510,8 @@ class BuildFileErrorCollector : public DescriptorPool::ErrorCollector {
bool had_errors;
};
PyObject* AddSerializedFile(PyDescriptorPool* self, PyObject* serialized_pb) {
static PyObject* AddSerializedFile(PyObject* pself, PyObject* serialized_pb) {
PyDescriptorPool* self = reinterpret_cast<PyDescriptorPool*>(pself);
char* message_type;
Py_ssize_t message_len;
@ -529,7 +559,7 @@ PyObject* AddSerializedFile(PyDescriptorPool* self, PyObject* serialized_pb) {
descriptor, serialized_pb);
}
PyObject* Add(PyDescriptorPool* self, PyObject* file_descriptor_proto) {
static PyObject* Add(PyObject* self, PyObject* file_descriptor_proto) {
ScopedPyObjectPtr serialized_pb(
PyObject_CallMethod(file_descriptor_proto, "SerializeToString", NULL));
if (serialized_pb == NULL) {
@ -539,46 +569,46 @@ PyObject* Add(PyDescriptorPool* self, PyObject* file_descriptor_proto) {
}
static PyMethodDef Methods[] = {
{ "Add", (PyCFunction)Add, METH_O,
{ "Add", Add, METH_O,
"Adds the FileDescriptorProto and its types to this pool." },
{ "AddSerializedFile", (PyCFunction)AddSerializedFile, METH_O,
{ "AddSerializedFile", AddSerializedFile, METH_O,
"Adds a serialized FileDescriptorProto to this pool." },
// TODO(amauryfa): Understand why the Python implementation differs from
// this one, ask users to use another API and deprecate these functions.
{ "AddFileDescriptor", (PyCFunction)AddFileDescriptor, METH_O,
{ "AddFileDescriptor", AddFileDescriptor, METH_O,
"No-op. Add() must have been called before." },
{ "AddDescriptor", (PyCFunction)AddDescriptor, METH_O,
{ "AddDescriptor", AddDescriptor, METH_O,
"No-op. Add() must have been called before." },
{ "AddEnumDescriptor", (PyCFunction)AddEnumDescriptor, METH_O,
{ "AddEnumDescriptor", AddEnumDescriptor, METH_O,
"No-op. Add() must have been called before." },
{ "AddExtensionDescriptor", (PyCFunction)AddExtensionDescriptor, METH_O,
{ "AddExtensionDescriptor", AddExtensionDescriptor, METH_O,
"No-op. Add() must have been called before." },
{ "AddServiceDescriptor", (PyCFunction)AddServiceDescriptor, METH_O,
{ "AddServiceDescriptor", AddServiceDescriptor, METH_O,
"No-op. Add() must have been called before." },
{ "FindFileByName", (PyCFunction)FindFileByName, METH_O,
{ "FindFileByName", FindFileByName, METH_O,
"Searches for a file descriptor by its .proto name." },
{ "FindMessageTypeByName", (PyCFunction)FindMessageByName, METH_O,
{ "FindMessageTypeByName", FindMessageByName, METH_O,
"Searches for a message descriptor by full name." },
{ "FindFieldByName", (PyCFunction)FindFieldByName, METH_O,
{ "FindFieldByName", FindFieldByNameMethod, METH_O,
"Searches for a field descriptor by full name." },
{ "FindExtensionByName", (PyCFunction)FindExtensionByName, METH_O,
{ "FindExtensionByName", FindExtensionByNameMethod, METH_O,
"Searches for extension descriptor by full name." },
{ "FindEnumTypeByName", (PyCFunction)FindEnumTypeByName, METH_O,
{ "FindEnumTypeByName", FindEnumTypeByNameMethod, METH_O,
"Searches for enum type descriptor by full name." },
{ "FindOneofByName", (PyCFunction)FindOneofByName, METH_O,
{ "FindOneofByName", FindOneofByNameMethod, METH_O,
"Searches for oneof descriptor by full name." },
{ "FindServiceByName", (PyCFunction)FindServiceByName, METH_O,
{ "FindServiceByName", FindServiceByName, METH_O,
"Searches for service descriptor by full name." },
{ "FindMethodByName", (PyCFunction)FindMethodByName, METH_O,
{ "FindMethodByName", FindMethodByName, METH_O,
"Searches for method descriptor by full name." },
{ "FindFileContainingSymbol", (PyCFunction)FindFileContainingSymbol, METH_O,
{ "FindFileContainingSymbol", FindFileContainingSymbol, METH_O,
"Gets the FileDescriptor containing the specified symbol." },
{ "FindExtensionByNumber", (PyCFunction)FindExtensionByNumber, METH_VARARGS,
{ "FindExtensionByNumber", FindExtensionByNumber, METH_VARARGS,
"Gets the extension descriptor for the given number." },
{ "FindAllExtensions", (PyCFunction)FindAllExtensions, METH_O,
{ "FindAllExtensions", FindAllExtensions, METH_O,
"Gets all known extensions of the given message descriptor." },
{NULL}
};
@ -590,7 +620,7 @@ PyTypeObject PyDescriptorPool_Type = {
FULL_MODULE_NAME ".DescriptorPool", // tp_name
sizeof(PyDescriptorPool), // tp_basicsize
0, // tp_itemsize
(destructor)cdescriptor_pool::Dealloc, // tp_dealloc
cdescriptor_pool::Dealloc, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr

View File

@ -33,9 +33,6 @@
#include <google/protobuf/pyext/extension_dict.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>

View File

@ -37,9 +37,8 @@
#include <Python.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/pyext/message.h>
namespace google {
namespace protobuf {
@ -47,16 +46,8 @@ namespace protobuf {
class Message;
class FieldDescriptor;
#ifdef _SHARED_PTR_H
using std::shared_ptr;
#else
using internal::shared_ptr;
#endif
namespace python {
struct CMessage;
typedef struct ExtensionDict {
PyObject_HEAD;
@ -64,7 +55,7 @@ typedef struct ExtensionDict {
// proto tree. Every Python container class holds a
// reference to it in order to keep it alive as long as there's a
// Python object that references any part of the tree.
shared_ptr<Message> owner;
CMessage::OwnerRef owner;
// Weak reference to parent message. Used to make sure
// the parent is writable when an extension field is modified.

View File

@ -33,9 +33,6 @@
#include <google/protobuf/pyext/map_container.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
@ -76,7 +73,7 @@ class MapReflectionFriend {
struct MapIterator {
PyObject_HEAD;
google::protobuf::scoped_ptr< ::google::protobuf::MapIterator> iter;
std::unique_ptr<::google::protobuf::MapIterator> iter;
// A pointer back to the container, so we can notice changes to the version.
// We own a ref on this.
@ -94,7 +91,7 @@ struct MapIterator {
// as this iterator does. This is solely for the benefit of the MapIterator
// destructor -- we should never actually access the iterator in this state
// except to delete it.
shared_ptr<Message> owner;
CMessage::OwnerRef owner;
// The version of the map when we took the iterator to it.
//
@ -339,6 +336,24 @@ PyObject* GetEntryClass(PyObject* _self) {
return reinterpret_cast<PyObject*>(message_class);
}
PyObject* MergeFrom(PyObject* _self, PyObject* arg) {
MapContainer* self = GetMap(_self);
MapContainer* other_map = GetMap(arg);
Message* message = self->GetMutableMessage();
const Message* other_message = other_map->message;
const Reflection* reflection = message->GetReflection();
const Reflection* other_reflection = other_message->GetReflection();
int count = other_reflection->FieldSize(
*other_message, other_map->parent_field_descriptor);
for (int i = 0 ; i < count; i ++) {
reflection->AddMessage(message, self->parent_field_descriptor)->MergeFrom(
other_reflection->GetRepeatedMessage(
*other_message, other_map->parent_field_descriptor, i));
}
self->version++;
Py_RETURN_NONE;
}
PyObject* MapReflectionFriend::Contains(PyObject* _self, PyObject* key) {
MapContainer* self = GetMap(_self);
@ -535,6 +550,8 @@ static PyMethodDef ScalarMapMethods[] = {
"Gets the value for the given key if present, or otherwise a default" },
{ "GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS,
"Return the class used to build Entries of (key, value) pairs." },
{ "MergeFrom", (PyCFunction)MergeFrom, METH_O,
"Merges a map into the current map." },
/*
{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
"Makes a deep copy of the class." },
@ -810,6 +827,8 @@ static PyMethodDef MessageMapMethods[] = {
"Alias for getitem, useful to make explicit that the map is mutated." },
{ "GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS,
"Return the class used to build Entries of (key, value) pairs." },
{ "MergeFrom", (PyCFunction)MergeFrom, METH_O,
"Merges a map into the current map." },
/*
{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
"Makes a deep copy of the class." },

View File

@ -34,27 +34,18 @@
#include <Python.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
#include <google/protobuf/pyext/message.h>
namespace google {
namespace protobuf {
class Message;
#ifdef _SHARED_PTR_H
using std::shared_ptr;
#else
using internal::shared_ptr;
#endif
namespace python {
struct CMessage;
struct CMessageClass;
// This struct is used directly for ScalarMap, and is the base class of
@ -66,7 +57,7 @@ struct MapContainer {
// proto tree. Every Python MapContainer holds a
// reference to it in order to keep it alive as long as there's a
// Python object that references any part of the tree.
shared_ptr<Message> owner;
CMessage::OwnerRef owner;
// Pointer to the C++ Message that contains this container. The
// MapContainer does not own this pointer.
@ -99,9 +90,7 @@ struct MapContainer {
int Release();
// Set the owner field of self and any children of self.
void SetOwner(const shared_ptr<Message>& new_owner) {
owner = new_owner;
}
void SetOwner(const CMessage::OwnerRef& new_owner) { owner = new_owner; }
};
struct MessageMapContainer : public MapContainer {

View File

@ -35,9 +35,6 @@
#include <map>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <string>
#include <vector>
#include <structmember.h> // A Python header file.
@ -658,7 +655,7 @@ bool CheckAndGetInteger(PyObject* arg, T* value) {
// Unlike PyLong_AsLongLong, PyLong_AsUnsignedLongLong is very
// picky about the exact type.
PyObject* casted = PyNumber_Long(arg);
if (GOOGLE_PREDICT_FALSE(casted == NULL)) {
if (GOOGLE_PREDICT_FALSE(casted == nullptr)) {
// Propagate existing error.
return false;
}
@ -683,7 +680,7 @@ bool CheckAndGetInteger(PyObject* arg, T* value) {
// Valid subclasses of numbers.Integral should have a __long__() method
// so fall back to that.
PyObject* casted = PyNumber_Long(arg);
if (GOOGLE_PREDICT_FALSE(casted == NULL)) {
if (GOOGLE_PREDICT_FALSE(casted == nullptr)) {
// Propagate existing error.
return false;
}
@ -830,7 +827,8 @@ bool CheckAndSetString(
return true;
}
PyObject* ToStringObject(const FieldDescriptor* descriptor, string value) {
PyObject* ToStringObject(const FieldDescriptor* descriptor,
const string& value) {
if (descriptor->type() != FieldDescriptor::TYPE_STRING) {
return PyBytes_FromStringAndSize(value.c_str(), value.length());
}
@ -1318,6 +1316,8 @@ CMessage* NewEmptyMessage(CMessageClass* type) {
return NULL;
}
// Use "placement new" syntax to initialize the C++ object.
new (&self->owner) CMessage::OwnerRef(NULL);
self->message = NULL;
self->parent = NULL;
self->parent_field_descriptor = NULL;
@ -1414,7 +1414,7 @@ static void Dealloc(CMessage* self) {
Py_CLEAR(self->extensions);
Py_CLEAR(self->composite_fields);
self->owner.reset();
self->owner.~ThreadUnsafeSharedPtr<Message>();
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}
@ -1616,9 +1616,10 @@ PyObject* HasExtension(CMessage* self, PyObject* extension) {
// * Clear the weak references from the released container to the
// parent.
struct SetOwnerVisitor : public ChildVisitor {
class SetOwnerVisitor : public ChildVisitor {
public:
// new_owner must outlive this object.
explicit SetOwnerVisitor(const shared_ptr<Message>& new_owner)
explicit SetOwnerVisitor(const CMessage::OwnerRef& new_owner)
: new_owner_(new_owner) {}
int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) {
@ -1642,11 +1643,11 @@ struct SetOwnerVisitor : public ChildVisitor {
}
private:
const shared_ptr<Message>& new_owner_;
const CMessage::OwnerRef& new_owner_;
};
// Change the owner of this CMessage and all its children, recursively.
int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner) {
int SetOwner(CMessage* self, const CMessage::OwnerRef& new_owner) {
self->owner = new_owner;
if (ForEachCompositeField(self, SetOwnerVisitor(new_owner)) == -1)
return -1;
@ -1679,7 +1680,7 @@ int ReleaseSubMessage(CMessage* self,
const FieldDescriptor* field_descriptor,
CMessage* child_cmessage) {
// Release the Message
shared_ptr<Message> released_message(ReleaseMessage(
CMessage::OwnerRef released_message(ReleaseMessage(
self, child_cmessage->message->GetDescriptor(), field_descriptor));
child_cmessage->message = released_message.get();
child_cmessage->owner.swap(released_message);
@ -2329,7 +2330,9 @@ PyObject* InternalGetScalar(const Message* message,
break;
}
case FieldDescriptor::CPPTYPE_STRING: {
string value = reflection->GetString(*message, field_descriptor);
string scratch;
const string& value =
reflection->GetStringReference(*message, field_descriptor, &scratch);
result = ToStringObject(field_descriptor, value);
break;
}

View File

@ -37,11 +37,11 @@
#include <Python.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/pyext/thread_unsafe_shared_ptr.h>
namespace google {
namespace protobuf {
@ -71,7 +71,9 @@ typedef struct CMessage {
// proto tree. Every Python CMessage holds a reference to it in
// order to keep it alive as long as there's a Python object that
// references any part of the tree.
shared_ptr<Message> owner;
typedef ThreadUnsafeSharedPtr<Message> OwnerRef;
OwnerRef owner;
// Weak reference to a parent CMessage object. This is NULL for any top-level
// message and is set for any child message (i.e. a child submessage or a
@ -255,7 +257,7 @@ PyObject* FindInitializationErrors(CMessage* self);
// Set the owner field of self and any children of self, recursively.
// Used when self is being released and thus has a new owner (the
// released Message.)
int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner);
int SetOwner(CMessage* self, const CMessage::OwnerRef& new_owner);
int AssureWritable(CMessage* self);
@ -336,7 +338,8 @@ bool CheckAndSetString(
const Reflection* reflection,
bool append,
int index);
PyObject* ToStringObject(const FieldDescriptor* descriptor, string value);
PyObject* ToStringObject(const FieldDescriptor* descriptor,
const string& value);
// Check if the passed field descriptor belongs to the given message.
// If not, return false and set a Python exception (a KeyError)
@ -347,6 +350,15 @@ extern PyObject* PickleError_class;
bool InitProto2MessageModule(PyObject *m);
#if LANG_CXX11
// These are referenced by repeated_scalar_container, and must
// be explicitly instantiated.
extern template bool CheckAndGetInteger<int32>(PyObject*, int32*);
extern template bool CheckAndGetInteger<int64>(PyObject*, int64*);
extern template bool CheckAndGetInteger<uint32>(PyObject*, uint32*);
extern template bool CheckAndGetInteger<uint64>(PyObject*, uint64*);
#endif
} // namespace python
} // namespace protobuf

View File

@ -100,7 +100,9 @@ PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
NewMessageFactory(type, reinterpret_cast<PyDescriptorPool*>(pool)));
}
static void Dealloc(PyMessageFactory* self) {
static void Dealloc(PyObject* pself) {
PyMessageFactory* self = reinterpret_cast<PyMessageFactory*>(pself);
// TODO(amauryfa): When the MessageFactory is not created from the
// DescriptorPool this reference should be owned, not borrowed.
// Py_CLEAR(self->pool);
@ -111,7 +113,7 @@ static void Dealloc(PyMessageFactory* self) {
}
delete self->classes_by_descriptor;
delete self->message_factory;
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
Py_TYPE(self)->tp_free(pself);
}
// Add a message class to our database.
@ -231,7 +233,7 @@ PyTypeObject PyMessageFactory_Type = {
".MessageFactory", // tp_name
sizeof(PyMessageFactory), // tp_basicsize
0, // tp_itemsize
(destructor)message_factory::Dealloc, // tp_dealloc
message_factory::Dealloc, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr

View File

@ -34,9 +34,6 @@
#include <google/protobuf/pyext/repeated_composite_container.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
@ -81,7 +78,10 @@ namespace repeated_composite_container {
// ---------------------------------------------------------------------
// len()
static Py_ssize_t Length(RepeatedCompositeContainer* self) {
static Py_ssize_t Length(PyObject* pself) {
RepeatedCompositeContainer* self =
reinterpret_cast<RepeatedCompositeContainer*>(pself);
Message* message = self->message;
if (message != NULL) {
return message->GetReflection()->FieldSize(*message,
@ -102,7 +102,7 @@ static int UpdateChildMessages(RepeatedCompositeContainer* self) {
// A MergeFrom on a parent message could have caused extra messages to be
// added in the underlying protobuf so add them to our list. They can never
// be removed in such a way so there's no need to worry about that.
Py_ssize_t message_length = Length(self);
Py_ssize_t message_length = Length(reinterpret_cast<PyObject*>(self));
Py_ssize_t child_length = PyList_GET_SIZE(self->child_messages);
Message* message = self->message;
const Reflection* reflection = message->GetReflection();
@ -191,6 +191,10 @@ PyObject* Add(RepeatedCompositeContainer* self,
return AddToAttached(self, args, kwargs);
}
static PyObject* AddMethod(PyObject* self, PyObject* args, PyObject* kwargs) {
return Add(reinterpret_cast<RepeatedCompositeContainer*>(self), args, kwargs);
}
// ---------------------------------------------------------------------
// extend()
@ -226,6 +230,10 @@ PyObject* Extend(RepeatedCompositeContainer* self, PyObject* value) {
Py_RETURN_NONE;
}
static PyObject* ExtendMethod(PyObject* self, PyObject* value) {
return Extend(reinterpret_cast<RepeatedCompositeContainer*>(self), value);
}
PyObject* MergeFrom(RepeatedCompositeContainer* self, PyObject* other) {
if (UpdateChildMessages(self) < 0) {
return NULL;
@ -233,6 +241,10 @@ PyObject* MergeFrom(RepeatedCompositeContainer* self, PyObject* other) {
return Extend(self, other);
}
static PyObject* MergeFromMethod(PyObject* self, PyObject* other) {
return MergeFrom(reinterpret_cast<RepeatedCompositeContainer*>(self), other);
}
PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice) {
if (UpdateChildMessages(self) < 0) {
return NULL;
@ -242,6 +254,10 @@ PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice) {
return PyObject_GetItem(self->child_messages, slice);
}
static PyObject* SubscriptMethod(PyObject* self, PyObject* slice) {
return Subscript(reinterpret_cast<RepeatedCompositeContainer*>(self), slice);
}
int AssignSubscript(RepeatedCompositeContainer* self,
PyObject* slice,
PyObject* value) {
@ -265,7 +281,7 @@ int AssignSubscript(RepeatedCompositeContainer* self,
Py_ssize_t from;
Py_ssize_t to;
Py_ssize_t step;
Py_ssize_t length = Length(self);
Py_ssize_t length = Length(reinterpret_cast<PyObject*>(self));
Py_ssize_t slicelength;
if (PySlice_Check(slice)) {
#if PY_MAJOR_VERSION >= 3
@ -290,7 +306,16 @@ int AssignSubscript(RepeatedCompositeContainer* self,
return 0;
}
static PyObject* Remove(RepeatedCompositeContainer* self, PyObject* value) {
static int AssignSubscriptMethod(PyObject* self, PyObject* slice,
PyObject* value) {
return AssignSubscript(reinterpret_cast<RepeatedCompositeContainer*>(self),
slice, value);
}
static PyObject* Remove(PyObject* pself, PyObject* value) {
RepeatedCompositeContainer* self =
reinterpret_cast<RepeatedCompositeContainer*>(pself);
if (UpdateChildMessages(self) < 0) {
return NULL;
}
@ -305,9 +330,10 @@ static PyObject* Remove(RepeatedCompositeContainer* self, PyObject* value) {
Py_RETURN_NONE;
}
static PyObject* RichCompare(RepeatedCompositeContainer* self,
PyObject* other,
int opid) {
static PyObject* RichCompare(PyObject* pself, PyObject* other, int opid) {
RepeatedCompositeContainer* self =
reinterpret_cast<RepeatedCompositeContainer*>(pself);
if (UpdateChildMessages(self) < 0) {
return NULL;
}
@ -340,12 +366,13 @@ static PyObject* RichCompare(RepeatedCompositeContainer* self,
}
}
static PyObject* ToStr(RepeatedCompositeContainer* self) {
static PyObject* ToStr(PyObject* pself) {
ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
if (full_slice == NULL) {
return NULL;
}
ScopedPyObjectPtr list(Subscript(self, full_slice.get()));
ScopedPyObjectPtr list(Subscript(
reinterpret_cast<RepeatedCompositeContainer*>(pself), full_slice.get()));
if (list == NULL) {
return NULL;
}
@ -359,7 +386,7 @@ static void ReorderAttached(RepeatedCompositeContainer* self) {
Message* message = self->message;
const Reflection* reflection = message->GetReflection();
const FieldDescriptor* descriptor = self->parent_field_descriptor;
const Py_ssize_t length = Length(self);
const Py_ssize_t length = Length(reinterpret_cast<PyObject*>(self));
// Since Python protobuf objects are never arena-allocated, adding and
// removing message pointers to the underlying array is just updating
@ -390,9 +417,10 @@ static int SortPythonMessages(RepeatedCompositeContainer* self,
return 0;
}
static PyObject* Sort(RepeatedCompositeContainer* self,
PyObject* args,
PyObject* kwds) {
static PyObject* Sort(PyObject* pself, PyObject* args, PyObject* kwds) {
RepeatedCompositeContainer* self =
reinterpret_cast<RepeatedCompositeContainer*>(pself);
// Support the old sort_function argument for backwards
// compatibility.
if (kwds != NULL) {
@ -416,11 +444,14 @@ static PyObject* Sort(RepeatedCompositeContainer* self,
// ---------------------------------------------------------------------
static PyObject* Item(RepeatedCompositeContainer* self, Py_ssize_t index) {
static PyObject* Item(PyObject* pself, Py_ssize_t index) {
RepeatedCompositeContainer* self =
reinterpret_cast<RepeatedCompositeContainer*>(pself);
if (UpdateChildMessages(self) < 0) {
return NULL;
}
Py_ssize_t length = Length(self);
Py_ssize_t length = Length(pself);
if (index < 0) {
index = length + index;
}
@ -432,17 +463,17 @@ static PyObject* Item(RepeatedCompositeContainer* self, Py_ssize_t index) {
return item;
}
static PyObject* Pop(RepeatedCompositeContainer* self,
PyObject* args) {
static PyObject* Pop(PyObject* pself, PyObject* args) {
RepeatedCompositeContainer* self =
reinterpret_cast<RepeatedCompositeContainer*>(pself);
Py_ssize_t index = -1;
if (!PyArg_ParseTuple(args, "|n", &index)) {
return NULL;
}
PyObject* item = Item(self, index);
PyObject* item = Item(pself, index);
if (item == NULL) {
PyErr_Format(PyExc_IndexError,
"list index (%zd) out of range",
index);
PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
return NULL;
}
ScopedPyObjectPtr py_index(PyLong_FromSsize_t(index));
@ -460,7 +491,7 @@ void ReleaseLastTo(CMessage* parent,
GOOGLE_CHECK_NOTNULL(field);
GOOGLE_CHECK_NOTNULL(target);
shared_ptr<Message> released_message(
CMessage::OwnerRef released_message(
parent->message->GetReflection()->ReleaseLast(parent->message, field));
// TODO(tibell): Deal with proto1.
@ -503,7 +534,10 @@ int Release(RepeatedCompositeContainer* self) {
return 0;
}
PyObject* DeepCopy(RepeatedCompositeContainer* self, PyObject* arg) {
PyObject* DeepCopy(PyObject* pself, PyObject* arg) {
RepeatedCompositeContainer* self =
reinterpret_cast<RepeatedCompositeContainer*>(pself);
ScopedPyObjectPtr cloneObj(
PyType_GenericAlloc(&RepeatedCompositeContainer_Type, 0));
if (cloneObj == NULL) {
@ -530,7 +564,7 @@ PyObject* DeepCopy(RepeatedCompositeContainer* self, PyObject* arg) {
}
int SetOwner(RepeatedCompositeContainer* self,
const shared_ptr<Message>& new_owner) {
const CMessage::OwnerRef& new_owner) {
GOOGLE_CHECK_ATTACHED(self);
self->owner = new_owner;
@ -571,43 +605,46 @@ PyObject *NewContainer(
return reinterpret_cast<PyObject*>(self);
}
static void Dealloc(RepeatedCompositeContainer* self) {
static void Dealloc(PyObject* pself) {
RepeatedCompositeContainer* self =
reinterpret_cast<RepeatedCompositeContainer*>(pself);
Py_CLEAR(self->child_messages);
Py_CLEAR(self->child_message_class);
// TODO(tibell): Do we need to call delete on these objects to make
// sure their destructors are called?
self->owner.reset();
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
Py_TYPE(self)->tp_free(pself);
}
static PySequenceMethods SqMethods = {
(lenfunc)Length, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
(ssizeargfunc)Item /* sq_item */
Length, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
Item /* sq_item */
};
static PyMappingMethods MpMethods = {
(lenfunc)Length, /* mp_length */
(binaryfunc)Subscript, /* mp_subscript */
(objobjargproc)AssignSubscript,/* mp_ass_subscript */
Length, /* mp_length */
SubscriptMethod, /* mp_subscript */
AssignSubscriptMethod, /* mp_ass_subscript */
};
static PyMethodDef Methods[] = {
{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
{ "__deepcopy__", DeepCopy, METH_VARARGS,
"Makes a deep copy of the class." },
{ "add", (PyCFunction) Add, METH_VARARGS | METH_KEYWORDS,
{ "add", (PyCFunction)AddMethod, METH_VARARGS | METH_KEYWORDS,
"Adds an object to the repeated container." },
{ "extend", (PyCFunction) Extend, METH_O,
{ "extend", ExtendMethod, METH_O,
"Adds objects to the repeated container." },
{ "pop", (PyCFunction)Pop, METH_VARARGS,
{ "pop", Pop, METH_VARARGS,
"Removes an object from the repeated container and returns it." },
{ "remove", (PyCFunction) Remove, METH_O,
{ "remove", Remove, METH_O,
"Removes an object from the repeated container." },
{ "sort", (PyCFunction) Sort, METH_VARARGS | METH_KEYWORDS,
{ "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS,
"Sorts the repeated container." },
{ "MergeFrom", (PyCFunction) MergeFrom, METH_O,
{ "MergeFrom", MergeFromMethod, METH_O,
"Adds objects to the repeated container." },
{ NULL, NULL }
};
@ -619,12 +656,12 @@ PyTypeObject RepeatedCompositeContainer_Type = {
FULL_MODULE_NAME ".RepeatedCompositeContainer", // tp_name
sizeof(RepeatedCompositeContainer), // tp_basicsize
0, // tp_itemsize
(destructor)repeated_composite_container::Dealloc, // tp_dealloc
repeated_composite_container::Dealloc, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc)repeated_composite_container::ToStr, // tp_repr
repeated_composite_container::ToStr, // tp_repr
0, // tp_as_number
&repeated_composite_container::SqMethods, // tp_as_sequence
&repeated_composite_container::MpMethods, // tp_as_mapping
@ -638,7 +675,7 @@ PyTypeObject RepeatedCompositeContainer_Type = {
"A Repeated scalar container", // tp_doc
0, // tp_traverse
0, // tp_clear
(richcmpfunc)repeated_composite_container::RichCompare, // tp_richcompare
repeated_composite_container::RichCompare, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext

View File

@ -37,27 +37,19 @@
#include <Python.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <string>
#include <vector>
#include <google/protobuf/pyext/message.h>
namespace google {
namespace protobuf {
class FieldDescriptor;
class Message;
#ifdef _SHARED_PTR_H
using std::shared_ptr;
#else
using internal::shared_ptr;
#endif
namespace python {
struct CMessage;
struct CMessageClass;
// A RepeatedCompositeContainer can be in one of two states: attached
@ -77,7 +69,7 @@ typedef struct RepeatedCompositeContainer {
// proto tree. Every Python RepeatedCompositeContainer holds a
// reference to it in order to keep it alive as long as there's a
// Python object that references any part of the tree.
shared_ptr<Message> owner;
CMessage::OwnerRef owner;
// Weak reference to parent object. May be NULL. Used to make sure
// the parent is writable before modifying the
@ -148,11 +140,6 @@ int AssignSubscript(RepeatedCompositeContainer* self,
PyObject* slice,
PyObject* value);
// Releases the messages in the container to the given message.
//
// Returns 0 on success, -1 on failure.
int ReleaseToMessage(RepeatedCompositeContainer* self, Message* new_message);
// Releases the messages in the container to a new message.
//
// Returns 0 on success, -1 on failure.
@ -160,7 +147,7 @@ int Release(RepeatedCompositeContainer* self);
// Returns 0 on success, -1 on failure.
int SetOwner(RepeatedCompositeContainer* self,
const shared_ptr<Message>& new_owner);
const CMessage::OwnerRef& new_owner);
// Removes the last element of the repeated message field 'field' on
// the Message 'parent', and transfers the ownership of the released

View File

@ -34,9 +34,6 @@
#include <google/protobuf/pyext/repeated_scalar_container.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
@ -77,15 +74,18 @@ static int InternalAssignRepeatedField(
return 0;
}
static Py_ssize_t Len(RepeatedScalarContainer* self) {
static Py_ssize_t Len(PyObject* pself) {
RepeatedScalarContainer* self =
reinterpret_cast<RepeatedScalarContainer*>(pself);
Message* message = self->message;
return message->GetReflection()->FieldSize(*message,
self->parent_field_descriptor);
}
static int AssignItem(RepeatedScalarContainer* self,
Py_ssize_t index,
PyObject* arg) {
static int AssignItem(PyObject* pself, Py_ssize_t index, PyObject* arg) {
RepeatedScalarContainer* self =
reinterpret_cast<RepeatedScalarContainer*>(pself);
cmessage::AssureWritable(self->parent);
Message* message = self->message;
const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
@ -188,7 +188,10 @@ static int AssignItem(RepeatedScalarContainer* self,
return 0;
}
static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) {
static PyObject* Item(PyObject* pself, Py_ssize_t index) {
RepeatedScalarContainer* self =
reinterpret_cast<RepeatedScalarContainer*>(pself);
Message* message = self->message;
const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
const Reflection* reflection = message->GetReflection();
@ -256,8 +259,9 @@ static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) {
break;
}
case FieldDescriptor::CPPTYPE_STRING: {
string value = reflection->GetRepeatedString(
*message, field_descriptor, index);
string scratch;
const string& value = reflection->GetRepeatedStringReference(
*message, field_descriptor, index, &scratch);
result = ToStringObject(field_descriptor, value);
break;
}
@ -271,7 +275,10 @@ static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) {
return result;
}
static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) {
static PyObject* Subscript(PyObject* pself, PyObject* slice) {
RepeatedScalarContainer* self =
reinterpret_cast<RepeatedScalarContainer*>(pself);
Py_ssize_t from;
Py_ssize_t to;
Py_ssize_t step;
@ -286,14 +293,13 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) {
if (PyLong_Check(slice)) {
from = to = PyLong_AsLong(slice);
} else if (PySlice_Check(slice)) {
length = Len(self);
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 NULL;
}
@ -304,7 +310,7 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) {
}
if (!return_list) {
return Item(self, from);
return Item(pself, from);
}
PyObject* list = PyList_New(0);
@ -319,7 +325,7 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) {
if (index < 0 || index >= length) {
break;
}
ScopedPyObjectPtr s(Item(self, index));
ScopedPyObjectPtr s(Item(pself, index));
PyList_Append(list, s.get());
}
} else {
@ -330,7 +336,7 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) {
if (index < 0 || index >= length) {
break;
}
ScopedPyObjectPtr s(Item(self, index));
ScopedPyObjectPtr s(Item(pself, index));
PyList_Append(list, s.get());
}
}
@ -417,9 +423,14 @@ PyObject* Append(RepeatedScalarContainer* self, PyObject* item) {
Py_RETURN_NONE;
}
static int AssSubscript(RepeatedScalarContainer* self,
PyObject* slice,
PyObject* value) {
static PyObject* AppendMethod(PyObject* self, PyObject* item) {
return Append(reinterpret_cast<RepeatedScalarContainer*>(self), item);
}
static int AssSubscript(PyObject* pself, PyObject* slice, PyObject* value) {
RepeatedScalarContainer* self =
reinterpret_cast<RepeatedScalarContainer*>(pself);
Py_ssize_t from;
Py_ssize_t to;
Py_ssize_t step;
@ -435,7 +446,7 @@ static int AssSubscript(RepeatedScalarContainer* self,
#if PY_MAJOR_VERSION < 3
if (PyInt_Check(slice)) {
from = to = PyInt_AsLong(slice);
} else
} else // NOLINT
#endif
if (PyLong_Check(slice)) {
from = to = PyLong_AsLong(slice);
@ -463,14 +474,14 @@ static int AssSubscript(RepeatedScalarContainer* self,
}
if (!create_list) {
return AssignItem(self, from, value);
return AssignItem(pself, from, value);
}
ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
if (full_slice == NULL) {
return -1;
}
ScopedPyObjectPtr new_list(Subscript(self, full_slice.get()));
ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get()));
if (new_list == NULL) {
return -1;
}
@ -509,14 +520,17 @@ PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) {
Py_RETURN_NONE;
}
static PyObject* Insert(RepeatedScalarContainer* self, PyObject* args) {
static PyObject* Insert(PyObject* pself, PyObject* args) {
RepeatedScalarContainer* self =
reinterpret_cast<RepeatedScalarContainer*>(pself);
Py_ssize_t index;
PyObject* value;
if (!PyArg_ParseTuple(args, "lO", &index, &value)) {
return NULL;
}
ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
ScopedPyObjectPtr new_list(Subscript(self, full_slice.get()));
ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get()));
if (PyList_Insert(new_list.get(), index, value) < 0) {
return NULL;
}
@ -527,10 +541,13 @@ static PyObject* Insert(RepeatedScalarContainer* self, PyObject* args) {
Py_RETURN_NONE;
}
static PyObject* Remove(RepeatedScalarContainer* self, PyObject* value) {
static PyObject* Remove(PyObject* pself, PyObject* value) {
RepeatedScalarContainer* self =
reinterpret_cast<RepeatedScalarContainer*>(pself);
Py_ssize_t match_index = -1;
for (Py_ssize_t i = 0; i < Len(self); ++i) {
ScopedPyObjectPtr elem(Item(self, i));
for (Py_ssize_t i = 0; i < Len(pself); ++i) {
ScopedPyObjectPtr elem(Item(pself, i));
if (PyObject_RichCompareBool(elem.get(), value, Py_EQ)) {
match_index = i;
break;
@ -540,15 +557,20 @@ static PyObject* Remove(RepeatedScalarContainer* self, PyObject* value) {
PyErr_SetString(PyExc_ValueError, "remove(x): x not in container");
return NULL;
}
if (AssignItem(self, match_index, NULL) < 0) {
if (AssignItem(pself, match_index, NULL) < 0) {
return NULL;
}
Py_RETURN_NONE;
}
static PyObject* RichCompare(RepeatedScalarContainer* self,
PyObject* other,
int opid) {
static PyObject* ExtendMethod(PyObject* self, PyObject* value) {
return Extend(reinterpret_cast<RepeatedScalarContainer*>(self), value);
}
static PyObject* RichCompare(PyObject* pself, PyObject* other, int opid) {
RepeatedScalarContainer* self =
reinterpret_cast<RepeatedScalarContainer*>(pself);
if (opid != Py_EQ && opid != Py_NE) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
@ -565,28 +587,25 @@ static PyObject* RichCompare(RepeatedScalarContainer* self,
ScopedPyObjectPtr other_list_deleter;
if (PyObject_TypeCheck(other, &RepeatedScalarContainer_Type)) {
other_list_deleter.reset(Subscript(
reinterpret_cast<RepeatedScalarContainer*>(other), full_slice.get()));
other_list_deleter.reset(Subscript(other, full_slice.get()));
other = other_list_deleter.get();
}
ScopedPyObjectPtr list(Subscript(self, full_slice.get()));
ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
if (list == NULL) {
return NULL;
}
return PyObject_RichCompare(list.get(), other, opid);
}
PyObject* Reduce(RepeatedScalarContainer* unused_self) {
PyObject* Reduce(PyObject* unused_self, PyObject* unused_other) {
PyErr_Format(
PickleError_class,
"can't pickle repeated message fields, convert to list first");
return NULL;
}
static PyObject* Sort(RepeatedScalarContainer* self,
PyObject* args,
PyObject* kwds) {
static PyObject* Sort(PyObject* pself, PyObject* args, PyObject* kwds) {
// Support the old sort_function argument for backwards
// compatibility.
if (kwds != NULL) {
@ -605,7 +624,7 @@ static PyObject* Sort(RepeatedScalarContainer* self,
if (full_slice == NULL) {
return NULL;
}
ScopedPyObjectPtr list(Subscript(self, full_slice.get()));
ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
if (list == NULL) {
return NULL;
}
@ -617,38 +636,39 @@ static PyObject* Sort(RepeatedScalarContainer* self,
if (res == NULL) {
return NULL;
}
int ret = InternalAssignRepeatedField(self, list.get());
int ret = InternalAssignRepeatedField(
reinterpret_cast<RepeatedScalarContainer*>(pself), list.get());
if (ret < 0) {
return NULL;
}
Py_RETURN_NONE;
}
static PyObject* Pop(RepeatedScalarContainer* self,
PyObject* args) {
static PyObject* Pop(PyObject* pself, PyObject* args) {
Py_ssize_t index = -1;
if (!PyArg_ParseTuple(args, "|n", &index)) {
return NULL;
}
PyObject* item = Item(self, index);
PyObject* item = Item(pself, index);
if (item == NULL) {
PyErr_Format(PyExc_IndexError,
"list index (%zd) out of range",
index);
PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
return NULL;
}
if (AssignItem(self, index, NULL) < 0) {
if (AssignItem(pself, index, NULL) < 0) {
return NULL;
}
return item;
}
static PyObject* ToStr(RepeatedScalarContainer* self) {
static PyObject* ToStr(PyObject* pself) {
RepeatedScalarContainer* self =
reinterpret_cast<RepeatedScalarContainer*>(pself);
ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
if (full_slice == NULL) {
return NULL;
}
ScopedPyObjectPtr list(Subscript(self, full_slice.get()));
ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
if (list == NULL) {
return NULL;
}
@ -687,7 +707,8 @@ static int InitializeAndCopyToParentContainer(
if (full_slice == NULL) {
return -1;
}
ScopedPyObjectPtr values(Subscript(from, full_slice.get()));
ScopedPyObjectPtr values(
Subscript(reinterpret_cast<PyObject*>(from), full_slice.get()));
if (values == NULL) {
return -1;
}
@ -706,7 +727,10 @@ int Release(RepeatedScalarContainer* self) {
return InitializeAndCopyToParentContainer(self, self);
}
PyObject* DeepCopy(RepeatedScalarContainer* self, PyObject* arg) {
PyObject* DeepCopy(PyObject* pself, PyObject* arg) {
RepeatedScalarContainer* self =
reinterpret_cast<RepeatedScalarContainer*>(pself);
RepeatedScalarContainer* clone = reinterpret_cast<RepeatedScalarContainer*>(
PyType_GenericAlloc(&RepeatedScalarContainer_Type, 0));
if (clone == NULL) {
@ -720,45 +744,47 @@ PyObject* DeepCopy(RepeatedScalarContainer* self, PyObject* arg) {
return reinterpret_cast<PyObject*>(clone);
}
static void Dealloc(RepeatedScalarContainer* self) {
static void Dealloc(PyObject* pself) {
RepeatedScalarContainer* self =
reinterpret_cast<RepeatedScalarContainer*>(pself);
self->owner.reset();
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
Py_TYPE(self)->tp_free(pself);
}
void SetOwner(RepeatedScalarContainer* self,
const shared_ptr<Message>& new_owner) {
const CMessage::OwnerRef& new_owner) {
self->owner = new_owner;
}
static PySequenceMethods SqMethods = {
(lenfunc)Len, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
(ssizeargfunc)Item, /* sq_item */
0, /* sq_slice */
(ssizeobjargproc)AssignItem /* sq_ass_item */
Len, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
Item, /* sq_item */
0, /* sq_slice */
AssignItem /* sq_ass_item */
};
static PyMappingMethods MpMethods = {
(lenfunc)Len, /* mp_length */
(binaryfunc)Subscript, /* mp_subscript */
(objobjargproc)AssSubscript, /* mp_ass_subscript */
Len, /* mp_length */
Subscript, /* mp_subscript */
AssSubscript, /* mp_ass_subscript */
};
static PyMethodDef Methods[] = {
{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
{ "__deepcopy__", DeepCopy, METH_VARARGS,
"Makes a deep copy of the class." },
{ "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
{ "__reduce__", Reduce, METH_NOARGS,
"Outputs picklable representation of the repeated field." },
{ "append", (PyCFunction)Append, METH_O,
{ "append", AppendMethod, METH_O,
"Appends an object to the repeated container." },
{ "extend", (PyCFunction)Extend, METH_O,
{ "extend", ExtendMethod, METH_O,
"Appends objects to the repeated container." },
{ "insert", (PyCFunction)Insert, METH_VARARGS,
"Appends objects to the repeated container." },
{ "pop", (PyCFunction)Pop, METH_VARARGS,
{ "insert", Insert, METH_VARARGS,
"Inserts an object at the specified position in the container." },
{ "pop", Pop, METH_VARARGS,
"Removes an object from the repeated container and returns it." },
{ "remove", (PyCFunction)Remove, METH_O,
{ "remove", Remove, METH_O,
"Removes an object from the repeated container." },
{ "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS,
"Sorts the repeated container."},
@ -772,12 +798,12 @@ PyTypeObject RepeatedScalarContainer_Type = {
FULL_MODULE_NAME ".RepeatedScalarContainer", // tp_name
sizeof(RepeatedScalarContainer), // tp_basicsize
0, // tp_itemsize
(destructor)repeated_scalar_container::Dealloc, // tp_dealloc
repeated_scalar_container::Dealloc, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc)repeated_scalar_container::ToStr, // tp_repr
repeated_scalar_container::ToStr, // tp_repr
0, // tp_as_number
&repeated_scalar_container::SqMethods, // tp_as_sequence
&repeated_scalar_container::MpMethods, // tp_as_mapping
@ -791,7 +817,7 @@ PyTypeObject RepeatedScalarContainer_Type = {
"A Repeated scalar container", // tp_doc
0, // tp_traverse
0, // tp_clear
(richcmpfunc)repeated_scalar_container::RichCompare, // tp_richcompare
repeated_scalar_container::RichCompare, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext

View File

@ -37,27 +37,14 @@
#include <Python.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/descriptor.h>
#include <google/protobuf/pyext/message.h>
namespace google {
namespace protobuf {
class Message;
#ifdef _SHARED_PTR_H
using std::shared_ptr;
#else
using internal::shared_ptr;
#endif
namespace python {
struct CMessage;
typedef struct RepeatedScalarContainer {
PyObject_HEAD;
@ -65,7 +52,7 @@ typedef struct RepeatedScalarContainer {
// proto tree. Every Python RepeatedScalarContainer holds a
// reference to it in order to keep it alive as long as there's a
// Python object that references any part of the tree.
shared_ptr<Message> owner;
CMessage::OwnerRef owner;
// Pointer to the C++ Message that contains this container. The
// RepeatedScalarContainer does not own this pointer.
@ -112,7 +99,7 @@ PyObject* Extend(RepeatedScalarContainer* self, PyObject* value);
// Set the owner field of self and any children of self.
void SetOwner(RepeatedScalarContainer* self,
const shared_ptr<Message>& new_owner);
const CMessage::OwnerRef& new_owner);
} // namespace repeated_scalar_container
} // namespace python

View File

@ -141,9 +141,11 @@ def MessageToString(message,
as_one_line: Don't introduce newlines between fields.
pointy_brackets: If True, use angle brackets instead of curly braces for
nesting.
use_index_order: If True, print fields of a proto message using the order
defined in source code instead of the field number. By default, use the
field number order.
use_index_order: If True, fields of a proto message will be printed using
the order defined in source code instead of the field number, extensions
will be printed at the end of the message and their relative order is
determined by the extension number. By default, use the field number
order.
float_format: If set, use this to specify floating point number formatting
(per the "Format Specification Mini-Language"); otherwise, str() is used.
use_field_number: If True, print field numbers instead of names.
@ -336,11 +338,12 @@ class _Printer(object):
return
fields = message.ListFields()
if self.use_index_order:
fields.sort(key=lambda x: x[0].index)
fields.sort(
key=lambda x: x[0].number if x[0].is_extension else x[0].index)
for field, value in fields:
if _IsMapEntry(field):
for key in sorted(value):
# This is slow for maps with submessage entires because it copies the
# This is slow for maps with submessage entries because it copies the
# entire tree. Unfortunately this would take significant refactoring
# of this file to work around.
#
@ -645,6 +648,30 @@ class _Parser(object):
ParseError: In case of text parsing problems.
"""
message_descriptor = message.DESCRIPTOR
if (message_descriptor.full_name == _ANY_FULL_TYPE_NAME and
tokenizer.TryConsume('[')):
type_url_prefix, packed_type_name = self._ConsumeAnyTypeUrl(tokenizer)
tokenizer.Consume(']')
tokenizer.TryConsume(':')
if tokenizer.TryConsume('<'):
expanded_any_end_token = '>'
else:
tokenizer.Consume('{')
expanded_any_end_token = '}'
expanded_any_sub_message = _BuildMessageFromTypeName(packed_type_name,
self.descriptor_pool)
if not expanded_any_sub_message:
raise ParseError('Type %s not found in descriptor pool' %
packed_type_name)
while not tokenizer.TryConsume(expanded_any_end_token):
if tokenizer.AtEnd():
raise tokenizer.ParseErrorPreviousToken('Expected "%s".' %
(expanded_any_end_token,))
self._MergeField(tokenizer, expanded_any_sub_message)
message.Pack(expanded_any_sub_message,
type_url_prefix=type_url_prefix)
return
if tokenizer.TryConsume('['):
name = [tokenizer.ConsumeIdentifier()]
while tokenizer.TryConsume('.'):
@ -725,11 +752,12 @@ class _Parser(object):
if (field.label == descriptor.FieldDescriptor.LABEL_REPEATED and
tokenizer.TryConsume('[')):
# Short repeated format, e.g. "foo: [1, 2, 3]"
while True:
merger(tokenizer, message, field)
if tokenizer.TryConsume(']'):
break
tokenizer.Consume(',')
if not tokenizer.TryConsume(']'):
while True:
merger(tokenizer, message, field)
if tokenizer.TryConsume(']'):
break
tokenizer.Consume(',')
else:
merger(tokenizer, message, field)
@ -777,33 +805,7 @@ class _Parser(object):
tokenizer.Consume('{')
end_token = '}'
if (field.message_type.full_name == _ANY_FULL_TYPE_NAME and
tokenizer.TryConsume('[')):
type_url_prefix, packed_type_name = self._ConsumeAnyTypeUrl(tokenizer)
tokenizer.Consume(']')
tokenizer.TryConsume(':')
if tokenizer.TryConsume('<'):
expanded_any_end_token = '>'
else:
tokenizer.Consume('{')
expanded_any_end_token = '}'
expanded_any_sub_message = _BuildMessageFromTypeName(packed_type_name,
self.descriptor_pool)
if not expanded_any_sub_message:
raise ParseError('Type %s not found in descriptor pool' %
packed_type_name)
while not tokenizer.TryConsume(expanded_any_end_token):
if tokenizer.AtEnd():
raise tokenizer.ParseErrorPreviousToken('Expected "%s".' %
(expanded_any_end_token,))
self._MergeField(tokenizer, expanded_any_sub_message)
if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
any_message = getattr(message, field.name).add()
else:
any_message = getattr(message, field.name)
any_message.Pack(expanded_any_sub_message,
type_url_prefix=type_url_prefix)
elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
if field.is_extension:
sub_message = message.Extensions[field].add()
elif is_map_entry:
@ -812,8 +814,20 @@ class _Parser(object):
sub_message = getattr(message, field.name).add()
else:
if field.is_extension:
if (not self._allow_multiple_scalars and
message.HasExtension(field)):
raise tokenizer.ParseErrorPreviousToken(
'Message type "%s" should not have multiple "%s" extensions.' %
(message.DESCRIPTOR.full_name, field.full_name))
sub_message = message.Extensions[field]
else:
# Also apply _allow_multiple_scalars to message field.
# TODO(jieluo): Change to _allow_singular_overwrites.
if (not self._allow_multiple_scalars and
message.HasField(field.name)):
raise tokenizer.ParseErrorPreviousToken(
'Message type "%s" should not have multiple "%s" fields.' %
(message.DESCRIPTOR.full_name, field.name))
sub_message = getattr(message, field.name)
sub_message.SetInParent()

View File

@ -64,20 +64,6 @@ MAINTAINERCLEANFILES = \
Makefile.in
nobase_include_HEADERS = \
google/protobuf/stubs/atomic_sequence_num.h \
google/protobuf/stubs/atomicops.h \
google/protobuf/stubs/atomicops_internals_power.h \
google/protobuf/stubs/atomicops_internals_ppc_gcc.h \
google/protobuf/stubs/atomicops_internals_arm64_gcc.h \
google/protobuf/stubs/atomicops_internals_arm_gcc.h \
google/protobuf/stubs/atomicops_internals_arm_qnx.h \
google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h \
google/protobuf/stubs/atomicops_internals_generic_gcc.h \
google/protobuf/stubs/atomicops_internals_mips_gcc.h \
google/protobuf/stubs/atomicops_internals_solaris.h \
google/protobuf/stubs/atomicops_internals_tsan.h \
google/protobuf/stubs/atomicops_internals_x86_gcc.h \
google/protobuf/stubs/atomicops_internals_x86_msvc.h \
google/protobuf/stubs/callback.h \
google/protobuf/stubs/bytestream.h \
google/protobuf/stubs/casts.h \
@ -90,8 +76,6 @@ nobase_include_HEADERS = \
google/protobuf/stubs/once.h \
google/protobuf/stubs/platform_macros.h \
google/protobuf/stubs/port.h \
google/protobuf/stubs/scoped_ptr.h \
google/protobuf/stubs/shared_ptr.h \
google/protobuf/stubs/singleton.h \
google/protobuf/stubs/status.h \
google/protobuf/stubs/stl_util.h \
@ -189,8 +173,6 @@ libprotobuf_lite_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotobuf-lite.m
EXTRA_libprotobuf_lite_la_DEPENDENCIES = libprotobuf-lite.map
endif
libprotobuf_lite_la_SOURCES = \
google/protobuf/stubs/atomicops_internals_x86_gcc.cc \
google/protobuf/stubs/atomicops_internals_x86_msvc.cc \
google/protobuf/stubs/bytestream.cc \
google/protobuf/stubs/bytestream.h \
google/protobuf/stubs/common.cc \
@ -201,8 +183,6 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/stubs/io_win32.h \
google/protobuf/stubs/map_util.h \
google/protobuf/stubs/mathutil.h \
google/protobuf/stubs/once.cc \
google/protobuf/stubs/shared_ptr.h \
google/protobuf/stubs/status.cc \
google/protobuf/stubs/status.h \
google/protobuf/stubs/status_macros.h \
@ -772,7 +752,6 @@ protobuf_test_SOURCES = \
google/protobuf/stubs/common_unittest.cc \
google/protobuf/stubs/int128_unittest.cc \
google/protobuf/stubs/io_win32_unittest.cc \
google/protobuf/stubs/once_unittest.cc \
google/protobuf/stubs/statusor_test.cc \
google/protobuf/stubs/status_test.cc \
google/protobuf/stubs/stringpiece_unittest.cc \
@ -796,8 +775,8 @@ protobuf_test_SOURCES = \
google/protobuf/message_unittest.cc \
google/protobuf/no_field_presence_test.cc \
google/protobuf/preserve_unknown_enum_test.cc \
google/protobuf/proto3_arena_unittest.cc \
google/protobuf/proto3_arena_lite_unittest.cc \
google/protobuf/proto3_arena_unittest.cc \
google/protobuf/proto3_lite_unittest.cc \
google/protobuf/reflection_ops_unittest.cc \
google/protobuf/repeated_field_reflection_unittest.cc \
@ -928,9 +907,7 @@ endif
no_warning_test.cc:
echo "// Generated from Makefile.am" > no_warning_test.cc
for FILE in $(nobase_include_HEADERS); do \
if ! echo $${FILE} | grep "atomicops"; then \
echo "#include <$${FILE}>" >> no_warning_test.cc; \
fi \
echo "#include <$${FILE}>" >> no_warning_test.cc; \
done
echo "int main(int, char**) { return 0; }" >> no_warning_test.cc

View File

@ -32,6 +32,7 @@
#include <google/protobuf/generated_message_util.h>
namespace google {
namespace protobuf {
namespace internal {
@ -84,15 +85,23 @@ bool AnyMetadata::InternalIs(const Descriptor* descriptor) const {
return full_name == descriptor->full_name();
}
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
bool ParseAnyTypeUrl(const string& type_url, string* url_prefix,
string* full_type_name) {
size_t pos = type_url.find_last_of("/");
if (pos == string::npos || pos + 1 == type_url.size()) {
return false;
}
if (url_prefix) {
*url_prefix = type_url.substr(0, pos + 1);
}
*full_type_name = type_url.substr(pos + 1);
return true;
}
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
return ParseAnyTypeUrl(type_url, NULL, full_type_name);
}
bool GetAnyFieldDescriptors(const Message& message,
const FieldDescriptor** type_url_field,

View File

@ -92,8 +92,19 @@ extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/".
// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
// *full_type_name. Returns false if the type_url does not have a "/"
// in the type url separating the full type name.
//
// NOTE: this function is available publicly as:
// google::protobuf::Any() // static method on the generated message type.
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name);
// Get the proto type name and prefix from Any::type_url value. For example,
// passing "type.googleapis.com/rpc.QueryOrigin" will return
// "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in
// *full_type_name. Returns false if the type_url does not have a "/" in the
// type url separating the full type name.
bool ParseAnyTypeUrl(const string& type_url, string* url_prefix,
string* full_type_name);
// See if message is of type google.protobuf.Any, if so, return the descriptors
// for "type_url" and "value" fields.
bool GetAnyFieldDescriptors(const Message& message,

View File

@ -7,7 +7,6 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/port.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.h>
@ -19,6 +18,7 @@
#include "third_party/protobuf/version.h"
#endif
// @@protoc_insertion_point(includes)
namespace google {
namespace protobuf {
class AnyDefaultTypeInternal {
@ -29,14 +29,9 @@ class AnyDefaultTypeInternal {
} // namespace protobuf
} // namespace google
namespace protobuf_google_2fprotobuf_2fany_2eproto {
void InitDefaultsAnyImpl() {
static void InitDefaultsAny() {
GOOGLE_PROTOBUF_VERIFY_VERSION;
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
::google::protobuf::internal::InitProtobufDefaultsForceUnique();
#else
::google::protobuf::internal::InitProtobufDefaults();
#endif // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
{
void* ptr = &::google::protobuf::_Any_default_instance_;
new (ptr) ::google::protobuf::Any();
@ -45,9 +40,11 @@ void InitDefaultsAnyImpl() {
::google::protobuf::Any::InitAsDefaultInstance();
}
void InitDefaultsAny() {
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
::google::protobuf::GoogleOnceInit(&once, &InitDefaultsAnyImpl);
LIBPROTOBUF_EXPORT ::google::protobuf::internal::SCCInfo<0> scc_info_Any =
{{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsAny}, {}};
void InitDefaults() {
::google::protobuf::internal::InitSCC(&scc_info_Any.base);
}
::google::protobuf::Metadata file_level_metadata[1];
@ -71,15 +68,14 @@ static ::google::protobuf::Message const * const file_default_instances[] = {
void protobuf_AssignDescriptors() {
AddDescriptors();
::google::protobuf::MessageFactory* factory = NULL;
AssignDescriptors(
"google/protobuf/any.proto", schemas, file_default_instances, TableStruct::offsets, factory,
"google/protobuf/any.proto", schemas, file_default_instances, TableStruct::offsets,
file_level_metadata, NULL, NULL);
}
void protobuf_AssignDescriptorsOnce() {
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
static ::google::protobuf::internal::once_flag once;
::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors);
}
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
@ -105,8 +101,8 @@ void AddDescriptorsImpl() {
}
void AddDescriptors() {
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
static ::google::protobuf::internal::once_flag once;
::google::protobuf::internal::call_once(once, AddDescriptorsImpl);
}
// Force AddDescriptors() to be called at dynamic initialization time.
struct StaticDescriptorInitializer {
@ -134,6 +130,11 @@ void Any::PackFrom(const ::google::protobuf::Message& message,
bool Any::UnpackTo(::google::protobuf::Message* message) const {
return _any_metadata_.UnpackTo(message);
}
bool Any::ParseAnyTypeUrl(const string& type_url,
string* full_type_name) {
return ::google::protobuf::internal::ParseAnyTypeUrl(type_url,
full_type_name);
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int Any::kTypeUrlFieldNumber;
@ -142,16 +143,14 @@ const int Any::kValueFieldNumber;
Any::Any()
: ::google::protobuf::Message(), _internal_metadata_(NULL), _any_metadata_(&type_url_, &value_) {
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
::protobuf_google_2fprotobuf_2fany_2eproto::InitDefaultsAny();
}
::google::protobuf::internal::InitSCC(
&protobuf_google_2fprotobuf_2fany_2eproto::scc_info_Any.base);
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Any)
}
Any::Any(const Any& from)
: ::google::protobuf::Message(),
_internal_metadata_(NULL),
_cached_size_(0),
_any_metadata_(&type_url_, &value_) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@ -168,7 +167,6 @@ Any::Any(const Any& from)
void Any::SharedCtor() {
type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
_cached_size_ = 0;
}
Any::~Any() {
@ -182,9 +180,7 @@ void Any::SharedDtor() {
}
void Any::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
_cached_size_.Set(size);
}
const ::google::protobuf::Descriptor* Any::descriptor() {
::protobuf_google_2fprotobuf_2fany_2eproto::protobuf_AssignDescriptorsOnce();
@ -192,7 +188,7 @@ const ::google::protobuf::Descriptor* Any::descriptor() {
}
const Any& Any::default_instance() {
::protobuf_google_2fprotobuf_2fany_2eproto::InitDefaultsAny();
::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fany_2eproto::scc_info_Any.base);
return *internal_default_instance();
}
@ -214,7 +210,7 @@ bool Any::MergePartialFromCodedStream(
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Any)
for (;;) {
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
tag = p.first;
if (!p.second) goto handle_unusual;
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
@ -352,9 +348,7 @@ size_t Any::ByteSizeLong() const {
}
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = cached_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
SetCachedSize(cached_size);
return total_size;
}
@ -414,10 +408,11 @@ void Any::Swap(Any* other) {
}
void Any::InternalSwap(Any* other) {
using std::swap;
type_url_.Swap(&other->type_url_);
value_.Swap(&other->value_);
type_url_.Swap(&other->type_url_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
GetArenaNoVirtual());
value_.Swap(&other->value_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
GetArenaNoVirtual());
_internal_metadata_.Swap(&other->_internal_metadata_);
swap(_cached_size_, other->_cached_size_);
}
::google::protobuf::Metadata Any::GetMetadata() const {
@ -431,7 +426,7 @@ void Any::InternalSwap(Any* other) {
} // namespace google
namespace google {
namespace protobuf {
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Any* Arena::Create< ::google::protobuf::Any >(Arena* arena) {
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Any* Arena::CreateMaybeMessage< ::google::protobuf::Any >(Arena* arena) {
return Arena::CreateInternal< ::google::protobuf::Any >(arena);
}
} // namespace protobuf

View File

@ -1,8 +1,8 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: google/protobuf/any.proto
#ifndef PROTOBUF_google_2fprotobuf_2fany_2eproto_INCLUDED
#define PROTOBUF_google_2fprotobuf_2fany_2eproto_INCLUDED
#ifndef PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
#define PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
#include <string>
@ -24,6 +24,7 @@
#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_table_driven.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/inlined_string_field.h>
#include <google/protobuf/metadata.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
@ -31,6 +32,7 @@
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/any.h>
// @@protoc_insertion_point(includes)
#define PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fany_2eproto LIBPROTOBUF_EXPORT
namespace protobuf_google_2fprotobuf_2fany_2eproto {
// Internal implementation detail -- do not use these members.
@ -43,11 +45,6 @@ struct LIBPROTOBUF_EXPORT TableStruct {
static const ::google::protobuf::uint32 offsets[];
};
void LIBPROTOBUF_EXPORT AddDescriptors();
void LIBPROTOBUF_EXPORT InitDefaultsAnyImpl();
void LIBPROTOBUF_EXPORT InitDefaultsAny();
inline void LIBPROTOBUF_EXPORT InitDefaults() {
InitDefaultsAny();
}
} // namespace protobuf_google_2fprotobuf_2fany_2eproto
namespace google {
namespace protobuf {
@ -58,7 +55,7 @@ LIBPROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
} // namespace google
namespace google {
namespace protobuf {
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Any* Arena::Create< ::google::protobuf::Any>(Arena*);
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Any* Arena::CreateMaybeMessage<::google::protobuf::Any>(Arena*);
} // namespace protobuf
} // namespace google
namespace google {
@ -100,7 +97,7 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_in
return reinterpret_cast<const Any*>(
&_Any_default_instance_);
}
static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
static constexpr int kIndexInFileMessages =
0;
// implements Any -----------------------------------------------
@ -112,6 +109,8 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_in
template<typename T> bool Is() const {
return _any_metadata_.Is<T>();
}
static bool ParseAnyTypeUrl(const string& type_url,
string* full_type_name);
void Swap(Any* other);
friend void swap(Any& a, Any& b) {
@ -120,32 +119,33 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_in
// implements Message ----------------------------------------------
inline Any* New() const PROTOBUF_FINAL {
return ::google::protobuf::Arena::Create<Any>(NULL);
inline Any* New() const final {
return CreateMaybeMessage<Any>(NULL);
}
Any* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
return ::google::protobuf::Arena::Create<Any>(arena);
Any* New(::google::protobuf::Arena* arena) const final {
return CreateMaybeMessage<Any>(arena);
}
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void CopyFrom(const ::google::protobuf::Message& from) final;
void MergeFrom(const ::google::protobuf::Message& from) final;
void CopyFrom(const Any& from);
void MergeFrom(const Any& from);
void Clear() PROTOBUF_FINAL;
bool IsInitialized() const PROTOBUF_FINAL;
void Clear() final;
bool IsInitialized() const final;
size_t ByteSizeLong() const PROTOBUF_FINAL;
size_t ByteSizeLong() const final;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
::google::protobuf::io::CodedInputStream* input) final;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
::google::protobuf::io::CodedOutputStream* output) const final;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
bool deterministic, ::google::protobuf::uint8* target) const final;
int GetCachedSize() const final { return _cached_size_.Get(); }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const PROTOBUF_FINAL;
void SetCachedSize(int size) const final;
void InternalSwap(Any* other);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
@ -156,7 +156,7 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_in
}
public:
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
::google::protobuf::Metadata GetMetadata() const final;
// nested types ----------------------------------------------------
@ -196,10 +196,9 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_in
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
::google::protobuf::internal::ArenaStringPtr type_url_;
::google::protobuf::internal::ArenaStringPtr value_;
mutable int _cached_size_;
mutable ::google::protobuf::internal::CachedSize _cached_size_;
::google::protobuf::internal::AnyMetadata _any_metadata_;
friend struct ::protobuf_google_2fprotobuf_2fany_2eproto::TableStruct;
friend void ::protobuf_google_2fprotobuf_2fany_2eproto::InitDefaultsAnyImpl();
};
// ===================================================================
@ -329,4 +328,4 @@ inline void Any::set_allocated_value(::std::string* value) {
// @@protoc_insertion_point(global_scope)
#endif // PROTOBUF_google_2fprotobuf_2fany_2eproto_INCLUDED
#endif // PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto

View File

@ -7,7 +7,6 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/port.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.h>
@ -19,6 +18,17 @@
#include "third_party/protobuf/version.h"
#endif
// @@protoc_insertion_point(includes)
namespace protobuf_google_2fprotobuf_2fapi_2eproto {
extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fapi_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Mixin;
extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fapi_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_Method;
} // namespace protobuf_google_2fprotobuf_2fapi_2eproto
namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto {
extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_SourceContext;
} // namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto
namespace protobuf_google_2fprotobuf_2ftype_2eproto {
extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2ftype_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_Option;
} // namespace protobuf_google_2fprotobuf_2ftype_2eproto
namespace google {
namespace protobuf {
class ApiDefaultTypeInternal {
@ -39,18 +49,9 @@ class MixinDefaultTypeInternal {
} // namespace protobuf
} // namespace google
namespace protobuf_google_2fprotobuf_2fapi_2eproto {
void InitDefaultsApiImpl() {
static void InitDefaultsApi() {
GOOGLE_PROTOBUF_VERIFY_VERSION;
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
::google::protobuf::internal::InitProtobufDefaultsForceUnique();
#else
::google::protobuf::internal::InitProtobufDefaults();
#endif // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaultsMethod();
protobuf_google_2fprotobuf_2ftype_2eproto::InitDefaultsOption();
protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::InitDefaultsSourceContext();
protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaultsMixin();
{
void* ptr = &::google::protobuf::_Api_default_instance_;
new (ptr) ::google::protobuf::Api();
@ -59,20 +60,16 @@ void InitDefaultsApiImpl() {
::google::protobuf::Api::InitAsDefaultInstance();
}
void InitDefaultsApi() {
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
::google::protobuf::GoogleOnceInit(&once, &InitDefaultsApiImpl);
}
LIBPROTOBUF_EXPORT ::google::protobuf::internal::SCCInfo<4> scc_info_Api =
{{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 4, InitDefaultsApi}, {
&protobuf_google_2fprotobuf_2fapi_2eproto::scc_info_Method.base,
&protobuf_google_2fprotobuf_2ftype_2eproto::scc_info_Option.base,
&protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::scc_info_SourceContext.base,
&protobuf_google_2fprotobuf_2fapi_2eproto::scc_info_Mixin.base,}};
void InitDefaultsMethodImpl() {
static void InitDefaultsMethod() {
GOOGLE_PROTOBUF_VERIFY_VERSION;
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
::google::protobuf::internal::InitProtobufDefaultsForceUnique();
#else
::google::protobuf::internal::InitProtobufDefaults();
#endif // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
protobuf_google_2fprotobuf_2ftype_2eproto::InitDefaultsOption();
{
void* ptr = &::google::protobuf::_Method_default_instance_;
new (ptr) ::google::protobuf::Method();
@ -81,19 +78,13 @@ void InitDefaultsMethodImpl() {
::google::protobuf::Method::InitAsDefaultInstance();
}
void InitDefaultsMethod() {
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
::google::protobuf::GoogleOnceInit(&once, &InitDefaultsMethodImpl);
}
LIBPROTOBUF_EXPORT ::google::protobuf::internal::SCCInfo<1> scc_info_Method =
{{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsMethod}, {
&protobuf_google_2fprotobuf_2ftype_2eproto::scc_info_Option.base,}};
void InitDefaultsMixinImpl() {
static void InitDefaultsMixin() {
GOOGLE_PROTOBUF_VERIFY_VERSION;
#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
::google::protobuf::internal::InitProtobufDefaultsForceUnique();
#else
::google::protobuf::internal::InitProtobufDefaults();
#endif // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
{
void* ptr = &::google::protobuf::_Mixin_default_instance_;
new (ptr) ::google::protobuf::Mixin();
@ -102,9 +93,13 @@ void InitDefaultsMixinImpl() {
::google::protobuf::Mixin::InitAsDefaultInstance();
}
void InitDefaultsMixin() {
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
::google::protobuf::GoogleOnceInit(&once, &InitDefaultsMixinImpl);
LIBPROTOBUF_EXPORT ::google::protobuf::internal::SCCInfo<0> scc_info_Mixin =
{{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsMixin}, {}};
void InitDefaults() {
::google::protobuf::internal::InitSCC(&scc_info_Api.base);
::google::protobuf::internal::InitSCC(&scc_info_Method.base);
::google::protobuf::internal::InitSCC(&scc_info_Mixin.base);
}
::google::protobuf::Metadata file_level_metadata[3];
@ -156,15 +151,14 @@ static ::google::protobuf::Message const * const file_default_instances[] = {
void protobuf_AssignDescriptors() {
AddDescriptors();
::google::protobuf::MessageFactory* factory = NULL;
AssignDescriptors(
"google/protobuf/api.proto", schemas, file_default_instances, TableStruct::offsets, factory,
"google/protobuf/api.proto", schemas, file_default_instances, TableStruct::offsets,
file_level_metadata, NULL, NULL);
}
void protobuf_AssignDescriptorsOnce() {
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
static ::google::protobuf::internal::once_flag once;
::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors);
}
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
@ -205,8 +199,8 @@ void AddDescriptorsImpl() {
}
void AddDescriptors() {
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
static ::google::protobuf::internal::once_flag once;
::google::protobuf::internal::call_once(once, AddDescriptorsImpl);
}
// Force AddDescriptors() to be called at dynamic initialization time.
struct StaticDescriptorInitializer {
@ -245,9 +239,8 @@ const int Api::kSyntaxFieldNumber;
Api::Api()
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
::protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaultsApi();
}
::google::protobuf::internal::InitSCC(
&protobuf_google_2fprotobuf_2fapi_2eproto::scc_info_Api.base);
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Api)
}
@ -256,8 +249,7 @@ Api::Api(const Api& from)
_internal_metadata_(NULL),
methods_(from.methods_),
options_(from.options_),
mixins_(from.mixins_),
_cached_size_(0) {
mixins_(from.mixins_) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (from.name().size() > 0) {
@ -282,7 +274,6 @@ void Api::SharedCtor() {
::memset(&source_context_, 0, static_cast<size_t>(
reinterpret_cast<char*>(&syntax_) -
reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
_cached_size_ = 0;
}
Api::~Api() {
@ -297,9 +288,7 @@ void Api::SharedDtor() {
}
void Api::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
_cached_size_.Set(size);
}
const ::google::protobuf::Descriptor* Api::descriptor() {
::protobuf_google_2fprotobuf_2fapi_2eproto::protobuf_AssignDescriptorsOnce();
@ -307,7 +296,7 @@ const ::google::protobuf::Descriptor* Api::descriptor() {
}
const Api& Api::default_instance() {
::protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaultsApi();
::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fapi_2eproto::scc_info_Api.base);
return *internal_default_instance();
}
@ -337,7 +326,7 @@ bool Api::MergePartialFromCodedStream(
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Api)
for (;;) {
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
tag = p.first;
if (!p.second) goto handle_unusual;
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
@ -503,7 +492,7 @@ void Api::SerializeWithCachedSizes(
// .google.protobuf.SourceContext source_context = 5;
if (this->has_source_context()) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
5, *source_context_, output);
5, this->_internal_source_context(), output);
}
// repeated .google.protobuf.Mixin mixins = 6;
@ -577,7 +566,7 @@ void Api::SerializeWithCachedSizes(
if (this->has_source_context()) {
target = ::google::protobuf::internal::WireFormatLite::
InternalWriteMessageToArray(
5, *source_context_, deterministic, target);
5, this->_internal_source_context(), deterministic, target);
}
// repeated .google.protobuf.Mixin mixins = 6;
@ -672,9 +661,7 @@ size_t Api::ByteSizeLong() const {
}
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = cached_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
SetCachedSize(cached_size);
return total_size;
}
@ -746,12 +733,13 @@ void Api::InternalSwap(Api* other) {
CastToBase(&methods_)->InternalSwap(CastToBase(&other->methods_));
CastToBase(&options_)->InternalSwap(CastToBase(&other->options_));
CastToBase(&mixins_)->InternalSwap(CastToBase(&other->mixins_));
name_.Swap(&other->name_);
version_.Swap(&other->version_);
name_.Swap(&other->name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
GetArenaNoVirtual());
version_.Swap(&other->version_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
GetArenaNoVirtual());
swap(source_context_, other->source_context_);
swap(syntax_, other->syntax_);
_internal_metadata_.Swap(&other->_internal_metadata_);
swap(_cached_size_, other->_cached_size_);
}
::google::protobuf::Metadata Api::GetMetadata() const {
@ -779,17 +767,15 @@ const int Method::kSyntaxFieldNumber;
Method::Method()
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
::protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaultsMethod();
}
::google::protobuf::internal::InitSCC(
&protobuf_google_2fprotobuf_2fapi_2eproto::scc_info_Method.base);
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Method)
}
Method::Method(const Method& from)
: ::google::protobuf::Message(),
_internal_metadata_(NULL),
options_(from.options_),
_cached_size_(0) {
options_(from.options_) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (from.name().size() > 0) {
@ -816,7 +802,6 @@ void Method::SharedCtor() {
::memset(&request_streaming_, 0, static_cast<size_t>(
reinterpret_cast<char*>(&syntax_) -
reinterpret_cast<char*>(&request_streaming_)) + sizeof(syntax_));
_cached_size_ = 0;
}
Method::~Method() {
@ -831,9 +816,7 @@ void Method::SharedDtor() {
}
void Method::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
_cached_size_.Set(size);
}
const ::google::protobuf::Descriptor* Method::descriptor() {
::protobuf_google_2fprotobuf_2fapi_2eproto::protobuf_AssignDescriptorsOnce();
@ -841,7 +824,7 @@ const ::google::protobuf::Descriptor* Method::descriptor() {
}
const Method& Method::default_instance() {
::protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaultsMethod();
::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fapi_2eproto::scc_info_Method.base);
return *internal_default_instance();
}
@ -868,7 +851,7 @@ bool Method::MergePartialFromCodedStream(
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Method)
for (;;) {
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
tag = p.first;
if (!p.second) goto handle_unusual;
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
@ -1193,9 +1176,7 @@ size_t Method::ByteSizeLong() const {
}
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = cached_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
SetCachedSize(cached_size);
return total_size;
}
@ -1270,14 +1251,16 @@ void Method::Swap(Method* other) {
void Method::InternalSwap(Method* other) {
using std::swap;
CastToBase(&options_)->InternalSwap(CastToBase(&other->options_));
name_.Swap(&other->name_);
request_type_url_.Swap(&other->request_type_url_);
response_type_url_.Swap(&other->response_type_url_);
name_.Swap(&other->name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
GetArenaNoVirtual());
request_type_url_.Swap(&other->request_type_url_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
GetArenaNoVirtual());
response_type_url_.Swap(&other->response_type_url_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
GetArenaNoVirtual());
swap(request_streaming_, other->request_streaming_);
swap(response_streaming_, other->response_streaming_);
swap(syntax_, other->syntax_);
_internal_metadata_.Swap(&other->_internal_metadata_);
swap(_cached_size_, other->_cached_size_);
}
::google::protobuf::Metadata Method::GetMetadata() const {
@ -1297,16 +1280,14 @@ const int Mixin::kRootFieldNumber;
Mixin::Mixin()
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
::protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaultsMixin();
}
::google::protobuf::internal::InitSCC(
&protobuf_google_2fprotobuf_2fapi_2eproto::scc_info_Mixin.base);
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Mixin)
}
Mixin::Mixin(const Mixin& from)
: ::google::protobuf::Message(),
_internal_metadata_(NULL),
_cached_size_(0) {
_internal_metadata_(NULL) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (from.name().size() > 0) {
@ -1322,7 +1303,6 @@ Mixin::Mixin(const Mixin& from)
void Mixin::SharedCtor() {
name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
root_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
_cached_size_ = 0;
}
Mixin::~Mixin() {
@ -1336,9 +1316,7 @@ void Mixin::SharedDtor() {
}
void Mixin::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
_cached_size_.Set(size);
}
const ::google::protobuf::Descriptor* Mixin::descriptor() {
::protobuf_google_2fprotobuf_2fapi_2eproto::protobuf_AssignDescriptorsOnce();
@ -1346,7 +1324,7 @@ const ::google::protobuf::Descriptor* Mixin::descriptor() {
}
const Mixin& Mixin::default_instance() {
::protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaultsMixin();
::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fapi_2eproto::scc_info_Mixin.base);
return *internal_default_instance();
}
@ -1368,7 +1346,7 @@ bool Mixin::MergePartialFromCodedStream(
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Mixin)
for (;;) {
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
tag = p.first;
if (!p.second) goto handle_unusual;
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
@ -1518,9 +1496,7 @@ size_t Mixin::ByteSizeLong() const {
}
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = cached_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
SetCachedSize(cached_size);
return total_size;
}
@ -1580,10 +1556,11 @@ void Mixin::Swap(Mixin* other) {
}
void Mixin::InternalSwap(Mixin* other) {
using std::swap;
name_.Swap(&other->name_);
root_.Swap(&other->root_);
name_.Swap(&other->name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
GetArenaNoVirtual());
root_.Swap(&other->root_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
GetArenaNoVirtual());
_internal_metadata_.Swap(&other->_internal_metadata_);
swap(_cached_size_, other->_cached_size_);
}
::google::protobuf::Metadata Mixin::GetMetadata() const {
@ -1597,13 +1574,13 @@ void Mixin::InternalSwap(Mixin* other) {
} // namespace google
namespace google {
namespace protobuf {
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Api* Arena::Create< ::google::protobuf::Api >(Arena* arena) {
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Api* Arena::CreateMaybeMessage< ::google::protobuf::Api >(Arena* arena) {
return Arena::CreateInternal< ::google::protobuf::Api >(arena);
}
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Method* Arena::Create< ::google::protobuf::Method >(Arena* arena) {
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Method* Arena::CreateMaybeMessage< ::google::protobuf::Method >(Arena* arena) {
return Arena::CreateInternal< ::google::protobuf::Method >(arena);
}
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Mixin* Arena::Create< ::google::protobuf::Mixin >(Arena* arena) {
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Mixin* Arena::CreateMaybeMessage< ::google::protobuf::Mixin >(Arena* arena) {
return Arena::CreateInternal< ::google::protobuf::Mixin >(arena);
}
} // namespace protobuf

View File

@ -1,8 +1,8 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: google/protobuf/api.proto
#ifndef PROTOBUF_google_2fprotobuf_2fapi_2eproto_INCLUDED
#define PROTOBUF_google_2fprotobuf_2fapi_2eproto_INCLUDED
#ifndef PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto
#define PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto
#include <string>
@ -24,6 +24,7 @@
#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_table_driven.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/inlined_string_field.h>
#include <google/protobuf/metadata.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
@ -32,6 +33,7 @@
#include <google/protobuf/source_context.pb.h>
#include <google/protobuf/type.pb.h>
// @@protoc_insertion_point(includes)
#define PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fapi_2eproto LIBPROTOBUF_EXPORT
namespace protobuf_google_2fprotobuf_2fapi_2eproto {
// Internal implementation detail -- do not use these members.
@ -44,17 +46,6 @@ struct LIBPROTOBUF_EXPORT TableStruct {
static const ::google::protobuf::uint32 offsets[];
};
void LIBPROTOBUF_EXPORT AddDescriptors();
void LIBPROTOBUF_EXPORT InitDefaultsApiImpl();
void LIBPROTOBUF_EXPORT InitDefaultsApi();
void LIBPROTOBUF_EXPORT InitDefaultsMethodImpl();
void LIBPROTOBUF_EXPORT InitDefaultsMethod();
void LIBPROTOBUF_EXPORT InitDefaultsMixinImpl();
void LIBPROTOBUF_EXPORT InitDefaultsMixin();
inline void LIBPROTOBUF_EXPORT InitDefaults() {
InitDefaultsApi();
InitDefaultsMethod();
InitDefaultsMixin();
}
} // namespace protobuf_google_2fprotobuf_2fapi_2eproto
namespace google {
namespace protobuf {
@ -71,9 +62,9 @@ LIBPROTOBUF_EXPORT extern MixinDefaultTypeInternal _Mixin_default_instance_;
} // namespace google
namespace google {
namespace protobuf {
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Api* Arena::Create< ::google::protobuf::Api>(Arena*);
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Method* Arena::Create< ::google::protobuf::Method>(Arena*);
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Mixin* Arena::Create< ::google::protobuf::Mixin>(Arena*);
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Api* Arena::CreateMaybeMessage<::google::protobuf::Api>(Arena*);
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Method* Arena::CreateMaybeMessage<::google::protobuf::Method>(Arena*);
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Mixin* Arena::CreateMaybeMessage<::google::protobuf::Mixin>(Arena*);
} // namespace protobuf
} // namespace google
namespace google {
@ -115,7 +106,7 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
return reinterpret_cast<const Api*>(
&_Api_default_instance_);
}
static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
static constexpr int kIndexInFileMessages =
0;
void Swap(Api* other);
@ -125,32 +116,33 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
// implements Message ----------------------------------------------
inline Api* New() const PROTOBUF_FINAL {
return ::google::protobuf::Arena::Create<Api>(NULL);
inline Api* New() const final {
return CreateMaybeMessage<Api>(NULL);
}
Api* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
return ::google::protobuf::Arena::Create<Api>(arena);
Api* New(::google::protobuf::Arena* arena) const final {
return CreateMaybeMessage<Api>(arena);
}
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void CopyFrom(const ::google::protobuf::Message& from) final;
void MergeFrom(const ::google::protobuf::Message& from) final;
void CopyFrom(const Api& from);
void MergeFrom(const Api& from);
void Clear() PROTOBUF_FINAL;
bool IsInitialized() const PROTOBUF_FINAL;
void Clear() final;
bool IsInitialized() const final;
size_t ByteSizeLong() const PROTOBUF_FINAL;
size_t ByteSizeLong() const final;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
::google::protobuf::io::CodedInputStream* input) final;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
::google::protobuf::io::CodedOutputStream* output) const final;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
bool deterministic, ::google::protobuf::uint8* target) const final;
int GetCachedSize() const final { return _cached_size_.Get(); }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const PROTOBUF_FINAL;
void SetCachedSize(int size) const final;
void InternalSwap(Api* other);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
@ -161,7 +153,7 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
}
public:
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
::google::protobuf::Metadata GetMetadata() const final;
// nested types ----------------------------------------------------
@ -235,6 +227,9 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
bool has_source_context() const;
void clear_source_context();
static const int kSourceContextFieldNumber = 5;
private:
const ::google::protobuf::SourceContext& _internal_source_context() const;
public:
const ::google::protobuf::SourceContext& source_context() const;
::google::protobuf::SourceContext* release_source_context();
::google::protobuf::SourceContext* mutable_source_context();
@ -257,9 +252,8 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
::google::protobuf::internal::ArenaStringPtr version_;
::google::protobuf::SourceContext* source_context_;
int syntax_;
mutable int _cached_size_;
mutable ::google::protobuf::internal::CachedSize _cached_size_;
friend struct ::protobuf_google_2fprotobuf_2fapi_2eproto::TableStruct;
friend void ::protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaultsApiImpl();
};
// -------------------------------------------------------------------
@ -297,7 +291,7 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc
return reinterpret_cast<const Method*>(
&_Method_default_instance_);
}
static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
static constexpr int kIndexInFileMessages =
1;
void Swap(Method* other);
@ -307,32 +301,33 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc
// implements Message ----------------------------------------------
inline Method* New() const PROTOBUF_FINAL {
return ::google::protobuf::Arena::Create<Method>(NULL);
inline Method* New() const final {
return CreateMaybeMessage<Method>(NULL);
}
Method* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
return ::google::protobuf::Arena::Create<Method>(arena);
Method* New(::google::protobuf::Arena* arena) const final {
return CreateMaybeMessage<Method>(arena);
}
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void CopyFrom(const ::google::protobuf::Message& from) final;
void MergeFrom(const ::google::protobuf::Message& from) final;
void CopyFrom(const Method& from);
void MergeFrom(const Method& from);
void Clear() PROTOBUF_FINAL;
bool IsInitialized() const PROTOBUF_FINAL;
void Clear() final;
bool IsInitialized() const final;
size_t ByteSizeLong() const PROTOBUF_FINAL;
size_t ByteSizeLong() const final;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
::google::protobuf::io::CodedInputStream* input) final;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
::google::protobuf::io::CodedOutputStream* output) const final;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
bool deterministic, ::google::protobuf::uint8* target) const final;
int GetCachedSize() const final { return _cached_size_.Get(); }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const PROTOBUF_FINAL;
void SetCachedSize(int size) const final;
void InternalSwap(Method* other);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
@ -343,7 +338,7 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc
}
public:
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
::google::protobuf::Metadata GetMetadata() const final;
// nested types ----------------------------------------------------
@ -432,9 +427,8 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc
bool request_streaming_;
bool response_streaming_;
int syntax_;
mutable int _cached_size_;
mutable ::google::protobuf::internal::CachedSize _cached_size_;
friend struct ::protobuf_google_2fprotobuf_2fapi_2eproto::TableStruct;
friend void ::protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaultsMethodImpl();
};
// -------------------------------------------------------------------
@ -472,7 +466,7 @@ class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message /* @@protoc_
return reinterpret_cast<const Mixin*>(
&_Mixin_default_instance_);
}
static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
static constexpr int kIndexInFileMessages =
2;
void Swap(Mixin* other);
@ -482,32 +476,33 @@ class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message /* @@protoc_
// implements Message ----------------------------------------------
inline Mixin* New() const PROTOBUF_FINAL {
return ::google::protobuf::Arena::Create<Mixin>(NULL);
inline Mixin* New() const final {
return CreateMaybeMessage<Mixin>(NULL);
}
Mixin* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
return ::google::protobuf::Arena::Create<Mixin>(arena);
Mixin* New(::google::protobuf::Arena* arena) const final {
return CreateMaybeMessage<Mixin>(arena);
}
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void CopyFrom(const ::google::protobuf::Message& from) final;
void MergeFrom(const ::google::protobuf::Message& from) final;
void CopyFrom(const Mixin& from);
void MergeFrom(const Mixin& from);
void Clear() PROTOBUF_FINAL;
bool IsInitialized() const PROTOBUF_FINAL;
void Clear() final;
bool IsInitialized() const final;
size_t ByteSizeLong() const PROTOBUF_FINAL;
size_t ByteSizeLong() const final;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
::google::protobuf::io::CodedInputStream* input) final;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
::google::protobuf::io::CodedOutputStream* output) const final;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
bool deterministic, ::google::protobuf::uint8* target) const final;
int GetCachedSize() const final { return _cached_size_.Get(); }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const PROTOBUF_FINAL;
void SetCachedSize(int size) const final;
void InternalSwap(Mixin* other);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
@ -518,7 +513,7 @@ class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message /* @@protoc_
}
public:
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
::google::protobuf::Metadata GetMetadata() const final;
// nested types ----------------------------------------------------
@ -558,9 +553,8 @@ class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message /* @@protoc_
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
::google::protobuf::internal::ArenaStringPtr name_;
::google::protobuf::internal::ArenaStringPtr root_;
mutable int _cached_size_;
mutable ::google::protobuf::internal::CachedSize _cached_size_;
friend struct ::protobuf_google_2fprotobuf_2fapi_2eproto::TableStruct;
friend void ::protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaultsMixinImpl();
};
// ===================================================================
@ -740,6 +734,9 @@ inline void Api::set_allocated_version(::std::string* version) {
inline bool Api::has_source_context() const {
return this != internal_default_instance() && source_context_ != NULL;
}
inline const ::google::protobuf::SourceContext& Api::_internal_source_context() const {
return *source_context_;
}
inline const ::google::protobuf::SourceContext& Api::source_context() const {
const ::google::protobuf::SourceContext* p = source_context_;
// @@protoc_insertion_point(field_get:google.protobuf.Api.source_context)
@ -756,8 +753,8 @@ inline ::google::protobuf::SourceContext* Api::release_source_context() {
inline ::google::protobuf::SourceContext* Api::mutable_source_context() {
if (source_context_ == NULL) {
source_context_ = ::google::protobuf::Arena::Create< ::google::protobuf::SourceContext >(
GetArenaNoVirtual());
auto* p = CreateMaybeMessage<::google::protobuf::SourceContext>(GetArenaNoVirtual());
source_context_ = p;
}
// @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context)
return source_context_;
@ -1182,4 +1179,4 @@ inline void Mixin::set_allocated_root(::std::string* root) {
// @@protoc_insertion_point(global_scope)
#endif // PROTOBUF_google_2fprotobuf_2fapi_2eproto_INCLUDED
#endif // PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto

View File

@ -48,7 +48,7 @@ namespace protobuf {
namespace internal {
google::protobuf::internal::SequenceNumber ArenaImpl::lifecycle_id_generator_;
std::atomic<int64> ArenaImpl::lifecycle_id_generator_;
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
@ -65,9 +65,10 @@ GOOGLE_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {-1, NULL}
#endif
void ArenaImpl::Init() {
lifecycle_id_ = lifecycle_id_generator_.GetNext();
google::protobuf::internal::NoBarrier_Store(&hint_, 0);
google::protobuf::internal::NoBarrier_Store(&threads_, 0);
lifecycle_id_ =
lifecycle_id_generator_.fetch_add(1, std::memory_order_relaxed);
hint_.store(nullptr, std::memory_order_relaxed);
threads_.store(nullptr, std::memory_order_relaxed);
if (initial_block_) {
// Thread which calls Init() owns the first block. This allows the
@ -77,13 +78,12 @@ void ArenaImpl::Init() {
SerialArena* serial =
SerialArena::New(initial_block_, &thread_cache(), this);
serial->set_next(NULL);
google::protobuf::internal::NoBarrier_Store(&threads_,
reinterpret_cast<google::protobuf::internal::AtomicWord>(serial));
google::protobuf::internal::NoBarrier_Store(&space_allocated_,
options_.initial_block_size);
threads_.store(serial, std::memory_order_relaxed);
space_allocated_.store(options_.initial_block_size,
std::memory_order_relaxed);
CacheSerialArena(serial);
} else {
google::protobuf::internal::NoBarrier_Store(&space_allocated_, 0);
space_allocated_.store(0, std::memory_order_relaxed);
}
}
@ -118,7 +118,7 @@ ArenaImpl::Block* ArenaImpl::NewBlock(Block* last_block, size_t min_bytes) {
void* mem = options_.block_alloc(size);
Block* b = new (mem) Block(size, last_block);
google::protobuf::internal::NoBarrier_AtomicIncrement(&space_allocated_, size);
space_allocated_.fetch_add(size, std::memory_order_relaxed);
return b;
}
@ -142,6 +142,7 @@ void ArenaImpl::SerialArena::AddCleanupFallback(void* elem,
AddCleanup(elem, cleanup);
}
GOOGLE_PROTOBUF_ATTRIBUTE_FUNC_ALIGN(32)
void* ArenaImpl::AllocateAligned(size_t n) {
SerialArena* arena;
if (GOOGLE_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
@ -199,8 +200,7 @@ bool ArenaImpl::GetSerialArenaFast(ArenaImpl::SerialArena** arena) {
// Check whether we own the last accessed SerialArena on this arena. This
// fast path optimizes the case where a single thread uses multiple arenas.
SerialArena* serial =
reinterpret_cast<SerialArena*>(google::protobuf::internal::Acquire_Load(&hint_));
SerialArena* serial = hint_.load(std::memory_order_acquire);
if (GOOGLE_PREDICT_TRUE(serial != NULL && serial->owner() == tc)) {
*arena = serial;
return true;
@ -235,12 +235,11 @@ void* ArenaImpl::SerialArena::AllocateAlignedFallback(size_t n) {
}
uint64 ArenaImpl::SpaceAllocated() const {
return google::protobuf::internal::NoBarrier_Load(&space_allocated_);
return space_allocated_.load(std::memory_order_relaxed);
}
uint64 ArenaImpl::SpaceUsed() const {
SerialArena* serial =
reinterpret_cast<SerialArena*>(google::protobuf::internal::Acquire_Load(&threads_));
SerialArena* serial = threads_.load(std::memory_order_acquire);
uint64 space_used = 0;
for ( ; serial; serial = serial->next()) {
space_used += serial->SpaceUsed();
@ -264,8 +263,7 @@ uint64 ArenaImpl::FreeBlocks() {
uint64 space_allocated = 0;
// By omitting an Acquire barrier we ensure that any user code that doesn't
// properly synchronize Reset() or the destructor will throw a TSAN warning.
SerialArena* serial =
reinterpret_cast<SerialArena*>(google::protobuf::internal::NoBarrier_Load(&threads_));
SerialArena* serial = threads_.load(std::memory_order_relaxed);
while (serial) {
// This is inside a block we are freeing, so we need to read it now.
@ -311,8 +309,7 @@ uint64 ArenaImpl::SerialArena::Free(ArenaImpl::SerialArena* serial,
void ArenaImpl::CleanupList() {
// By omitting an Acquire barrier we ensure that any user code that doesn't
// properly synchronize Reset() or the destructor will throw a TSAN warning.
SerialArena* serial =
reinterpret_cast<SerialArena*>(google::protobuf::internal::NoBarrier_Load(&threads_));
SerialArena* serial = threads_.load(std::memory_order_relaxed);
for ( ; serial; serial = serial->next()) {
serial->CleanupList();
@ -368,8 +365,7 @@ ArenaImpl::SerialArena* ArenaImpl::SerialArena::New(Block* b, void* owner,
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
ArenaImpl::SerialArena* ArenaImpl::GetSerialArenaFallback(void* me) {
// Look for this SerialArena in our linked list.
SerialArena* serial =
reinterpret_cast<SerialArena*>(google::protobuf::internal::Acquire_Load(&threads_));
SerialArena* serial = threads_.load(std::memory_order_acquire);
for ( ; serial; serial = serial->next()) {
if (serial->owner() == me) {
break;
@ -382,12 +378,11 @@ ArenaImpl::SerialArena* ArenaImpl::GetSerialArenaFallback(void* me) {
Block* b = NewBlock(NULL, kSerialArenaSize);
serial = SerialArena::New(b, me, this);
google::protobuf::internal::AtomicWord head;
SerialArena* head = threads_.load(std::memory_order_relaxed);
do {
head = google::protobuf::internal::NoBarrier_Load(&threads_);
serial->set_next(reinterpret_cast<SerialArena*>(head));
} while (google::protobuf::internal::Release_CompareAndSwap(
&threads_, head, reinterpret_cast<google::protobuf::internal::AtomicWord>(serial)) != head);
serial->set_next(head);
} while (!threads_.compare_exchange_weak(
head, serial, std::memory_order_release, std::memory_order_relaxed));
}
CacheSerialArena(serial);

View File

@ -37,9 +37,6 @@
#ifdef max
#undef max // Visual Studio defines this macro
#endif
#if LANG_CXX11
#include <google/protobuf/stubs/type_traits.h>
#endif
#if defined(_MSC_VER) && !_HAS_EXCEPTIONS
// Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
#include <exception>
@ -53,10 +50,13 @@ using type_info = ::type_info;
#include <google/protobuf/arena_impl.h>
#include <google/protobuf/stubs/port.h>
#include <type_traits>
namespace google {
namespace protobuf {
struct ArenaOptions;
struct ArenaOptions; // defined below
} // namespace protobuf
namespace quality_webanswers {
@ -66,27 +66,32 @@ void TempPrivateWorkAround(::google::protobuf::ArenaOptions* arena_options);
} // namespace quality_webanswers
namespace protobuf {
class Arena; // defined below
class Message; // defined in message.h
class MessageLite;
namespace arena_metrics {
void EnableArenaMetrics(::google::protobuf::ArenaOptions* options);
} // namespace arena_metrics
class Arena; // defined below
class Message; // message.h
namespace internal {
struct ArenaStringPtr; // arenastring.h
class LazyField; // lazy_field.h
template<typename Type>
class GenericTypeHandler; // repeated_field.h
struct ArenaStringPtr; // defined in arenastring.h
class LazyField; // defined in lazy_field.h
template <typename Type>
class GenericTypeHandler; // defined in repeated_field.h
// Templated cleanup methods.
template<typename T> void arena_destruct_object(void* object) {
template <typename T>
void arena_destruct_object(void* object) {
reinterpret_cast<T*>(object)->~T();
}
template<typename T> void arena_delete_object(void* object) {
template <typename T>
void arena_delete_object(void* object) {
delete reinterpret_cast<T*>(object);
}
inline void arena_free(void* object, size_t size) {
@ -165,12 +170,12 @@ struct ArenaOptions {
// intentionally want to avoid monitoring an allocation. (i.e. internal
// allocations for managing the arena)
void (*on_arena_allocation)(const std::type_info* allocated_type,
uint64 alloc_size, void* cookie);
uint64 alloc_size, void* cookie);
// Constants define default starting block size and max block size for
// arena allocator behavior -- see descriptions above.
static const size_t kDefaultStartBlockSize = 256;
static const size_t kDefaultMaxBlockSize = 8192;
static const size_t kDefaultMaxBlockSize = 8192;
friend void ::google::protobuf::arena_metrics::EnableArenaMetrics(ArenaOptions*);
friend void quality_webanswers::TempPrivateWorkAround(ArenaOptions*);
@ -285,70 +290,16 @@ class LIBPROTOBUF_EXPORT Arena {
//
// This function also accepts any type T that satisfies the arena message
// allocation protocol, documented above.
#if LANG_CXX11
template <typename T, typename... Args>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMessage(
::google::protobuf::Arena* arena, Args&&... args) {
Arena* arena, Args&&... args) {
static_assert(
InternalHelper<T>::is_arena_constructable::value,
"CreateMessage can only construct types that are ArenaConstructable");
if (arena == NULL) {
return new T(NULL, std::forward<Args>(args)...);
} else {
return arena->CreateMessageInternal<T>(std::forward<Args>(args)...);
}
}
#endif
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* CreateMessage(::google::protobuf::Arena* arena) {
#if LANG_CXX11
static_assert(
InternalHelper<T>::is_arena_constructable::value,
"CreateMessage can only construct types that are ArenaConstructable");
#endif
if (arena == NULL) {
return new T;
} else {
return arena->CreateMessageInternal<T>();
}
}
// One-argument form of CreateMessage. This is useful for constructing objects
// that implement the arena message construction protocol described above but
// take additional constructor arguments.
template <typename T, typename Arg> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* CreateMessage(::google::protobuf::Arena* arena, const Arg& arg) {
#if LANG_CXX11
static_assert(
InternalHelper<T>::is_arena_constructable::value,
"CreateMessage can only construct types that are ArenaConstructable");
#endif
if (arena == NULL) {
return new T(NULL, arg);
} else {
return arena->CreateMessageInternal<T>(arg);
}
}
// Two-argument form of CreateMessage. This is useful for constructing objects
// that implement the arena message construction protocol described above but
// take additional constructor arguments.
template <typename T, typename Arg1, typename Arg2>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* CreateMessage(::google::protobuf::Arena* arena,
const Arg1& arg1,
const Arg2& arg2) {
#if LANG_CXX11
static_assert(
InternalHelper<T>::is_arena_constructable::value,
"CreateMessage can only construct types that are ArenaConstructable");
#endif
if (arena == NULL) {
return new T(NULL, arg1, arg2);
} else {
return arena->CreateMessageInternal<T>(arg1, arg2);
}
// We must delegate to CreateMaybeMessage() and NOT CreateMessageInternal()
// because protobuf generated classes specialize CreateMaybeMessage() and we
// need to use that specialization for code size reasons.
return Arena::CreateMaybeMessage<T>(arena, std::forward<Args>(args)...);
}
// API to create any objects on the arena. Note that only the object will
@ -366,153 +317,11 @@ class LIBPROTOBUF_EXPORT Arena {
// (unless the destructor is trivial). Hence, from T's point of view, it is as
// if the object were allocated on the heap (except that the underlying memory
// is obtained from the arena).
#if LANG_CXX11
template <typename T, typename... Args>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* Create(::google::protobuf::Arena* arena, Args&&... args) {
if (arena == NULL) {
return new T(std::forward<Args>(args)...);
} else {
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
std::forward<Args>(args)...);
}
}
#endif
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* Create(::google::protobuf::Arena* arena) {
if (arena == NULL) {
return new T();
} else {
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value);
}
}
// Version of the above with one constructor argument for the created object.
template <typename T, typename Arg> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* Create(::google::protobuf::Arena* arena, const Arg& arg) {
if (arena == NULL) {
return new T(arg);
} else {
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
arg);
}
}
// Version of the above with two constructor arguments for the created object.
template <typename T, typename Arg1, typename Arg2>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* Create(::google::protobuf::Arena* arena, const Arg1& arg1, const Arg2& arg2) {
if (arena == NULL) {
return new T(arg1, arg2);
} else {
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
arg1, arg2);
}
}
// Version of the above with three constructor arguments for the created
// object.
template <typename T, typename Arg1, typename Arg2, typename Arg3>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* Create(::google::protobuf::Arena* arena,
const Arg1& arg1,
const Arg2& arg2,
const Arg3& arg3) {
if (arena == NULL) {
return new T(arg1, arg2, arg3);
} else {
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
arg1, arg2, arg3);
}
}
// Version of the above with four constructor arguments for the created
// object.
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* Create(::google::protobuf::Arena* arena,
const Arg1& arg1, const Arg2& arg2,
const Arg3& arg3, const Arg4& arg4) {
if (arena == NULL) {
return new T(arg1, arg2, arg3, arg4);
} else {
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
arg1, arg2, arg3, arg4);
}
}
// Version of the above with five constructor arguments for the created
// object.
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* Create(::google::protobuf::Arena* arena,
const Arg1& arg1, const Arg2& arg2,
const Arg3& arg3, const Arg4& arg4,
const Arg5& arg5) {
if (arena == NULL) {
return new T(arg1, arg2, arg3, arg4, arg5);
} else {
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
arg1, arg2, arg3, arg4, arg5);
}
}
// Version of the above with six constructor arguments for the created
// object.
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5, typename Arg6>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* Create(::google::protobuf::Arena* arena,
const Arg1& arg1, const Arg2& arg2,
const Arg3& arg3, const Arg4& arg4,
const Arg5& arg5, const Arg6& arg6) {
if (arena == NULL) {
return new T(arg1, arg2, arg3, arg4, arg5, arg6);
} else {
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
arg1, arg2, arg3, arg4, arg5, arg6);
}
}
// Version of the above with seven constructor arguments for the created
// object.
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5, typename Arg6, typename Arg7>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* Create(::google::protobuf::Arena* arena,
const Arg1& arg1, const Arg2& arg2,
const Arg3& arg3, const Arg4& arg4,
const Arg5& arg5, const Arg6& arg6,
const Arg7& arg7) {
if (arena == NULL) {
return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
} else {
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
}
// Version of the above with eight constructor arguments for the created
// object.
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5, typename Arg6, typename Arg7,
typename Arg8>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* Create(::google::protobuf::Arena* arena,
const Arg1& arg1, const Arg2& arg2,
const Arg3& arg3, const Arg4& arg4,
const Arg5& arg5, const Arg6& arg6,
const Arg7& arg7, const Arg8& arg8) {
if (arena == NULL) {
return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
} else {
return arena->CreateInternal<T>(
google::protobuf::internal::has_trivial_destructor<T>::value,
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* Create(Arena* arena,
Args&&... args) {
return CreateNoMessage<T>(arena, is_arena_constructable<T>(),
std::forward<Args>(args)...);
}
// Create an array of object type T on the arena *without* invoking the
@ -521,10 +330,14 @@ class LIBPROTOBUF_EXPORT Arena {
// To ensure safe uses, this function checks at compile time
// (when compiled as C++11) that T is trivially default-constructible and
// trivially destructible.
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) {
GOOGLE_CHECK_LE(num_elements,
std::numeric_limits<size_t>::max() / sizeof(T))
template <typename T>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateArray(
Arena* arena, size_t num_elements) {
static_assert(std::is_trivially_default_constructible<T>::value,
"CreateArray requires a trivially constructible type");
static_assert(std::is_trivially_destructible<T>::value,
"CreateArray requires a trivially destructible type");
GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
<< "Requested size is too large to fit into size_t.";
if (arena == NULL) {
return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
@ -566,9 +379,9 @@ class LIBPROTOBUF_EXPORT Arena {
// Adds |object| to a list of heap-allocated objects to be freed with |delete|
// when the arena is destroyed or reset.
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
void Own(T* object) {
OwnInternal(object, google::protobuf::internal::is_convertible<T*, ::google::protobuf::Message*>());
template <typename T>
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void Own(T* object) {
OwnInternal(object, std::is_convertible<T*, Message*>());
}
// Adds |object| to a list of objects whose destructors will be manually
@ -576,8 +389,8 @@ class LIBPROTOBUF_EXPORT Arena {
// that it does not free the underlying memory with |delete|; hence, it is
// normally only used for objects that are placement-newed into
// arena-allocated memory.
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
void OwnDestructor(T* object) {
template <typename T>
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void OwnDestructor(T* object) {
if (object != NULL) {
impl_.AddCleanup(object, &internal::arena_destruct_object<T>);
}
@ -596,8 +409,9 @@ class LIBPROTOBUF_EXPORT Arena {
// message, or NULL otherwise. This differs from value->GetArena() in that the
// latter is a virtual call, while this method is a templated call that
// resolves at compile-time.
template<typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static ::google::protobuf::Arena* GetArena(const T* value) {
template <typename T>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Arena* GetArena(
const T* value) {
return GetArenaInternal(value, is_arena_constructable<T>());
}
@ -608,80 +422,89 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename U>
static double DestructorSkippable(...);
typedef google::protobuf::internal::integral_constant<
typedef std::integral_constant<
bool, sizeof(DestructorSkippable<T>(static_cast<const T*>(0))) ==
sizeof(char) ||
google::protobuf::internal::has_trivial_destructor<T>::value>
std::is_trivially_destructible<T>::value>
is_destructor_skippable;
template<typename U>
template <typename U>
static char ArenaConstructable(
const typename U::InternalArenaConstructable_*);
template<typename U>
template <typename U>
static double ArenaConstructable(...);
typedef google::protobuf::internal::integral_constant<bool, sizeof(ArenaConstructable<T>(
static_cast<const T*>(0))) ==
sizeof(char)>
typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>(
static_cast<const T*>(0))) ==
sizeof(char)>
is_arena_constructable;
#if LANG_CXX11
template <typename... Args>
static T* Construct(void* ptr, Args&&... args) {
return new (ptr) T(std::forward<Args>(args)...);
}
#else
template <typename Arg1>
static T* Construct(void* ptr, const Arg1& arg1) {
return new (ptr) T(arg1);
}
template <typename Arg1, typename Arg2>
static T* Construct(void* ptr, const Arg1& arg1, const Arg2& arg2) {
return new (ptr) T(arg1, arg2);
}
template <typename Arg1, typename Arg2, typename Arg3>
static T* Construct(void* ptr, const Arg1& arg1,
const Arg2& arg2, const Arg3& arg3) {
return new (ptr) T(arg1, arg2, arg3);
}
#endif // LANG_CXX11
static Arena* GetArena(const T* p) { return p->GetArenaNoVirtual(); }
friend class Arena;
};
// Helper typetrait that indicates support for arenas in a type T at compile
// Helper typetraits that indicates support for arenas in a type T at compile
// time. This is public only to allow construction of higher-level templated
// utilities. is_arena_constructable<T>::value is true if the message type T
// has arena support enabled, and false otherwise.
// utilities.
//
// is_arena_constructable<T>::value is true if the message type T has arena
// support enabled, and false otherwise.
//
// is_destructor_skippable<T>::value is true if the message type T has told
// the arena that it is safe to skip the destructor, and false otherwise.
//
// This is inside Arena because only Arena has the friend relationships
// necessary to see the underlying generated code traits.
template <typename T>
struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {};
template <typename T>
struct is_destructor_skippable : InternalHelper<T>::is_destructor_skippable {
};
private:
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* CreateMessageInternal(::google::protobuf::Arena* arena) {
#if LANG_CXX11
template <typename T, typename... Args>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMessageInternal(
Arena* arena, Args&&... args) {
static_assert(
InternalHelper<T>::is_arena_constructable::value,
"CreateMessage can only construct types that are ArenaConstructable");
#endif
if (arena == NULL) {
return new T;
return new T(nullptr, std::forward<Args>(args)...);
} else {
return arena->CreateMessageInternal<T>();
return arena->DoCreateMessage<T>(std::forward<Args>(args)...);
}
}
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* CreateInternal(::google::protobuf::Arena* arena) {
// This specialization for no arguments is necessary, because its behavior is
// slightly different. When the arena pointer is nullptr, it calls T()
// instead of T(nullptr).
template <typename T>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMessageInternal(
Arena* arena) {
static_assert(
InternalHelper<T>::is_arena_constructable::value,
"CreateMessage can only construct types that are ArenaConstructable");
if (arena == NULL) {
return new T();
} else {
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value);
return arena->DoCreateMessage<T>();
}
}
template <typename T, typename... Args>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateInternal(
Arena* arena, Args&&... args) {
if (arena == NULL) {
return new T(std::forward<Args>(args)...);
} else {
return arena->DoCreate<T>(std::is_trivially_destructible<T>::value,
std::forward<Args>(args)...);
}
}
@ -696,8 +519,9 @@ class LIBPROTOBUF_EXPORT Arena {
// Allocate and also optionally call on_arena_allocation callback with the
// allocated type info when the hooks are in place in ArenaOptions and
// the cookie is not null.
template<typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
void* AllocateInternal(bool skip_explicit_ownership) {
template <typename T>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void* AllocateInternal(
bool skip_explicit_ownership) {
const size_t n = internal::AlignUpTo8(sizeof(T));
AllocHook(RTTI_TYPE_ID(T), n);
// Monitor allocation if needed.
@ -714,27 +538,49 @@ class LIBPROTOBUF_EXPORT Arena {
// as it can cause confusing API usages, and end up having double free in
// user code. These are used only internally from LazyField and Repeated
// fields, since they are designed to work in all mode combinations.
template <typename Msg> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static Msg* CreateMaybeMessage(Arena* arena, google::protobuf::internal::true_type) {
return CreateMessageInternal<Msg>(arena);
template <typename Msg, typename... Args>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Msg* DoCreateMaybeMessage(
Arena* arena, std::true_type, Args&&... args) {
return CreateMessageInternal<Msg>(arena, std::forward<Args>(args)...);
}
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* CreateMaybeMessage(Arena* arena, google::protobuf::internal::false_type) {
return CreateInternal<T>(arena);
template <typename T, typename... Args>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* DoCreateMaybeMessage(
Arena* arena, std::false_type, Args&&... args) {
return CreateInternal<T>(arena, std::forward<Args>(args)...);
}
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static T* CreateMaybeMessage(Arena* arena) {
return CreateMaybeMessage<T>(arena, is_arena_constructable<T>());
template <typename T, typename... Args>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMaybeMessage(
Arena* arena, Args&&... args) {
return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(),
std::forward<Args>(args)...);
}
template <typename T, typename... Args>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateNoMessage(
Arena* arena, std::true_type, Args&&... args) {
// User is constructing with Create() despite the fact that T supports arena
// construction. In this case we have to delegate to CreateInternal(), and
// we can't use any CreateMaybeMessage() specialization that may be defined.
return CreateInternal<T>(arena, std::forward<Args>(args)...);
}
template <typename T, typename... Args>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateNoMessage(
Arena* arena, std::false_type, Args&&... args) {
// User is constructing with Create() and the type does not support arena
// construction. In this case we can delegate to CreateMaybeMessage() and
// use any specialization that may be available for that.
return CreateMaybeMessage<T>(arena, std::forward<Args>(args)...);
}
// Just allocate the required size for the given type assuming the
// type has a trivial constructor.
template<typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateInternalRawArray(size_t num_elements) {
GOOGLE_CHECK_LE(num_elements,
std::numeric_limits<size_t>::max() / sizeof(T))
template <typename T>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* CreateInternalRawArray(
size_t num_elements) {
GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
<< "Requested size is too large to fit into size_t.";
const size_t n = internal::AlignUpTo8(sizeof(T) * num_elements);
// Monitor allocation if needed.
@ -742,143 +588,18 @@ class LIBPROTOBUF_EXPORT Arena {
return static_cast<T*>(impl_.AllocateAligned(n));
}
#if LANG_CXX11
template <typename T, typename... Args>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateInternal(bool skip_explicit_ownership, Args&&... args) {
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* DoCreate(
bool skip_explicit_ownership, Args&&... args) {
return new (AllocateInternal<T>(skip_explicit_ownership))
T(std::forward<Args>(args)...);
}
#else
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateInternal(bool skip_explicit_ownership) {
return new (AllocateInternal<T>(skip_explicit_ownership)) T();
}
template <typename T, typename Arg> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateInternal(bool skip_explicit_ownership, const Arg& arg) {
return new (AllocateInternal<T>(skip_explicit_ownership)) T(arg);
}
template <typename T, typename Arg1, typename Arg2>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateInternal(bool skip_explicit_ownership,
const Arg1& arg1,
const Arg2& arg2) {
return new (AllocateInternal<T>(skip_explicit_ownership)) T(arg1, arg2);
}
template <typename T, typename Arg1, typename Arg2, typename Arg3>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateInternal(bool skip_explicit_ownership,
const Arg1& arg1,
const Arg2& arg2,
const Arg3& arg3) {
return new (AllocateInternal<T>(skip_explicit_ownership))
T(arg1, arg2, arg3);
}
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateInternal(bool skip_explicit_ownership,
const Arg1& arg1,
const Arg2& arg2,
const Arg3& arg3,
const Arg4& arg4) {
return new (AllocateInternal<T>(skip_explicit_ownership))
T(arg1, arg2, arg3, arg4);
}
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateInternal(bool skip_explicit_ownership,
const Arg1& arg1,
const Arg2& arg2,
const Arg3& arg3,
const Arg4& arg4,
const Arg5& arg5) {
return new (AllocateInternal<T>(skip_explicit_ownership))
T(arg1, arg2, arg3, arg4, arg5);
}
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5, typename Arg6>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateInternal(bool skip_explicit_ownership,
const Arg1& arg1,
const Arg2& arg2,
const Arg3& arg3,
const Arg4& arg4,
const Arg5& arg5,
const Arg6& arg6) {
return new (AllocateInternal<T>(skip_explicit_ownership))
T(arg1, arg2, arg3, arg4, arg5, arg6);
}
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5, typename Arg6, typename Arg7>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateInternal(bool skip_explicit_ownership,
const Arg1& arg1,
const Arg2& arg2,
const Arg3& arg3,
const Arg4& arg4,
const Arg5& arg5,
const Arg6& arg6,
const Arg7& arg7) {
return new (AllocateInternal<T>(skip_explicit_ownership))
T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5, typename Arg6, typename Arg7,
typename Arg8>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateInternal(bool skip_explicit_ownership,
const Arg1& arg1,
const Arg2& arg2,
const Arg3& arg3,
const Arg4& arg4,
const Arg5& arg5,
const Arg6& arg6,
const Arg7& arg7,
const Arg8& arg8) {
return new (AllocateInternal<T>(skip_explicit_ownership))
T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}
#endif
#if LANG_CXX11
template <typename T, typename... Args>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* CreateMessageInternal(
Args&&... args) {
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* DoCreateMessage(Args&&... args) {
return InternalHelper<T>::Construct(
AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value),
this, std::forward<Args>(args)...);
}
#endif
template <typename T>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* CreateMessageInternal() {
return InternalHelper<T>::Construct(
AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value),
this);
}
template <typename T, typename Arg> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateMessageInternal(const Arg& arg) {
return InternalHelper<T>::Construct(
AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value),
this, arg);
}
template <typename T, typename Arg1, typename Arg2>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
T* CreateMessageInternal(const Arg1& arg1, const Arg2& arg2) {
return InternalHelper<T>::Construct(
AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value),
this, arg1, arg2);
}
// CreateInArenaStorage is used to implement map field. Without it,
// google::protobuf::Map need to call generated message's protected arena constructor,
@ -893,22 +614,22 @@ class LIBPROTOBUF_EXPORT Arena {
}
template <typename T>
static void CreateInArenaStorageInternal(
T* ptr, Arena* arena, google::protobuf::internal::true_type) {
static void CreateInArenaStorageInternal(T* ptr, Arena* arena,
std::true_type) {
InternalHelper<T>::Construct(ptr, arena);
}
template <typename T>
static void CreateInArenaStorageInternal(
T* ptr, Arena* /* arena */, google::protobuf::internal::false_type) {
static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */,
std::false_type) {
new (ptr) T();
}
template <typename T>
static void RegisterDestructorInternal(
T* /* ptr */, Arena* /* arena */, google::protobuf::internal::true_type) {}
static void RegisterDestructorInternal(T* /* ptr */, Arena* /* arena */,
std::true_type) {}
template <typename T>
static void RegisterDestructorInternal(
T* ptr, Arena* arena, google::protobuf::internal::false_type) {
static void RegisterDestructorInternal(T* ptr, Arena* arena,
std::false_type) {
arena->OwnDestructor(ptr);
}
@ -917,15 +638,16 @@ class LIBPROTOBUF_EXPORT Arena {
// is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing
// all template instantiations to one for generic Message reduces code size,
// using the virtual destructor instead.
template<typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
void OwnInternal(T* object, google::protobuf::internal::true_type) {
template <typename T>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void OwnInternal(T* object,
std::true_type) {
if (object != NULL) {
impl_.AddCleanup(object,
&internal::arena_delete_object< ::google::protobuf::Message>);
impl_.AddCleanup(object, &internal::arena_delete_object<Message>);
}
}
template<typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
void OwnInternal(T* object, google::protobuf::internal::false_type) {
template <typename T>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void OwnInternal(T* object,
std::false_type) {
if (object != NULL) {
impl_.AddCleanup(object, &internal::arena_delete_object<T>);
}
@ -934,16 +656,15 @@ class LIBPROTOBUF_EXPORT Arena {
// Implementation for GetArena(). Only message objects with
// InternalArenaConstructable_ tags can be associated with an arena, and such
// objects must implement a GetArenaNoVirtual() method.
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static ::google::protobuf::Arena* GetArenaInternal(
const T* value, google::protobuf::internal::true_type) {
template <typename T>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Arena* GetArenaInternal(
const T* value, std::true_type) {
return InternalHelper<T>::GetArena(value);
}
template <typename T>
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
static ::google::protobuf::Arena* GetArenaInternal(
const T* /* value */, google::protobuf::internal::false_type) {
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Arena* GetArenaInternal(
const T* /* value */, std::false_type) {
return NULL;
}
@ -965,9 +686,10 @@ class LIBPROTOBUF_EXPORT Arena {
void* hooks_cookie_;
template <typename Type>
friend class ::google::protobuf::internal::GenericTypeHandler;
friend class internal::GenericTypeHandler;
friend struct internal::ArenaStringPtr; // For AllocateAligned.
friend class internal::LazyField; // For CreateMaybeMessage.
friend class internal::LazyField; // For CreateMaybeMessage.
friend class MessageLite;
template <typename Key, typename T>
friend class Map;
};

View File

@ -33,13 +33,11 @@
#ifndef GOOGLE_PROTOBUF_ARENA_IMPL_H__
#define GOOGLE_PROTOBUF_ARENA_IMPL_H__
#include <atomic>
#include <limits>
#include <google/protobuf/stubs/atomic_sequence_num.h>
#include <google/protobuf/stubs/atomicops.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/port.h>
@ -248,7 +246,7 @@ class LIBPROTOBUF_EXPORT ArenaImpl {
int64 last_lifecycle_id_seen;
SerialArena* last_serial_arena;
};
static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
static std::atomic<int64> lifecycle_id_generator_;
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
// Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
// local storage class we implemented.
@ -277,12 +275,15 @@ class LIBPROTOBUF_EXPORT ArenaImpl {
// TODO(haberman): evaluate whether we would gain efficiency by getting rid
// of hint_. It's the only write we do to ArenaImpl in the allocation path,
// which will dirty the cache line.
google::protobuf::internal::Release_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(serial));
hint_.store(serial, std::memory_order_release);
}
google::protobuf::internal::AtomicWord threads_; // Pointer to a linked list of SerialArena.
google::protobuf::internal::AtomicWord hint_; // Fast thread-local block access
google::protobuf::internal::AtomicWord space_allocated_; // Sum of sizes of all allocated blocks.
std::atomic<SerialArena*>
threads_; // Pointer to a linked list of SerialArena.
std::atomic<SerialArena*> hint_; // Fast thread-local block access
std::atomic<size_t> space_allocated_; // Total size of all allocated blocks.
Block *initial_block_; // If non-NULL, points to the block that came from
// user data.
@ -297,18 +298,20 @@ class LIBPROTOBUF_EXPORT ArenaImpl {
Options options_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArenaImpl);
// All protos have pointers back to the arena hence Arena must have
// pointer stability.
ArenaImpl(ArenaImpl&&) = delete;
ArenaImpl& operator=(ArenaImpl&&) = delete;
public:
// kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8
// to protect the invariant that pos is always at a multiple of 8.
static const size_t kBlockHeaderSize = (sizeof(Block) + 7) & -8;
static const size_t kSerialArenaSize = (sizeof(SerialArena) + 7) & -8;
#if LANG_CXX11
static_assert(kBlockHeaderSize % 8 == 0,
"kBlockHeaderSize must be a multiple of 8.");
static_assert(kSerialArenaSize % 8 == 0,
"kSerialArenaSize must be a multiple of 8.");
#endif
};
} // namespace internal

View File

@ -50,7 +50,7 @@ void TestParseCorruptedString(const T& message) {
s[i] ^= c;
google::protobuf::Arena arena;
T* message =
google::protobuf::Arena::CreateMessage<T>(use_arena ? &arena : NULL);
google::protobuf::Arena::CreateMessage<T>(use_arena ? &arena : nullptr);
if (message->ParseFromString(s)) {
++success_count;
}

View File

@ -33,10 +33,8 @@
#include <algorithm>
#include <cstring>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <string>
#include <type_traits>
#include <typeinfo>
#include <vector>
@ -153,9 +151,19 @@ class MustBeConstructedWithOneThroughEight {
TEST(ArenaTest, ArenaConstructable) {
EXPECT_TRUE(Arena::is_arena_constructable<TestAllTypes>::type::value);
EXPECT_TRUE(Arena::is_arena_constructable<const TestAllTypes>::type::value);
EXPECT_FALSE(Arena::is_arena_constructable<
protobuf_unittest_no_arena::TestNoArenaMessage>::type::value);
EXPECT_FALSE(Arena::is_arena_constructable<Arena>::type::value);
}
TEST(ArenaTest, DestructorSkippable) {
EXPECT_TRUE(Arena::is_destructor_skippable<TestAllTypes>::type::value);
EXPECT_TRUE(Arena::is_destructor_skippable<const TestAllTypes>::type::value);
EXPECT_FALSE(Arena::is_destructor_skippable<
protobuf_unittest_no_arena::TestNoArenaMessage>::type::value);
EXPECT_FALSE(Arena::is_destructor_skippable<Arena>::type::value);
}
TEST(ArenaTest, BasicCreate) {
Arena arena;
EXPECT_TRUE(Arena::Create<int32>(&arena) != NULL);
@ -197,7 +205,6 @@ TEST(ArenaTest, CreateAndNonConstCopy) {
EXPECT_EQ("foo", *s_copy);
}
#if LANG_CXX11
TEST(ArenaTest, CreateAndMove) {
Arena arena;
string s("foo");
@ -206,7 +213,6 @@ TEST(ArenaTest, CreateAndMove) {
EXPECT_TRUE(s.empty()); // NOLINT
EXPECT_EQ("foo", *s_move);
}
#endif
TEST(ArenaTest, CreateWithFourConstructorArguments) {
Arena arena;
@ -242,7 +248,6 @@ TEST(ArenaTest, CreateWithEightConstructorArguments) {
ASSERT_EQ("8", new_object->eight_);
}
#if LANG_CXX11
class PleaseMoveMe {
public:
explicit PleaseMoveMe(const string& value) : value_(value) {}
@ -263,7 +268,6 @@ TEST(ArenaTest, CreateWithMoveArguments) {
EXPECT_TRUE(new_object);
ASSERT_EQ("1", new_object->value());
}
#endif
TEST(ArenaTest, InitialBlockTooSmall) {
// Construct a small (64 byte) initial block of memory to be used by the
@ -442,7 +446,7 @@ TEST(ArenaTest, ReflectionSwapFields) {
TestUtil::SetAllFields(arena1_message);
reflection->SwapFields(arena1_message, &message, fields);
EXPECT_EQ(&arena1, arena1_message->GetArena());
EXPECT_EQ(NULL, message.GetArena());
EXPECT_EQ(nullptr, message.GetArena());
arena1_message->SerializeToString(&output);
EXPECT_EQ(0, output.size());
TestUtil::ExpectAllFieldsSet(message);
@ -468,7 +472,7 @@ TEST(ArenaTest, ReleaseMessage) {
Arena arena;
TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
arena_message->mutable_optional_nested_message()->set_bb(118);
google::protobuf::scoped_ptr<TestAllTypes::NestedMessage> nested(
std::unique_ptr<TestAllTypes::NestedMessage> nested(
arena_message->release_optional_nested_message());
EXPECT_EQ(118, nested->bb());
@ -489,7 +493,7 @@ TEST(ArenaTest, ReleaseString) {
Arena arena;
TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
arena_message->set_optional_string("hello");
google::protobuf::scoped_ptr<string> released_str(
std::unique_ptr<string> released_str(
arena_message->release_optional_string());
EXPECT_EQ("hello", *released_str);
@ -600,25 +604,6 @@ TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) {
}
#endif // !GOOGLE_PROTOBUF_NO_RTTI
TEST(ArenaTest, UnsafeArenaReleaseDoesNotMakeCopy) {
Arena arena;
TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
TestAllTypes::NestedMessage* nested_msg = NULL;
TestAllTypes::NestedMessage* orig_nested_msg = NULL;
string* nested_string = NULL;
string* orig_nested_string = NULL;
arena_message->mutable_optional_nested_message()->set_bb(42);
*arena_message->mutable_optional_string() = "Hello";
orig_nested_msg = arena_message->mutable_optional_nested_message();
orig_nested_string = arena_message->mutable_optional_string();
nested_msg = arena_message->unsafe_arena_release_optional_nested_message();
nested_string = arena_message->unsafe_arena_release_optional_string();
EXPECT_EQ(orig_nested_msg, nested_msg);
EXPECT_EQ(orig_nested_string, nested_string);
// Released pointers still on arena; no 'delete' calls needed here.
}
TEST(ArenaTest, SetAllocatedAcrossArenas) {
Arena arena1;
TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
@ -898,17 +883,18 @@ TEST(ArenaTest, ReleaseLastRepeatedField) {
TEST(ArenaTest, UnsafeArenaReleaseAdd) {
// Use unsafe_arena_release() and unsafe_arena_set_allocated() to transfer an
// arena-allocated string from one message to another.
const char kContent[] = "Test content";
Arena arena;
TestAllTypes* message1 = Arena::CreateMessage<TestAllTypes>(&arena);
TestAllTypes* message2 = Arena::CreateMessage<TestAllTypes>(&arena);
string* arena_string = Arena::Create<string>(&arena);
*arena_string = "Test content";
*arena_string = kContent;
message1->unsafe_arena_set_allocated_optional_string(arena_string);
EXPECT_EQ(arena_string, message1->mutable_optional_string());
message2->unsafe_arena_set_allocated_optional_string(
message1->unsafe_arena_release_optional_string());
EXPECT_EQ(arena_string, message2->mutable_optional_string());
EXPECT_EQ(kContent, message2->optional_string());
}
TEST(ArenaTest, UnsafeArenaAddAllocated) {
@ -1432,7 +1418,7 @@ TEST(ArenaTest, ArenaHooksSanity) {
EXPECT_EQ(1, ArenaHooksTestUtil::num_init);
EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations);
::google::protobuf::Arena::Create<uint64>(&arena);
if (google::protobuf::internal::has_trivial_destructor<uint64>::value) {
if (std::is_trivially_destructible<uint64>::value) {
EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations);
} else {
EXPECT_EQ(2, ArenaHooksTestUtil::num_allocations);

View File

@ -99,6 +99,13 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
if (ptr_ == default_value) {
return NULL;
}
return ReleaseNonDefault(default_value, arena);
}
// Similar to Release, but ptr_ cannot be the default_value.
inline ::std::string* ReleaseNonDefault(
const ::std::string* default_value, ::google::protobuf::Arena* arena) {
GOOGLE_DCHECK(!IsDefault(default_value));
::std::string* released = NULL;
if (arena != NULL) {
// ptr_ is owned by the arena.
@ -164,6 +171,29 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) {
std::swap(ptr_, other->ptr_);
}
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void Swap(
ArenaStringPtr* other, const ::std::string* default_value, Arena* arena) {
#ifndef NDEBUG
// For debug builds, we swap the contents of the string, rather than the
// string instances themselves. This invalidates previously taken const
// references that are (per our documentation) invalidated by calling Swap()
// on the message.
//
// If both strings are the default_value, swapping is uninteresting.
// Otherwise, we use ArenaStringPtr::Mutable() to access the string, to
// ensure that we do not try to mutate default_value itself.
if (IsDefault(default_value) && other->IsDefault(default_value)) {
return;
}
::std::string* this_ptr = Mutable(default_value, arena);
::std::string* other_ptr = other->Mutable(default_value, arena);
this_ptr->swap(*other_ptr);
#else
std::swap(ptr_, other->ptr_);
#endif
}
// Frees storage (if not on an arena).
inline void Destroy(const ::std::string* default_value,
@ -186,6 +216,15 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
}
}
// Clears content, assuming that the current value is not the empty string
// default.
inline void ClearNonDefaultToEmpty() {
ptr_->clear();
}
inline void ClearNonDefaultToEmptyNoArena() {
ptr_->clear();
}
// Clears content, but keeps allocated string if arena != NULL, to avoid the
// overhead of heap operations. After this returns, the content (as seen by
// the user) will always be equal to |default_value|.
@ -253,12 +292,19 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
if (ptr_ == default_value) {
return NULL;
} else {
::std::string* released = ptr_;
ptr_ = const_cast< ::std::string* >(default_value);
return released;
return ReleaseNonDefaultNoArena(default_value);
}
}
inline ::std::string* ReleaseNonDefaultNoArena(
const ::std::string* default_value) {
GOOGLE_DCHECK(!IsDefault(default_value));
::std::string* released = ptr_;
ptr_ = const_cast< ::std::string* >(default_value);
return released;
}
inline void SetAllocatedNoArena(const ::std::string* default_value,
::std::string* value) {
if (ptr_ != default_value) {

View File

@ -35,9 +35,6 @@
#include <algorithm>
#include <cstdlib>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <string>
#include <vector>

View File

@ -31,9 +31,6 @@
#include <google/protobuf/compiler/annotation_test_util.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/io/printer.h>

View File

@ -34,9 +34,9 @@
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/plugin.pb.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/plugin.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/stubs/strutil.h>

View File

@ -58,9 +58,6 @@
#include <limits.h> //For PATH_MAX
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
@ -171,8 +168,7 @@ bool VerifyDirectoryExists(const string& path) {
// directories listed in |filename|.
bool TryCreateParentDirectory(const string& prefix, const string& filename) {
// Recursively create parent directories to the output file.
std::vector<string> parts =
Split(filename, "/", true);
std::vector<string> parts = Split(filename, "/", true);
string path_so_far = prefix;
for (int i = 0; i < parts.size() - 1; i++) {
path_so_far += parts[i];
@ -440,7 +436,7 @@ class CommandLineInterface::MemoryOutputStream
bool append_mode_;
// StringOutputStream writing to data_.
google::protobuf::scoped_ptr<io::StringOutputStream> inner_;
std::unique_ptr<io::StringOutputStream> inner_;
};
// -------------------------------------------------------------------
@ -835,10 +831,10 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
std::vector<const FileDescriptor*> parsed_files;
// null unless descriptor_set_in_names_.empty()
google::protobuf::scoped_ptr<DiskSourceTree> disk_source_tree;
google::protobuf::scoped_ptr<ErrorPrinter> error_collector;
google::protobuf::scoped_ptr<DescriptorPool> descriptor_pool;
google::protobuf::scoped_ptr<DescriptorDatabase> descriptor_database;
std::unique_ptr<DiskSourceTree> disk_source_tree;
std::unique_ptr<ErrorPrinter> error_collector;
std::unique_ptr<DescriptorPool> descriptor_pool;
std::unique_ptr<DescriptorDatabase> descriptor_database;
if (descriptor_set_in_names_.empty()) {
disk_source_tree.reset(new DiskSourceTree());
if (!InitializeDiskSourceTree(disk_source_tree.get())) {
@ -1395,8 +1391,7 @@ CommandLineInterface::InterpretArgument(const string& name,
// with colons. Let's accept that syntax too just to make things more
// intuitive.
std::vector<string> parts = Split(
value,
CommandLineInterface::kPathSeparator,
value, CommandLineInterface::kPathSeparator,
true);
for (int i = 0; i < parts.size(); i++) {
@ -1421,7 +1416,7 @@ CommandLineInterface::InterpretArgument(const string& name,
// Make sure disk path exists, warn otherwise.
if (access(disk_path.c_str(), F_OK) < 0) {
// Try the original path; it may have just happed to have a '=' in it.
// Try the original path; it may have just happened to have a '=' in it.
if (access(parts[i].c_str(), F_OK) < 0) {
std::cerr << disk_path << ": warning: directory does not exist."
<< std::endl;
@ -1447,8 +1442,7 @@ CommandLineInterface::InterpretArgument(const string& name,
}
direct_dependencies_explicitly_set_ = true;
std::vector<string> direct = Split(
value, ":", true);
std::vector<string> direct = Split(value, ":", true);
GOOGLE_DCHECK(direct_dependencies_.empty());
direct_dependencies_.insert(direct.begin(), direct.end());
@ -1481,9 +1475,8 @@ CommandLineInterface::InterpretArgument(const string& name,
}
descriptor_set_in_names_ = Split(
value,
CommandLineInterface::kPathSeparator,
true);
value, CommandLineInterface::kPathSeparator,
true);
} else if (name == "-o" || name == "--descriptor_set_out") {
if (!descriptor_set_out_name_.empty()) {
@ -1629,7 +1622,6 @@ CommandLineInterface::InterpretArgument(const string& name,
}
mode_ = MODE_PRINT;
print_mode_ = PRINT_FREE_FIELDS;
} else if (name == "--profile_path") {
} else {
// Some other flag. Look it up in the generators list.
const GeneratorInfo* generator_info =
@ -1908,10 +1900,12 @@ bool CommandLineInterface::GeneratePluginOutput(
string* error) {
CodeGeneratorRequest request;
CodeGeneratorResponse response;
string processed_parameter = parameter;
// Build the request.
if (!parameter.empty()) {
request.set_parameter(parameter);
if (!processed_parameter.empty()) {
request.set_parameter(processed_parameter);
}
@ -1948,17 +1942,18 @@ bool CommandLineInterface::GeneratePluginOutput(
// Write the files. We do this even if there was a generator error in order
// to match the behavior of a compiled-in generator.
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> current_output;
std::unique_ptr<io::ZeroCopyOutputStream> current_output;
for (int i = 0; i < response.file_size(); i++) {
const CodeGeneratorResponse::File& output_file = response.file(i);
if (!output_file.insertion_point().empty()) {
string filename = output_file.name();
// Open a file for insert.
// We reset current_output to NULL first so that the old file is closed
// before the new one is opened.
current_output.reset();
current_output.reset(generator_context->OpenForInsert(
output_file.name(), output_file.insertion_point()));
filename, output_file.insertion_point()));
} else if (!output_file.name().empty()) {
// Starting a new file. Open it.
// We reset current_output to NULL first so that the old file is closed
@ -1997,7 +1992,7 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
}
DynamicMessageFactory dynamic_factory(pool);
google::protobuf::scoped_ptr<Message> message(dynamic_factory.GetPrototype(type)->New());
std::unique_ptr<Message> message(dynamic_factory.GetPrototype(type)->New());
if (mode_ == MODE_ENCODE) {
SetFdToTextMode(STDIN_FILENO);

View File

@ -413,11 +413,6 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// dependency file will be written. Otherwise, empty.
string dependency_out_name_;
// Path to a file that contains serialized AccessInfo which provides
// relative hotness of fields per message. This helps protoc to generate
// better code.
string profile_path_;
// True if --include_imports was given, meaning that we should
// write all transitive dependencies to the DescriptorSet. Otherwise, only
// the .proto files listed on the command-line are added.

View File

@ -40,9 +40,6 @@
#include <unistd.h>
#endif
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <vector>
#include <google/protobuf/stubs/stringprintf.h>
@ -344,7 +341,7 @@ void CommandLineInterfaceTest::RunWithArgs(std::vector<string> args) {
}
}
google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
std::unique_ptr<const char * []> argv(new const char* [args.size()]);
for (int i = 0; i < args.size(); i++) {
args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true);
@ -2298,7 +2295,7 @@ class EncodeDecodeTest : public testing::TestWithParam<EncodeDecodeTestMode> {
ADD_FAILURE() << "unexpected EncodeDecodeTestMode: " << GetParam();
}
google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
std::unique_ptr<const char * []> argv(new const char* [args.size()]);
for (int i = 0; i < args.size(); i++) {
argv[i] = args[i].c_str();
}

View File

@ -44,6 +44,7 @@
#include <map>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_generator.h>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@ -97,9 +98,10 @@ class MockGeneratorContext : public GeneratorContext {
File::GetContents(TestSourceDir() + "/" + physical_filename,
&actual_contents, true));
EXPECT_TRUE(actual_contents == *expected_contents)
<< physical_filename << " needs to be regenerated. Please run "
"generate_descriptor_proto.sh. Then add this file "
"to your CL.";
<< physical_filename
<< " needs to be regenerated. Please run "
"generate_descriptor_proto.sh. "
"Then add this file to your CL.";
}
// implements GeneratorContext --------------------------------------
@ -116,37 +118,50 @@ class MockGeneratorContext : public GeneratorContext {
std::map<string, string*> files_;
};
TEST(BootstrapTest, GeneratedDescriptorMatches) {
MockErrorCollector error_collector;
const char kDescriptorParameter[] = "dllexport_decl=LIBPROTOBUF_EXPORT";
const char kPluginParameter[] = "dllexport_decl=LIBPROTOC_EXPORT";
const char kNormalParameter[] = "";
const char* test_protos[][2] = {
{"google/protobuf/descriptor", kDescriptorParameter},
{"google/protobuf/compiler/plugin", kPluginParameter},
};
TEST(BootstrapTest, GeneratedFilesMatch) {
// We need a mapping from the actual file to virtual and actual path
// of the data to compare to.
std::map<string, string> vpath_map;
std::map<string, string> rpath_map;
rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto2"] =
"net/proto2/z_generated_example/test_messages_proto2";
rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto3"] =
"net/proto2/z_generated_example/test_messages_proto3";
rpath_map["google/protobuf/proto2_weak"] =
"net/proto2/z_generated_example/proto2_weak";
DiskSourceTree source_tree;
source_tree.MapPath("", TestSourceDir());
Importer importer(&source_tree, &error_collector);
const FileDescriptor* proto_file =
importer.Import("google/protobuf/descriptor.proto");
const FileDescriptor* plugin_proto_file =
importer.Import("google/protobuf/compiler/plugin.proto");
EXPECT_EQ("", error_collector.text_);
ASSERT_TRUE(proto_file != NULL);
ASSERT_TRUE(plugin_proto_file != NULL);
CppGenerator generator;
MockGeneratorContext context;
string error;
string parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
ASSERT_TRUE(generator.Generate(proto_file, parameter,
&context, &error));
parameter = "dllexport_decl=LIBPROTOC_EXPORT";
ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter,
&context, &error));
for (auto file_parameter : test_protos) {
MockErrorCollector error_collector;
Importer importer(&source_tree, &error_collector);
const FileDescriptor* file =
importer.Import(file_parameter[0] + string(".proto"));
ASSERT_TRUE(file != nullptr)
<< "Can't import file " << file_parameter[0] + string(".proto") << "\n";
EXPECT_EQ("", error_collector.text_);
CppGenerator generator;
MockGeneratorContext context;
string error;
ASSERT_TRUE(generator.Generate(file, file_parameter[1], &context, &error));
context.ExpectFileMatches("google/protobuf/descriptor.pb.h",
"google/protobuf/descriptor.pb.h");
context.ExpectFileMatches("google/protobuf/descriptor.pb.cc",
"google/protobuf/descriptor.pb.cc");
context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h",
"google/protobuf/compiler/plugin.pb.h");
context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc",
"google/protobuf/compiler/plugin.pb.cc");
string vpath =
FindWithDefault(vpath_map, file_parameter[0], file_parameter[0]);
string rpath =
FindWithDefault(rpath_map, file_parameter[0], file_parameter[0]);
context.ExpectFileMatches(vpath + ".pb.cc", rpath + ".pb.cc");
context.ExpectFileMatches(vpath + ".pb.h", rpath + ".pb.h");
}
}
} // namespace

View File

@ -179,7 +179,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
void EnumGenerator::
GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
printer->Print(
"template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type "
"template <> struct is_proto_enum< $classname$> : ::std::true_type "
"{};\n",
"classname", ClassName(descriptor_, true));
if (HasDescriptorMethods(descriptor_->file(), options_)) {

View File

@ -35,8 +35,8 @@
#include <google/protobuf/compiler/cpp/cpp_extension.h>
#include <map>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
@ -120,7 +120,6 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
" ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
" $name$;\n"
);
}
void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {

View File

@ -34,21 +34,18 @@
#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
#include <google/protobuf/compiler/cpp/cpp_map_field.h>
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
@ -116,26 +113,30 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
}
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
const Options& options)
const Options& options,
SCCAnalyzer* scc_analyzer)
: descriptor_(descriptor),
options_(options),
field_generators_(
new google::protobuf::scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
new std::unique_ptr<FieldGenerator>[descriptor->field_count()]) {
// Construct all the FieldGenerators.
for (int i = 0; i < descriptor->field_count(); i++) {
field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
field_generators_[i].reset(
MakeGenerator(descriptor->field(i), options, scc_analyzer));
}
}
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
const Options& options) {
const Options& options,
SCCAnalyzer* scc_analyzer) {
if (field->is_repeated()) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
if (field->is_map()) {
return new MapFieldGenerator(field, options);
} else {
return new RepeatedMessageFieldGenerator(field, options);
return new RepeatedMessageFieldGenerator(field, options,
scc_analyzer);
}
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
@ -151,7 +152,7 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
} else if (field->containing_oneof()) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
return new MessageOneofFieldGenerator(field, options);
return new MessageOneofFieldGenerator(field, options, scc_analyzer);
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // StringOneofFieldGenerator handles unknown ctypes.
@ -166,7 +167,7 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
} else {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
return new MessageFieldGenerator(field, options);
return new MessageFieldGenerator(field, options, scc_analyzer);
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // StringFieldGenerator handles unknown ctypes.

View File

@ -37,13 +37,11 @@
#include <map>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <string>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/descriptor.h>
namespace google {
namespace protobuf {
@ -82,38 +80,12 @@ class FieldGenerator {
// implementation is empty.
virtual void GenerateStaticMembers(io::Printer* /*printer*/) const {}
// Generate prototypes for accessors that will manipulate imported
// messages inline. These are for .proto.h headers.
//
// In .proto.h mode, the headers of imports are not #included. However,
// functions that manipulate the imported message types need access to
// the class definition of the imported message, meaning that the headers
// must be #included. To get around this, functions that manipulate
// imported message objects are defined as dependent functions in a base
// template class. By making them dependent template functions, the
// function templates will not be instantiated until they are called, so
// we can defer to those translation units to #include the necessary
// generated headers.
//
// See:
// http://en.cppreference.com/w/cpp/language/class_template#Implicit_instantiation
//
// Most field types don't need this, so the default implementation is empty.
virtual void GenerateDependentAccessorDeclarations(
io::Printer* printer) const {}
// Generate prototypes for all of the accessor functions related to this
// field. These are placed inside the class definition.
virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0;
// Generate inline definitions of depenent accessor functions for this field.
// These are placed inside the header after all class definitions.
virtual void GenerateDependentInlineAccessorDefinitions(
io::Printer* printer) const {}
// Generate inline definitions of accessor functions for this field.
// These are placed inside the header after all class definitions.
// In non-.proto.h mode, this generates dependent accessor functions as well.
virtual void GenerateInlineAccessorDefinitions(
io::Printer* printer) const = 0;
@ -207,6 +179,11 @@ class FieldGenerator {
// are placed in the message's ByteSize() method.
virtual void GenerateByteSize(io::Printer* printer) const = 0;
// Any tags about field layout decisions (such as inlining) to embed in the
// offset.
virtual uint32 CalculateFieldTag() const { return 0; }
virtual bool IsInlined() const { return false; }
protected:
const Options& options_;
@ -217,7 +194,8 @@ class FieldGenerator {
// Convenience class which constructs FieldGenerators for a Descriptor.
class FieldGeneratorMap {
public:
FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
FieldGeneratorMap(const Descriptor* descriptor, const Options& options,
SCCAnalyzer* scc_analyzer);
~FieldGeneratorMap();
const FieldGenerator& get(const FieldDescriptor* field) const;
@ -225,10 +203,11 @@ class FieldGeneratorMap {
private:
const Descriptor* descriptor_;
const Options& options_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<FieldGenerator> > field_generators_;
std::unique_ptr<std::unique_ptr<FieldGenerator> []> field_generators_;
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
const Options& options);
const Options& options,
SCCAnalyzer* scc_analyzer);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};

View File

@ -35,20 +35,17 @@
#include <google/protobuf/compiler/cpp/cpp_file.h>
#include <map>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <set>
#include <vector>
#include <google/protobuf/compiler/cpp/cpp_enum.h>
#include <google/protobuf/compiler/cpp/cpp_service.h>
#include <google/protobuf/compiler/cpp/cpp_extension.h>
#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_message.h>
#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/compiler/cpp/cpp_service.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
@ -61,11 +58,11 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
options_(options),
scc_analyzer_(options),
enum_generators_owner_(
new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
new std::unique_ptr<EnumGenerator>[file->enum_type_count()]),
service_generators_owner_(
new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
new std::unique_ptr<ServiceGenerator>[file->service_count()]),
extension_generators_owner_(
new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]) {
new std::unique_ptr<ExtensionGenerator>[file->extension_count()]) {
std::vector<const Descriptor*> msgs = FlattenMessagesInFile(file);
for (int i = 0; i < msgs.size(); i++) {
// Deleted in destructor
@ -141,6 +138,9 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
printer->Print(
"// @@protoc_insertion_point(includes)\n");
printer->Print("#define PROTOBUF_INTERNAL_EXPORT_$filename$ $export$\n",
"filename", FileLevelNamespace(file_),
"export", options_.dllexport_decl);
GenerateMacroUndefs(printer);
GenerateGlobalStateFunctionDeclarations(printer);
@ -223,8 +223,9 @@ void FileGenerator::GeneratePBHeader(io::Printer* printer,
GenerateTopHeaderGuard(printer, filename_identifier);
if (options_.proto_h) {
string target_basename = StripProto(file_->name());
printer->Print("#include \"$basename$.proto.h\" // IWYU pragma: export\n",
"basename", StripProto(file_->name()));
"basename", target_basename);
} else {
GenerateLibraryIncludes(printer);
}
@ -256,9 +257,10 @@ void FileGenerator::GeneratePBHeader(io::Printer* printer,
}
void FileGenerator::GenerateSourceIncludes(io::Printer* printer) {
string target_basename = StripProto(file_->name());
const bool use_system_include = IsWellKnownMessage(file_);
string header =
StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
string header = target_basename + (options_.proto_h ? ".proto.h" : ".pb.h");
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"// source: $filename$\n"
@ -269,7 +271,6 @@ void FileGenerator::GenerateSourceIncludes(io::Printer* printer) {
"\n"
"#include <google/protobuf/stubs/common.h>\n"
"#include <google/protobuf/stubs/port.h>\n"
"#include <google/protobuf/stubs/once.h>\n"
"#include <google/protobuf/io/coded_stream.h>\n"
"#include <google/protobuf/wire_format_lite_inl.h>\n",
"filename", file_->name(),
@ -296,7 +297,8 @@ void FileGenerator::GenerateSourceIncludes(io::Printer* printer) {
for (int i = 0; i < file_->dependency_count(); i++) {
const FileDescriptor* dep = file_->dependency(i);
const char* extension = ".proto.h";
string dependency = StripProto(dep->name()) + extension;
string basename = StripProto(dep->name());
string dependency = basename + extension;
printer->Print(
"#include \"$dependency$\"\n",
"dependency", dependency);
@ -338,33 +340,34 @@ namespace {
// Generates weak symbol declarations for types that are to be considered weakly
// referenced.
void GenerateWeakDeclarations(
const FileDescriptor* file, const Options& options,
SCCAnalyzer* scc_analyzer,
io::Printer* printer) {
std::vector<const FieldDescriptor*> fields;
ListAllFields(file, &fields);
void GenerateInternalForwardDeclarations(
const std::vector<const FieldDescriptor*>& fields, const Options& options,
SCCAnalyzer* scc_analyzer, io::Printer* printer) {
// To ensure determinism and minimize the number of namespace statements,
// we output the forward declarations sorted on namespace and type / function
// name.
std::set<std::pair<string, string> > messages;
std::set<std::pair<string, string> > sccs;
std::set<std::pair<string, string> > inits;
for (int i = 0; i < fields.size(); ++i) {
const FieldDescriptor* field = fields[i];
bool is_weak = IsImplicitWeakField(field, options);
const Descriptor* msg = field->message_type();
if (msg == nullptr) continue;
bool is_weak = IsImplicitWeakField(field, options, scc_analyzer);
string flns = FileLevelNamespace(msg);
auto scc = scc_analyzer->GetSCC(msg);
string repr = ClassName(scc->GetRepresentative());
string weak_attr;
if (is_weak) {
const Descriptor* msg = field->message_type();
string flns = FileLevelNamespace(msg);
string repr = ClassName(scc_analyzer->GetSCC(msg)->GetRepresentative());
inits.insert(std::make_pair(flns, "InitDefaults" + repr));
inits.insert(std::make_pair(flns, "AddDescriptors"));
messages.insert(std::make_pair(Namespace(msg), ClassName(msg)));
weak_attr = " __attribute__((weak))";
}
}
if (messages.empty()) {
return;
string dllexport = "PROTOBUF_INTERNAL_EXPORT_" + FileLevelNamespace(msg);
sccs.insert(std::make_pair(flns, "extern " + dllexport + weak_attr +
" ::google::protobuf::internal::SCCInfo<" +
SimpleItoa(scc->children.size()) +
"> scc_info_" + repr + ";\n"));
}
printer->Print("\n");
@ -384,13 +387,33 @@ void GenerateWeakDeclarations(
printer->Print("void $name$() __attribute__((weak));\n",
"name", it->second);
}
for (const auto& p : sccs) {
ns.ChangeTo(p.first);
printer->Print(p.second.c_str());
}
}
} // namespace
void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
GenerateSourceIncludes(printer);
GenerateWeakDeclarations(file_, options_, &scc_analyzer_, printer);
// Generate weak declarations. We do this for the whole strongly-connected
// component (SCC), because we have a single InitDefaults* function for the
// SCC.
std::vector<const FieldDescriptor*> fields;
for (const Descriptor* message :
scc_analyzer_.GetSCC(message_generators_[idx]->descriptor_)
->descriptors) {
ListAllFields(message, &fields);
}
GenerateInternalForwardDeclarations(fields, options_, &scc_analyzer_,
printer);
if (IsSCCRepresentative(message_generators_[idx]->descriptor_)) {
NamespaceOpener ns(FileLevelNamespace(file_), printer);
GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), printer);
}
{ // package namespace
NamespaceOpener ns(Namespace(file_), printer);
@ -411,12 +434,6 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
"// @@protoc_insertion_point(namespace_scope)\n");
} // end package namespace
if (IsSCCRepresentative(message_generators_[idx]->descriptor_)) {
NamespaceOpener ns(FileLevelNamespace(file_), printer);
GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), printer);
}
printer->Print(
"namespace google {\nnamespace protobuf {\n");
message_generators_[idx]->GenerateSourceInProto2Namespace(printer);
@ -430,15 +447,16 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
void FileGenerator::GenerateGlobalSource(io::Printer* printer) {
GenerateSourceIncludes(printer);
GenerateWeakDeclarations(file_, options_, &scc_analyzer_, printer);
// TODO(gerbens) Generate tables here
// Define the code to initialize reflection. This code uses a global
// constructor to register reflection data with the runtime pre-main.
if (HasDescriptorMethods(file_, options_)) {
{
NamespaceOpener ns(FileLevelNamespace(file_), printer);
GenerateReflectionInitializationCode(printer);
GenerateTables(printer);
// Define the code to initialize reflection. This code uses a global
// constructor to register reflection data with the runtime pre-main.
if (HasDescriptorMethods(file_, options_)) {
GenerateReflectionInitializationCode(printer);
}
}
NamespaceOpener ns(Namespace(file_), printer);
@ -466,7 +484,10 @@ void FileGenerator::GenerateGlobalSource(io::Printer* printer) {
void FileGenerator::GenerateSource(io::Printer* printer) {
GenerateSourceIncludes(printer);
GenerateWeakDeclarations(file_, options_, &scc_analyzer_, printer);
std::vector<const FieldDescriptor*> fields;
ListAllFields(file_, &fields);
GenerateInternalForwardDeclarations(fields, options_, &scc_analyzer_,
printer);
{
NamespaceOpener ns(Namespace(file_), printer);
@ -483,9 +504,25 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
{
NamespaceOpener ns(FileLevelNamespace(file_), printer);
// Define the initialization code to initialize the default instances.
// This code doesn't use a global constructor.
GenerateInitializationCode(printer);
GenerateTables(printer);
// Now generate the InitDefaults for each SCC.
for (int i = 0; i < message_generators_.size(); i++) {
if (IsSCCRepresentative(message_generators_[i]->descriptor_)) {
GenerateInitForSCC(GetSCC(message_generators_[i]->descriptor_),
printer);
}
}
printer->Print("void InitDefaults() {\n");
for (int i = 0; i < message_generators_.size(); i++) {
if (!IsSCCRepresentative(message_generators_[i]->descriptor_)) continue;
string scc_name = ClassName(message_generators_[i]->descriptor_);
printer->Print(
" ::google::protobuf::internal::InitSCC(&scc_info_$scc_name$.base);\n",
"scc_name", scc_name);
}
printer->Print("}\n\n");
// Define the code to initialize reflection. This code uses a global
// constructor to register reflection data with the runtime pre-main.
@ -560,7 +597,7 @@ class FileGenerator::ForwardDeclarations {
ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
ForwardDeclarations*& ns = namespaces_[ns_name];
if (ns == NULL) {
if (ns == nullptr) {
ns = new ForwardDeclarations;
}
return ns;
@ -648,17 +685,12 @@ class FileGenerator::ForwardDeclarations {
end = classes_.end();
it != end; ++it) {
const Descriptor* d = it->second;
string extra_class_qualifier;
// "class" is to disambiguate in case there is also a function with this
// name. There is code out there that does this!
printer->Print(
"template<> "
"$dllexport_decl$"
"$class$$classname$* Arena::$func$< $class$$classname$>(Arena*);\n",
"classname", QualifiedClassName(d),
"func", MessageCreateFunction(d),
"class", extra_class_qualifier,
"dllexport_decl",
"$classname$* Arena::CreateMaybeMessage<$classname$>"
"(Arena*);\n",
"classname", QualifiedClassName(d), "dllexport_decl",
options.dllexport_decl.empty() ? "" : options.dllexport_decl + " ");
}
printer->Print(
@ -758,7 +790,6 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
// protobuf_AssignDescriptorsOnce(): The first time it is called, calls
// AssignDescriptors(). All later times, waits for the first call to
// complete and then returns.
string message_factory = "NULL";
printer->Print(
"void protobuf_AssignDescriptors() {\n"
// Make sure the file has found its way into the pool. If a descriptor
@ -766,10 +797,9 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
// been called yet, so we call it manually. Note that it's fine if
// AddDescriptors() is called multiple times.
" AddDescriptors();\n"
" ::google::protobuf::MessageFactory* factory = $factory$;\n"
" AssignDescriptors(\n"
" \"$filename$\", schemas, file_default_instances, "
"TableStruct::offsets, factory,\n"
"TableStruct::offsets,\n"
" $metadata$, $enum_descriptors$, $service_descriptors$);\n",
"filename", file_->name(), "metadata",
!message_generators_.empty() ? "file_level_metadata" : "NULL",
@ -778,14 +808,13 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
"service_descriptors",
HasGenericServices(file_, options_) && file_->service_count() > 0
? "file_level_service_descriptors"
: "NULL",
"factory", message_factory);
: "NULL");
printer->Print(
"}\n"
"\n"
"void protobuf_AssignDescriptorsOnce() {\n"
" static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n"
" ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);\n"
" static ::google::protobuf::internal::once_flag once;\n"
" ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors);\n"
"}\n"
"\n",
"filename", file_->name(), "metadata",
@ -795,8 +824,7 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
"service_descriptors",
HasGenericServices(file_, options_) && file_->service_count() > 0
? "file_level_service_descriptors"
: "NULL",
"factory", message_factory);
: "NULL");
// Only here because of useless string reference that we don't want in
// protobuf_AssignDescriptorsOnce, because that is called from all the
@ -891,8 +919,8 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
"}\n"
"\n"
"void AddDescriptors() {\n"
" static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n"
" ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);\n"
" static ::google::protobuf::internal::once_flag once;\n"
" ::google::protobuf::internal::call_once(once, AddDescriptorsImpl);\n"
"}\n");
printer->Print(
@ -907,47 +935,16 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
void FileGenerator::GenerateInitForSCC(const SCC* scc, io::Printer* printer) {
const string scc_name = ClassName(scc->GetRepresentative());
// We use static and not anonymous namespace because symbol names are
// substantially shorter.
printer->Print(
"void InitDefaults$scc_name$Impl() {\n"
"static void InitDefaults$scc_name$() {\n"
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n"
"#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS\n"
" ::google::protobuf::internal::InitProtobufDefaultsForceUnique();\n"
"#else\n"
" ::google::protobuf::internal::InitProtobufDefaults();\n"
"#endif // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS\n",
// Force initialization of primitive values we depend on.
, // awkward comma due to macro
"scc_name", scc_name);
printer->Indent();
// Call the InitDefaults() methods for all of our dependencies, to make
// sure they get added first.
for (int i = 0; i < scc->children.size(); i++) {
const SCC* child_scc = scc->children[i];
const FileDescriptor* dependency = child_scc->GetRepresentative()->file();
// Print the namespace prefix for the dependency.
string file_namespace = FileLevelNamespace(dependency);
std::map<string, string> variables;
variables["file_namespace"] = file_namespace;
variables["scc_name"] = ClassName(child_scc->GetRepresentative(), false);
bool using_weak_fields = UsingImplicitWeakFields(file_, options_);
if (using_weak_fields) {
// We're building for lite with implicit weak fields, so we need to handle
// the possibility that this InitDefaults function is not linked into the
// binary. Some of these might actually be guaranteed to be non-null since
// we might have a strong reference to the dependency (via a required
// field, for example), but it's simplest to just assume that any of them
// could be null.
printer->Print(
variables,
"if (&$file_namespace$::InitDefaults$scc_name$ != NULL) {\n"
" $file_namespace$::InitDefaults$scc_name$();\n"
"}\n");
} else {
printer->Print(variables,
"$file_namespace$::InitDefaults$scc_name$();\n");
}
}
// First construct all the necessary default instances.
for (int i = 0; i < message_generators_.size(); i++) {
@ -982,23 +979,24 @@ void FileGenerator::GenerateInitForSCC(const SCC* scc, io::Printer* printer) {
}
printer->Outdent();
printer->Print("}\n\n");
printer->Print(
"void InitDefaults$scc_name$() {\n"
" static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n"
" ::google::protobuf::GoogleOnceInit(&once, "
"&InitDefaults$scc_name$Impl);\n"
"}\n\n",
"scc_name", scc_name);
"$dllexport_decl$::google::protobuf::internal::SCCInfo<$size$> "
"scc_info_$scc_name$ =\n"
" {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), "
"$size$, InitDefaults$scc_name$}, {",
"size", SimpleItoa(scc->children.size()), "scc_name",
ClassName(scc->GetRepresentative()), "dllexport_decl",
options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
for (const SCC* child : scc->children) {
auto repr = child->GetRepresentative();
printer->Print("\n &$ns$::scc_info_$child$.base,", "ns",
FileLevelNamespace(repr), "child", ClassName(repr));
}
printer->Print("}};\n\n");
}
void FileGenerator::GenerateInitializationCode(io::Printer* printer) {
// Messages depend on the existence of a default instance, which has to
// initialized properly. The default instances are allocated in the data
// segment, but we can't quite allocate the type directly. The destructors
// cannot run at program exit as this could lead to segfaults in a threaded
// environment. Hence these instances must be inplace constructed at first
// use.
void FileGenerator::GenerateTables(io::Printer* printer) {
if (options_.table_driven_parsing) {
// TODO(ckennelly): Gate this with the same options flag to enable
// table-driven parsing.
@ -1105,16 +1103,6 @@ void FileGenerator::GenerateInitializationCode(io::Printer* printer) {
"};\n"
"\n");
}
// -----------------------------------------------------------------
// All functionality that need private access.
// Now generate the InitDefaults for each SCC.
for (int i = 0; i < message_generators_.size(); i++) {
if (IsSCCRepresentative(message_generators_[i]->descriptor_)) {
GenerateInitForSCC(GetSCC(message_generators_[i]->descriptor_), printer);
}
}
}
void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
@ -1145,8 +1133,8 @@ void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"// source: $filename$\n"
"\n"
"#ifndef PROTOBUF_$filename_identifier$_INCLUDED\n"
"#define PROTOBUF_$filename_identifier$_INCLUDED\n"
"#ifndef PROTOBUF_INCLUDED_$filename_identifier$\n"
"#define PROTOBUF_INCLUDED_$filename_identifier$\n"
"\n"
"#include <string>\n",
"filename", file_->name(), "filename_identifier", filename_identifier);
@ -1156,7 +1144,7 @@ void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
void FileGenerator::GenerateBottomHeaderGuard(
io::Printer* printer, const string& filename_identifier) {
printer->Print(
"#endif // PROTOBUF_$filename_identifier$_INCLUDED\n",
"#endif // PROTOBUF_INCLUDED_$filename_identifier$\n",
"filename_identifier", filename_identifier);
}
@ -1193,7 +1181,9 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
"#include <google/protobuf/arena.h>\n"
"#include <google/protobuf/arenastring.h>\n"
"#include <google/protobuf/generated_message_table_driven.h>\n"
"#include <google/protobuf/generated_message_util.h>\n");
"#include <google/protobuf/generated_message_util.h>\n"
"#include <google/protobuf/inlined_string_field.h>\n");
if (HasDescriptorMethods(file_, options_)) {
printer->Print(
@ -1280,11 +1270,12 @@ void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
const bool use_system_include = IsWellKnownMessage(file_->dependency(i));
const string& name = file_->dependency(i)->name();
bool public_import = (public_import_names.count(name) != 0);
string basename = StripProto(name);
printer->Print(
"#include $left$$dependency$.pb.h$right$$iwyu$\n",
"dependency", StripProto(name),
"dependency", basename,
"iwyu", (public_import) ? " // IWYU pragma: export" : "",
"left", use_system_include ? "<" : "\"",
"right", use_system_include ? ">" : "\"");
@ -1318,28 +1309,6 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations(
"void $dllexport_decl$AddDescriptors();\n", "dllexport_decl",
options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
}
for (int i = 0; i < message_generators_.size(); i++) {
if (!IsSCCRepresentative(message_generators_[i]->descriptor_)) continue;
string scc_name = ClassName(message_generators_[i]->descriptor_);
// TODO(gerbens) Remove the Impl from header. This is solely because
// it currently still needs to be a friend of the protos.
printer->Print(
"void $dllexport_decl$InitDefaults$scc_name$Impl();\n"
"void $dllexport_decl$InitDefaults$scc_name$();\n",
"scc_name", scc_name, "dllexport_decl",
options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
}
// TODO(gerbens) This is for proto1 interoperability. Remove when proto1
// is gone.
printer->Print(
"inline void $dllexport_decl$InitDefaults() {\n", "dllexport_decl",
options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
for (int i = 0; i < message_generators_.size(); i++) {
if (!IsSCCRepresentative(message_generators_[i]->descriptor_)) continue;
string scc_name = ClassName(message_generators_[i]->descriptor_);
printer->Print(" InitDefaults$scc_name$();\n", "scc_name", scc_name);
}
printer->Print("}\n");
printer->Print(
"} // namespace $file_namespace$\n",
"file_namespace", FileLevelNamespace(file_));
@ -1416,8 +1385,6 @@ void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
printer->Print(kThinSeparator);
printer->Print("\n");
}
// Methods of the dependent base class must always be inline in the header.
message_generators_[i]->GenerateDependentInlineMethods(printer);
}
}

View File

@ -37,9 +37,6 @@
#include <algorithm>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <set>
#include <string>
#include <vector>
@ -97,7 +94,7 @@ class FileGenerator {
void GenerateSourceDefaultInstance(int idx, io::Printer* printer);
void GenerateInitForSCC(const SCC* scc, io::Printer* printer);
void GenerateInitializationCode(io::Printer* printer);
void GenerateTables(io::Printer* printer);
void GenerateReflectionInitializationCode(io::Printer* printer);
// For other imports, generates their forward-declarations.
@ -176,10 +173,10 @@ class FileGenerator {
// These members are just for owning (and thus proper deleting).
// Nested (enum/extension)_generators are owned by child messages.
google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_owner_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ServiceGenerator> >
std::unique_ptr<std::unique_ptr<EnumGenerator> []> enum_generators_owner_;
std::unique_ptr<std::unique_ptr<ServiceGenerator> []>
service_generators_owner_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> >
std::unique_ptr<std::unique_ptr<ExtensionGenerator> []>
extension_generators_owner_;
// E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.

View File

@ -36,17 +36,15 @@
#include <vector>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <utility>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/compiler/cpp/cpp_file.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>
namespace google {
namespace protobuf {
@ -66,12 +64,6 @@ bool CppGenerator::Generate(const FileDescriptor* file,
// -----------------------------------------------------------------
// parse generator options
// TODO(kenton): If we ever have more options, we may want to create a
// class that encapsulates them which we can pass down to all the
// generator classes. Currently we pass dllexport_decl down to all of
// them via the constructors, but we don't want to have to add another
// constructor parameter for every option.
// If the dllexport_decl option is passed to the compiler, we need to write
// it in front of every symbol that should be exported if this .proto is
// compiled into a Windows DLL. E.g., if the user invokes the protocol
@ -127,11 +119,12 @@ bool CppGenerator::Generate(const FileDescriptor* file,
string basename = StripProto(file->name());
FileGenerator file_generator(file, file_options);
// Generate header(s).
if (file_options.proto_h) {
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
std::unique_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + ".proto.h"));
GeneratedCodeInfo annotations;
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
@ -143,14 +136,14 @@ bool CppGenerator::Generate(const FileDescriptor* file,
file_generator.GenerateProtoHeader(
&printer, file_options.annotate_headers ? info_path : "");
if (file_options.annotate_headers) {
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output(
std::unique_ptr<io::ZeroCopyOutputStream> info_output(
generator_context->Open(info_path));
annotations.SerializeToZeroCopyStream(info_output.get());
}
}
{
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
std::unique_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + ".pb.h"));
GeneratedCodeInfo annotations;
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
@ -162,7 +155,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
file_generator.GeneratePBHeader(
&printer, file_options.annotate_headers ? info_path : "");
if (file_options.annotate_headers) {
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output(
std::unique_ptr<io::ZeroCopyOutputStream> info_output(
generator_context->Open(info_path));
annotations.SerializeToZeroCopyStream(info_output.get());
}
@ -172,7 +165,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
if (UsingImplicitWeakFields(file, file_options)) {
{
// This is the global .cc file, containing enum/services/tables/reflection
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
std::unique_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + ".pb.cc"));
io::Printer printer(output.get(), '$');
file_generator.GenerateGlobalSource(&printer);
@ -191,7 +184,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
}
for (int i = 0; i < num_cc_files; i++) {
// TODO(gerbens) Agree on naming scheme.
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
std::unique_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + "." + SimpleItoa(i) + ".cc"));
io::Printer printer(output.get(), '$');
if (i < file_generator.NumMessages()) {
@ -199,7 +192,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
}
}
} else {
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
std::unique_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + ".pb.cc"));
io::Printer printer(output.get(), '$');
file_generator.GenerateSource(&printer);

View File

@ -42,6 +42,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
@ -73,7 +74,7 @@ const char* const kKeywordList[] = {
"constexpr", "const_cast", "continue", "decltype", "default", "delete", "do",
"double", "dynamic_cast", "else", "enum", "explicit", "export", "extern",
"false", "float", "for", "friend", "goto", "if", "inline", "int", "long",
"mutable", "namespace", "new", "noexcept", "not", "not_eq", "NULL",
"mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr",
"operator", "or", "or_eq", "private", "protected", "public", "register",
"reinterpret_cast", "return", "short", "signed", "sizeof", "static",
"static_assert", "static_cast", "struct", "switch", "template", "this",
@ -219,24 +220,12 @@ string ReferenceFunctionName(const Descriptor* descriptor) {
return QualifiedClassName(descriptor) + "_ReferenceStrong";
}
string DependentBaseClassTemplateName(const Descriptor* descriptor) {
return ClassName(descriptor, false) + "_InternalBase";
}
string SuperClassName(const Descriptor* descriptor, const Options& options) {
return HasDescriptorMethods(descriptor->file(), options)
? "::google::protobuf::Message"
: "::google::protobuf::MessageLite";
}
string DependentBaseDownCast() {
return "reinterpret_cast<T*>(this)->";
}
string DependentBaseConstDownCast() {
return "reinterpret_cast<const T*>(this)->";
}
string FieldName(const FieldDescriptor* field) {
string result = field->name();
LowerString(&result);
@ -294,60 +283,6 @@ string FieldConstantName(const FieldDescriptor *field) {
return result;
}
bool IsFieldDependent(const FieldDescriptor* field) {
if (field->containing_oneof() != NULL &&
field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
return true;
}
if (field->is_map()) {
const Descriptor* map_descriptor = field->message_type();
for (int i = 0; i < map_descriptor->field_count(); i++) {
if (IsFieldDependent(map_descriptor->field(i))) {
return true;
}
}
return false;
}
if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
return false;
}
if (field->containing_oneof() != NULL) {
// Oneof fields will always be dependent.
//
// This is a unique case for field codegen. Field generators are
// responsible for generating all the field-specific accessor
// functions, except for the clear_*() function; instead, field
// generators produce inline clearing code.
//
// For non-oneof fields, the Message class uses the inline clearing
// code to define the field's clear_*() function, as well as in the
// destructor. For oneof fields, the Message class generates a much
// more complicated clear_*() function, which clears only the oneof
// member that is set, in addition to clearing methods for each of the
// oneof members individually.
//
// Since oneofs do not have their own generator class, the Message code
// generation logic would be significantly complicated in order to
// split dependent and non-dependent manipulation logic based on
// whether the oneof truly needs to be dependent; so, for oneof fields,
// we just assume it (and its constituents) should be manipulated by a
// dependent base class function.
//
// This is less precise than how dependent message-typed fields are
// handled, but the cost is limited to only the generated code for the
// oneof field, which seems like an acceptable tradeoff.
return true;
}
if (field->file() == field->message_type()->file()) {
return false;
}
return true;
}
string DependentTypeName(const FieldDescriptor* field) {
return "InternalBase_" + field->name() + "_T";
}
string FieldMessageTypeName(const FieldDescriptor* field) {
// Note: The Google-internal version of Protocol Buffers uses this function
// as a hook point for hacks to support legacy code.
@ -748,12 +683,17 @@ bool UsingImplicitWeakFields(const FileDescriptor* file,
GetOptimizeFor(file, options) == FileOptions::LITE_RUNTIME;
}
bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options) {
bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
SCCAnalyzer* scc_analyzer) {
return UsingImplicitWeakFields(field->file(), options) &&
field->type() == FieldDescriptor::TYPE_MESSAGE &&
!field->is_required() && !field->is_map() &&
field->containing_oneof() == NULL;
field->containing_oneof() == NULL &&
!IsWellKnownMessage(field->message_type()->file()) &&
// We do not support implicit weak fields between messages in the same
// strongly-connected component.
scc_analyzer->GetSCC(field->containing_type()) !=
scc_analyzer->GetSCC(field->message_type());
}
struct CompareDescriptors {
@ -920,6 +860,7 @@ void ListAllTypesForServices(const FileDescriptor* fd,
}
}
} // namespace cpp
} // namespace compiler
} // namespace protobuf

View File

@ -38,8 +38,9 @@
#include <map>
#include <string>
#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/stubs/strutil.h>
@ -53,6 +54,7 @@ namespace cpp {
extern const char kThickSeparator[];
extern const char kThinSeparator[];
// Name space of the proto file. This namespace is such that the string
// "<namespace>::some_name" is the correct fully qualified namespace.
// This means if the package is empty the namespace is "", and otherwise
@ -102,19 +104,9 @@ string DefaultInstanceName(const Descriptor* descriptor);
// fields.
string ReferenceFunctionName(const Descriptor* descriptor);
// Name of the CRTP class template (for use with proto_h).
// This is a class name, like "ProtoName_InternalBase".
string DependentBaseClassTemplateName(const Descriptor* descriptor);
// Name of the base class: either the dependent base class (for use with
// proto_h) or google::protobuf::Message.
// Name of the base class: google::protobuf::Message or google::protobuf::MessageLite.
string SuperClassName(const Descriptor* descriptor, const Options& options);
// Returns a string that down-casts from the dependent base class to the
// derived class.
string DependentBaseDownCast();
string DependentBaseConstDownCast();
// Get the (unqualified) name that should be used for this field in C++ code.
// The name is coerced to lower-case to emulate proto1 behavior. People
// should be using lowercase-with-underscores style for proto field names
@ -141,20 +133,6 @@ inline const Descriptor* FieldScope(const FieldDescriptor* field) {
field->extension_scope() : field->containing_type();
}
// Returns true if the given 'field_descriptor' has a message type that is
// a dependency of the file where the field is defined (i.e., the field
// type is defined in a different file than the message holding the field).
//
// This only applies to Message-typed fields. Enum-typed fields may refer
// to an enum in a dependency; however, enums are specified and
// forward-declared with an enum-base, so the definition is not required to
// manipulate the field value.
bool IsFieldDependent(const FieldDescriptor* field_descriptor);
// Returns the name that should be used for forcing dependent lookup from a
// dependent base class.
string DependentTypeName(const FieldDescriptor* field);
// Returns the fully-qualified type name field->message_type(). Usually this
// is just ClassName(field->message_type(), true);
string FieldMessageTypeName(const FieldDescriptor* field);
@ -314,6 +292,11 @@ inline string MessageCreateFunction(const Descriptor* d) {
return SupportsArenas(d) ? "CreateMessage" : "Create";
}
inline string MakeDefaultName(const FieldDescriptor* field) {
return "_i_give_permission_to_break_this_code_default_" + FieldName(field) +
"_";
}
bool IsAnyMessage(const FileDescriptor* descriptor);
bool IsAnyMessage(const Descriptor* descriptor);
@ -350,13 +333,6 @@ inline std::vector<const Descriptor*> FlattenMessagesInFile(
bool HasWeakFields(const Descriptor* desc);
bool HasWeakFields(const FileDescriptor* desc);
// Indicates whether we should use implicit weak fields for this file.
bool UsingImplicitWeakFields(const FileDescriptor* file,
const Options& options);
// Indicates whether to treat this field as implicitly weak.
bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options);
// Returns true if the "required" restriction check should be ignored for the
// given field.
inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
@ -462,11 +438,21 @@ class LIBPROTOC_EXPORT SCCAnalyzer {
void AddChildren(SCC* scc);
};
void ListAllFields(const Descriptor* d,
std::vector<const FieldDescriptor*>* fields);
void ListAllFields(const FileDescriptor* d,
std::vector<const FieldDescriptor*>* fields);
void ListAllTypesForServices(const FileDescriptor* fd,
std::vector<const Descriptor*>* types);
// Indicates whether we should use implicit weak fields for this file.
bool UsingImplicitWeakFields(const FileDescriptor* file,
const Options& options);
// Indicates whether to treat this field as implicitly weak.
bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
SCCAnalyzer* scc_analyzer);
} // namespace cpp
} // namespace compiler
} // namespace protobuf

View File

@ -104,9 +104,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: FieldGenerator(options),
descriptor_(descriptor),
dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
: FieldGenerator(options), descriptor_(descriptor) {
SetMessageVariables(descriptor, &variables_, options);
}
@ -202,7 +200,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
key = "entry->key()";
value = "entry->value()";
printer->Print(variables_,
"::google::protobuf::scoped_ptr<$map_classname$> entry($name$_.NewEntry());\n");
"::std::unique_ptr<$map_classname$> entry($name$_.NewEntry());\n");
printer->Print(variables_,
"{\n"
" ::std::string data;\n"
@ -258,7 +256,7 @@ static void GenerateSerializationLoop(io::Printer* printer,
const string& ptr,
bool loop_via_iterators) {
printer->Print(variables,
StrCat("::google::protobuf::scoped_ptr<$map_classname$> entry;\n",
StrCat("::std::unique_ptr<$map_classname$> entry;\n",
loop_header, " {\n").c_str());
printer->Indent();
@ -365,7 +363,7 @@ void MapFieldGenerator::GenerateSerializeWithCachedSizes(
"\n"
"if ($deterministic$ &&\n"
" this->$name$().size() > 1) {\n"
" ::google::protobuf::scoped_array<SortItem> items(\n"
" ::std::unique_ptr<SortItem[]> items(\n"
" new SortItem[this->$name$().size()]);\n"
" typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::size_type size_type;\n"
" size_type n = 0;\n"
@ -402,7 +400,7 @@ GenerateByteSize(io::Printer* printer) const {
"total_size += $tag_size$ *\n"
" ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
"{\n"
" ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
" ::std::unique_ptr<$map_classname$> entry;\n"
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
" it = this->$name$().begin();\n"
" it != this->$name$().end(); ++it) {\n");

View File

@ -66,7 +66,6 @@ class MapFieldGenerator : public FieldGenerator {
io::Printer* printer, const std::map<string, string>& variables) const;
const FieldDescriptor* descriptor_;
const bool dependent_field_;
std::map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);

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