diff options
39 files changed, 673 insertions, 289 deletions
diff --git a/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in index abd70616..4b572bb6 100644 --- a/cmake/extract_includes.bat.in +++ b/cmake/extract_includes.bat.in @@ -80,10 +80,10 @@ copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_intern 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_atomicword_compat.h include\google\protobuf\stubs\atomicops_internals_atomicword_compat.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_macosx.h include\google\protobuf\stubs\atomicops_internals_macosx.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_pnacl.h include\google\protobuf\stubs\atomicops_internals_pnacl.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 diff --git a/conformance/failure_list_csharp.txt b/conformance/failure_list_csharp.txt index dfafbecc..84f46fab 100644 --- a/conformance/failure_list_csharp.txt +++ b/conformance/failure_list_csharp.txt @@ -1,6 +1,2 @@ Recommended.JsonInput.FieldNameWithDoubleUnderscores.JsonOutput Required.JsonInput.FieldNameInSnakeCase.JsonOutput -Required.JsonInput.FieldNameWithMixedCases.JsonOutput -Required.JsonInput.FieldNameWithMixedCases.ProtobufOutput -Required.JsonInput.FieldNameWithMixedCases.Validator -Required.JsonInput.OriginalProtoFieldName.JsonOutput diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs index 261ac6a7..302f8143 100644 --- a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs @@ -229,16 +229,16 @@ namespace Google.Protobuf [Test] [TestCase("foo_bar", "fooBar")] [TestCase("bananaBanana", "bananaBanana")] - [TestCase("BANANABanana", "bananaBanana")] + [TestCase("BANANABanana", "BANANABanana")] [TestCase("simple", "simple")] - [TestCase("ACTION_AND_ADVENTURE", "actionAndAdventure")] + [TestCase("ACTION_AND_ADVENTURE", "ACTIONANDADVENTURE")] [TestCase("action_and_adventure", "actionAndAdventure")] [TestCase("kFoo", "kFoo")] - [TestCase("HTTPServer", "httpServer")] - [TestCase("CLIENT", "client")] - public void ToCamelCase(string original, string expected) + [TestCase("HTTPServer", "HTTPServer")] + [TestCase("CLIENT", "CLIENT")] + public void ToJsonName(string original, string expected) { - Assert.AreEqual(expected, JsonFormatter.ToCamelCase(original)); + Assert.AreEqual(expected, JsonFormatter.ToJsonName(original)); } [Test] diff --git a/csharp/src/Google.Protobuf.Test/project.json b/csharp/src/Google.Protobuf.Test/project.json index 87b732c9..3a73bf7a 100644 --- a/csharp/src/Google.Protobuf.Test/project.json +++ b/csharp/src/Google.Protobuf.Test/project.json @@ -21,7 +21,7 @@ "dependencies": { "Google.Protobuf": { "target": "project" }, "NUnit": "3.4.0", - "dotnet-test-nunit": "3.4.0-alpha-2", + "dotnet-test-nunit": "3.4.0-alpha-2" }, "testRunner": "nunit", diff --git a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs index eeb0f13a..0fbc5306 100644 --- a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs +++ b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs @@ -61,7 +61,7 @@ namespace Google.Protobuf {
return new InvalidProtocolBufferException(
"While parsing a protocol message, the input ended unexpectedly " +
- "in the middle of a field. This could mean either than the " +
+ "in the middle of a field. This could mean either that the " +
"input has been truncated or that an embedded message " +
"misreported its own length.");
}
diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs index d8a814d9..bb1a361e 100644 --- a/csharp/src/Google.Protobuf/JsonFormatter.cs +++ b/csharp/src/Google.Protobuf/JsonFormatter.cs @@ -248,87 +248,25 @@ namespace Google.Protobuf return !first; } - /// <summary> - /// Camel-case converter with added strictness for field mask formatting. - /// </summary> - /// <exception cref="InvalidOperationException">The field mask is invalid for JSON representation</exception> - private static string ToCamelCaseForFieldMask(string input) + // Converted from java/core/src/main/java/com/google/protobuf/Descriptors.java + internal static string ToJsonName(string name) { - for (int i = 0; i < input.Length; i++) + StringBuilder result = new StringBuilder(name.Length); + bool isNextUpperCase = false; + foreach (char ch in name) { - char c = input[i]; - if (c >= 'A' && c <= 'Z') + if (ch == '_') { - throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {input}"); + isNextUpperCase = true; } - if (c == '_' && i < input.Length - 1) - { - char next = input[i + 1]; - if (next < 'a' || next > 'z') - { - throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {input}"); - } - } - } - return ToCamelCase(input); - } - - // Converted from src/google/protobuf/util/internal/utility.cc ToCamelCase - internal static string ToCamelCase(string input) - { - bool capitalizeNext = false; - bool wasCap = true; - bool isCap = false; - bool firstWord = true; - StringBuilder result = new StringBuilder(input.Length); - - for (int i = 0; i < input.Length; i++, wasCap = isCap) - { - isCap = char.IsUpper(input[i]); - if (input[i] == '_') + else if (isNextUpperCase) { - capitalizeNext = true; - if (result.Length != 0) - { - firstWord = false; - } - continue; - } - else if (firstWord) - { - // Consider when the current character B is capitalized, - // first word ends when: - // 1) following a lowercase: "...aB..." - // 2) followed by a lowercase: "...ABc..." - if (result.Length != 0 && isCap && - (!wasCap || (i + 1 < input.Length && char.IsLower(input[i + 1])))) - { - firstWord = false; - result.Append(input[i]); - } - else - { - result.Append(char.ToLowerInvariant(input[i])); - continue; - } - } - else if (capitalizeNext) - { - capitalizeNext = false; - if (char.IsLower(input[i])) - { - result.Append(char.ToUpperInvariant(input[i])); - continue; - } - else - { - result.Append(input[i]); - continue; - } + result.Append(char.ToUpperInvariant(ch)); + isNextUpperCase = false; } else { - result.Append(char.ToLowerInvariant(input[i])); + result.Append(ch); } } return result.ToString(); diff --git a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs index 6c6f6ee0..ed15d0e1 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs @@ -97,7 +97,7 @@ namespace Google.Protobuf.Reflection // We could trust the generated code and check whether the type of the property is // a MapField, but that feels a tad nasty. this.propertyName = propertyName; - JsonName = Proto.JsonName == "" ? JsonFormatter.ToCamelCase(Proto.Name) : Proto.JsonName; + JsonName = Proto.JsonName == "" ? JsonFormatter.ToJsonName(Proto.Name) : Proto.JsonName; } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs index f9cdb8af..0685c21a 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs @@ -52,7 +52,7 @@ namespace Google.Protobuf.WellKnownTypes /// </remarks> /// <param name="paths">Paths in the field mask</param> /// <param name="diagnosticOnly">Determines the handling of non-normalized values</param> - /// <exception cref="InvalidOperationException">The represented duration is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception> + /// <exception cref="InvalidOperationException">The represented field mask is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception> internal static string ToJson(IList<string> paths, bool diagnosticOnly) { var firstInvalid = paths.FirstOrDefault(p => !ValidatePath(p)); @@ -60,10 +60,10 @@ namespace Google.Protobuf.WellKnownTypes { var writer = new StringWriter(); #if DOTNET35 - var query = paths.Select(JsonFormatter.ToCamelCase); + var query = paths.Select(JsonFormatter.ToJsonName); JsonFormatter.WriteString(writer, string.Join(",", query.ToArray())); #else - JsonFormatter.WriteString(writer, string.Join(",", paths.Select(JsonFormatter.ToCamelCase))); + JsonFormatter.WriteString(writer, string.Join(",", paths.Select(JsonFormatter.ToJsonName))); #endif return writer.ToString(); } @@ -85,9 +85,9 @@ namespace Google.Protobuf.WellKnownTypes } /// <summary> - /// Camel-case converter with added strictness for field mask formatting. + /// Checks whether the given path is valid for a field mask. /// </summary> - /// <exception cref="InvalidOperationException">The field mask is invalid for JSON representation</exception> + /// <returns>true if the path is valid; false otherwise</returns> private static bool ValidatePath(string input) { for (int i = 0; i < input.Length; i++) diff --git a/java/compatibility_tests/v2.5.0/protos/pom.xml b/java/compatibility_tests/v2.5.0/protos/pom.xml index 24447bdc..a22e91ed 100644 --- a/java/compatibility_tests/v2.5.0/protos/pom.xml +++ b/java/compatibility_tests/v2.5.0/protos/pom.xml @@ -28,7 +28,7 @@ <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> - <version>3.3</version> + <version>3.6.0</version> <configuration> <source>1.6</source> <target>1.6</target> diff --git a/java/core/pom.xml b/java/core/pom.xml index 8a83eb4e..cced344e 100644 --- a/java/core/pom.xml +++ b/java/core/pom.xml @@ -92,11 +92,34 @@ <!-- Add the generated sources to the build --> <plugin> - <artifactId>maven-compiler-plugin</artifactId> - <configuration> - <generatedSourcesDirectory>${generated.sources.dir}</generatedSourcesDirectory> - <generatedTestSourcesDirectory>${generated.testsources.dir}</generatedTestSourcesDirectory> - </configuration> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>add-generated-sources</id> + <phase>generate-sources</phase> + <goals> + <goal>add-source</goal> + </goals> + <configuration> + <sources> + <source>${generated.sources.dir}</source> + </sources> + </configuration> + </execution> + <execution> + <id>add-generated-test-sources</id> + <phase>generate-test-sources</phase> + <goals> + <goal>add-test-source</goal> + </goals> + <configuration> + <sources> + <source>${generated.testsources.dir}</source> + </sources> + </configuration> + </execution> + </executions> </plugin> <!-- OSGI bundle configuration --> diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldLite.java b/java/core/src/main/java/com/google/protobuf/MapFieldLite.java index 3c0ad89a..16b3fefe 100644 --- a/java/core/src/main/java/com/google/protobuf/MapFieldLite.java +++ b/java/core/src/main/java/com/google/protobuf/MapFieldLite.java @@ -58,7 +58,7 @@ public final class MapFieldLite<K, V> extends LinkedHashMap<K, V> { } @SuppressWarnings({"rawtypes", "unchecked"}) - private static final MapFieldLite EMPTY_MAP_FIELD = new MapFieldLite(Collections.emptyMap()); + private static final MapFieldLite EMPTY_MAP_FIELD = new MapFieldLite(); static { EMPTY_MAP_FIELD.makeImmutable(); } diff --git a/java/lite/pom.xml b/java/lite/pom.xml index 9862cd94..d7b15097 100644 --- a/java/lite/pom.xml +++ b/java/lite/pom.xml @@ -76,10 +76,38 @@ <!-- Only compile a subset of the files --> <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>add-generated-sources</id> + <phase>generate-sources</phase> + <goals> + <goal>add-source</goal> + </goals> + <configuration> + <sources> + <source>${generated.sources.lite.dir}</source> + </sources> + </configuration> + </execution> + <execution> + <id>add-generated-test-sources</id> + <phase>generate-test-sources</phase> + <goals> + <goal>add-test-source</goal> + </goals> + <configuration> + <sources> + <source>${generated.testsources.lite.dir}</source> + </sources> + </configuration> + </execution> + </executions> + </plugin> + <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> - <generatedSourcesDirectory>${generated.sources.lite.dir}</generatedSourcesDirectory> - <generatedTestSourcesDirectory>${generated.testsources.lite.dir}</generatedTestSourcesDirectory> <includes> <include>**/AbstractMessageLite.java</include> <include>**/AbstractParser.java</include> diff --git a/java/pom.xml b/java/pom.xml index 881473f3..6789e7c1 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -94,7 +94,7 @@ <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> - <version>3.3</version> + <version>3.6.0</version> <configuration> <source>1.6</source> <target>1.6</target> diff --git a/java/util/pom.xml b/java/util/pom.xml index 6b07bcdf..0ccfc848 100644 --- a/java/util/pom.xml +++ b/java/util/pom.xml @@ -79,12 +79,24 @@ </executions> </plugin> + <!-- Add the generated test sources to the build --> <plugin> - <artifactId>maven-compiler-plugin</artifactId> - <configuration> - <!-- Add the generated test sources to the build --> - <generatedTestSourcesDirectory>${generated.testsources.dir}</generatedTestSourcesDirectory> - </configuration> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>add-generated-test-sources</id> + <phase>generate-test-sources</phase> + <goals> + <goal>add-test-source</goal> + </goals> + <configuration> + <sources> + <source>${generated.testsources.dir}</source> + </sources> + </configuration> + </execution> + </executions> </plugin> <!-- Configure the OSGI bundle --> diff --git a/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java b/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java index 3864d38a..9a83d6d3 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java +++ b/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java @@ -48,7 +48,7 @@ public class InvalidProtocolBufferNanoException extends IOException { static InvalidProtocolBufferNanoException truncatedMessage() { return new InvalidProtocolBufferNanoException( "While parsing a protocol message, the input ended unexpectedly " + - "in the middle of a field. This could mean either than the " + + "in the middle of a field. This could mean either that the " + "input has been truncated or that an embedded message " + "misreported its own length."); } diff --git a/js/binary/decoder.js b/js/binary/decoder.js index 41094a36..040cf715 100644 --- a/js/binary/decoder.js +++ b/js/binary/decoder.js @@ -895,11 +895,9 @@ jspb.BinaryDecoder.prototype.readEnum = function() { /** * Reads and parses a UTF-8 encoded unicode string from the stream. - * The code is inspired by maps.vectortown.parse.StreamedDataViewReader, with - * the exception that the implementation here does not get confused if it - * encounters characters longer than three bytes. These characters are ignored - * though, as they are extremely rare: three UTF-8 bytes cover virtually all - * characters in common use (http://en.wikipedia.org/wiki/UTF-8). + * The code is inspired by maps.vectortown.parse.StreamedDataViewReader. + * Supports codepoints from U+0000 up to U+10FFFF. + * (http://en.wikipedia.org/wiki/UTF-8). * @param {number} length The length of the string to read. * @return {string} The decoded string. */ @@ -907,30 +905,45 @@ jspb.BinaryDecoder.prototype.readString = function(length) { var bytes = this.bytes_; var cursor = this.cursor_; var end = cursor + length; - var chars = []; + var codeUnits = []; while (cursor < end) { var c = bytes[cursor++]; if (c < 128) { // Regular 7-bit ASCII. - chars.push(c); + codeUnits.push(c); } else if (c < 192) { // UTF-8 continuation mark. We are out of sync. This // might happen if we attempted to read a character - // with more than three bytes. + // with more than four bytes. continue; } else if (c < 224) { // UTF-8 with two bytes. var c2 = bytes[cursor++]; - chars.push(((c & 31) << 6) | (c2 & 63)); + codeUnits.push(((c & 31) << 6) | (c2 & 63)); } else if (c < 240) { // UTF-8 with three bytes. var c2 = bytes[cursor++]; var c3 = bytes[cursor++]; - chars.push(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + codeUnits.push(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + } else if (c < 248) { // UTF-8 with 4 bytes. + var c2 = bytes[cursor++]; + var c3 = bytes[cursor++]; + var c4 = bytes[cursor++]; + // Characters written on 4 bytes have 21 bits for a codepoint. + // We can't fit that on 16bit characters, so we use surrogates. + var codepoint = ((c & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63); + // Surrogates formula from wikipedia. + // 1. Subtract 0x10000 from codepoint + codepoint -= 0x10000; + // 2. Split this into the high 10-bit value and the low 10-bit value + // 3. Add 0xD800 to the high value to form the high surrogate + // 4. Add 0xDC00 to the low value to form the low surrogate: + var low = (codepoint & 1023) + 0xDC00; + var high = ((codepoint >> 10) & 1023) + 0xD800; + codeUnits.push(high, low) } } - // String.fromCharCode.apply is faster than manually appending characters on // Chrome 25+, and generates no additional cons string garbage. - var result = String.fromCharCode.apply(null, chars); + var result = String.fromCharCode.apply(null, codeUnits); this.cursor_ = cursor; return result; }; diff --git a/js/binary/decoder_test.js b/js/binary/decoder_test.js index ac312648..9f947b99 100644 --- a/js/binary/decoder_test.js +++ b/js/binary/decoder_test.js @@ -209,7 +209,30 @@ describe('binaryDecoderTest', function() { assertEquals(hashC, decoder.readFixedHash64()); assertEquals(hashD, decoder.readFixedHash64()); }); + + /** + * Test encoding and decoding utf-8. + */ + it('testUtf8', function() { + var encoder = new jspb.BinaryEncoder(); + var ascii = "ASCII should work in 3, 2, 1..." + var utf8_two_bytes = "©"; + var utf8_three_bytes = "❄"; + var utf8_four_bytes = "😁"; + + encoder.writeString(ascii); + encoder.writeString(utf8_two_bytes); + encoder.writeString(utf8_three_bytes); + encoder.writeString(utf8_four_bytes); + + var decoder = jspb.BinaryDecoder.alloc(encoder.end()); + + assertEquals(ascii, decoder.readString(ascii.length)); + assertEquals(utf8_two_bytes, decoder.readString(utf8_two_bytes.length)); + assertEquals(utf8_three_bytes, decoder.readString(utf8_three_bytes.length)); + assertEquals(utf8_four_bytes, decoder.readString(utf8_four_bytes.length)); + }); /** * Verifies that misuse of the decoder class triggers assertions. diff --git a/js/binary/encoder.js b/js/binary/encoder.js index c9b0c2ae..d952d714 100644 --- a/js/binary/encoder.js +++ b/js/binary/encoder.js @@ -409,19 +409,36 @@ jspb.BinaryEncoder.prototype.writeFixedHash64 = function(hash) { */ jspb.BinaryEncoder.prototype.writeString = function(value) { var oldLength = this.buffer_.length; - - // UTF16 to UTF8 conversion loop swiped from goog.crypt.stringToUtf8ByteArray. + for (var i = 0; i < value.length; i++) { + var c = value.charCodeAt(i); + if (c < 128) { this.buffer_.push(c); } else if (c < 2048) { this.buffer_.push((c >> 6) | 192); this.buffer_.push((c & 63) | 128); - } else { - this.buffer_.push((c >> 12) | 224); - this.buffer_.push(((c >> 6) & 63) | 128); - this.buffer_.push((c & 63) | 128); + } else if (c < 65536) { + // Look for surrogates + if (c >= 0xD800 && c <= 0xDBFF && i + 1 < value.length) { + var second = value.charCodeAt(i + 1); + if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + c = (c - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; + + this.buffer_.push((c >> 18) | 240); + this.buffer_.push(((c >> 12) & 63 ) | 128); + this.buffer_.push(((c >> 6) & 63) | 128); + this.buffer_.push((c & 63) | 128); + i++; + } + } + else { + this.buffer_.push((c >> 12) | 224); + this.buffer_.push(((c >> 6) & 63) | 128); + this.buffer_.push((c & 63) | 128); + } } } diff --git a/js/package.json b/js/package.json index ee4181ff..d3c77eb6 100644 --- a/js/package.json +++ b/js/package.json @@ -22,5 +22,5 @@ "url": "https://github.com/google/protobuf/tree/master/js" }, "author": "Google Protocol Buffers Team", - "license": "Apache-2.0" + "license" : "BSD-3-Clause" } diff --git a/php/ext/google/protobuf/array.c b/php/ext/google/protobuf/array.c index 215dcd46..e4a88c39 100644 --- a/php/ext/google/protobuf/array.c +++ b/php/ext/google/protobuf/array.c @@ -54,6 +54,16 @@ static zend_function_entry repeated_field_methods[] = { PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC) PHP_ME(RepeatedField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC) PHP_ME(RepeatedField, count, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, getIterator, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static zend_function_entry repeated_field_iter_methods[] = { + PHP_ME(RepeatedFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -70,11 +80,15 @@ static int repeated_field_has_dimension(zval *object, zval *offset TSRMLS_DC); static HashTable *repeated_field_get_gc(zval *object, zval ***table, int *n TSRMLS_DC); +static zend_object_value repeated_field_iter_create(zend_class_entry *ce TSRMLS_DC); +static void repeated_field_iter_free(void *object TSRMLS_DC); + // ----------------------------------------------------------------------------- // RepeatedField creation/desctruction // ----------------------------------------------------------------------------- zend_class_entry* repeated_field_type; +zend_class_entry* repeated_field_iter_type; zend_object_handlers* repeated_field_handlers; void repeated_field_init(TSRMLS_D) { @@ -86,8 +100,8 @@ void repeated_field_init(TSRMLS_D) { repeated_field_type = zend_register_internal_class(&class_type TSRMLS_CC); repeated_field_type->create_object = repeated_field_create; - zend_class_implements(repeated_field_type TSRMLS_CC, 2, spl_ce_ArrayAccess, - spl_ce_Countable); + zend_class_implements(repeated_field_type TSRMLS_CC, 3, spl_ce_ArrayAccess, + zend_ce_aggregate, spl_ce_Countable); repeated_field_handlers = PEMALLOC(zend_object_handlers); memcpy(repeated_field_handlers, zend_get_std_object_handlers(), @@ -386,3 +400,112 @@ PHP_METHOD(RepeatedField, count) { RETURN_LONG(zend_hash_num_elements(HASH_OF(intern->array))); } + +/** + * Return the beginning iterator. + * This will also be called for: foreach($arr) + * @return object Beginning iterator. + */ +PHP_METHOD(RepeatedField, getIterator) { + zval *iter_php = NULL; + MAKE_STD_ZVAL(iter_php); + Z_TYPE_P(iter_php) = IS_OBJECT; + Z_OBJVAL_P(iter_php) = repeated_field_iter_type->create_object( + repeated_field_iter_type TSRMLS_CC); + + RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC); + RepeatedFieldIter *iter = zend_object_store_get_object(iter_php TSRMLS_CC); + iter->repeated_field = intern; + iter->position = 0; + + RETURN_ZVAL(iter_php, 1, 1); +} + +// ----------------------------------------------------------------------------- +// RepeatedFieldIter creation/desctruction +// ----------------------------------------------------------------------------- + +void repeated_field_iter_init(TSRMLS_D) { + zend_class_entry class_type; + const char* class_name = "Google\\Protobuf\\Internal\\RepeatedFieldIter"; + INIT_CLASS_ENTRY_EX(class_type, class_name, strlen(class_name), + repeated_field_iter_methods); + + repeated_field_iter_type = + zend_register_internal_class(&class_type TSRMLS_CC); + repeated_field_iter_type->create_object = repeated_field_iter_create; + + zend_class_implements(repeated_field_iter_type TSRMLS_CC, 1, + zend_ce_iterator); +} + +static zend_object_value repeated_field_iter_create( + zend_class_entry *ce TSRMLS_DC) { + zend_object_value retval = {0}; + RepeatedFieldIter *intern; + + intern = emalloc(sizeof(RepeatedFieldIter)); + memset(intern, 0, sizeof(RepeatedFieldIter)); + + zend_object_std_init(&intern->std, ce TSRMLS_CC); + object_properties_init(&intern->std, ce); + + intern->repeated_field = NULL; + intern->position = 0; + + retval.handle = zend_objects_store_put( + intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, + (zend_objects_free_object_storage_t)repeated_field_iter_free, + NULL TSRMLS_CC); + retval.handlers = zend_get_std_object_handlers(); + + return retval; +} + +static void repeated_field_iter_free(void *object TSRMLS_DC) { + RepeatedFieldIter *intern = object; + zend_object_std_dtor(&intern->std TSRMLS_CC); + efree(object); +} + +// ----------------------------------------------------------------------------- +// PHP RepeatedFieldIter Methods +// ----------------------------------------------------------------------------- + +PHP_METHOD(RepeatedFieldIter, rewind) { + RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC); + intern->position = 0; +} + +PHP_METHOD(RepeatedFieldIter, current) { + RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC); + RepeatedField *repeated_field = intern->repeated_field; + + long index; + void *memory; + + HashTable *table = HASH_OF(repeated_field->array); + + if (zend_hash_index_find(table, intern->position, (void **)&memory) == + FAILURE) { + zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index); + return; + } + native_slot_get(repeated_field->type, memory, return_value_ptr TSRMLS_CC); +} + +PHP_METHOD(RepeatedFieldIter, key) { + RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC); + RETURN_LONG(intern->position); +} + +PHP_METHOD(RepeatedFieldIter, next) { + RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC); + ++intern->position; +} + +PHP_METHOD(RepeatedFieldIter, valid) { + RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC); + RETURN_BOOL(zend_hash_num_elements(HASH_OF(intern->repeated_field->array)) > + intern->position); +} diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c index 019bca29..ea85b999 100644 --- a/php/ext/google/protobuf/protobuf.c +++ b/php/ext/google/protobuf/protobuf.c @@ -156,6 +156,7 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) { static PHP_MINIT_FUNCTION(protobuf) { map_field_init(TSRMLS_C); repeated_field_init(TSRMLS_C); + repeated_field_iter_init(TSRMLS_C); gpb_type_init(TSRMLS_C); message_init(TSRMLS_C); descriptor_pool_init(TSRMLS_C); diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h index 8a1d9261..fb5879dc 100644 --- a/php/ext/google/protobuf/protobuf.h +++ b/php/ext/google/protobuf/protobuf.h @@ -39,6 +39,9 @@ #define PHP_PROTOBUF_EXTNAME "protobuf" #define PHP_PROTOBUF_VERSION "3.1.0a1" +#define MAX_LENGTH_OF_INT64 20 +#define SIZEOF_INT64 8 + // ----------------------------------------------------------------------------- // Forward Declaration // ---------------------------------------------------------------------------- @@ -51,6 +54,7 @@ struct MessageField; struct MessageHeader; struct MessageLayout; struct RepeatedField; +struct RepeatedFieldIter; struct MapField; typedef struct DescriptorPool DescriptorPool; @@ -61,6 +65,7 @@ typedef struct MessageField MessageField; typedef struct MessageHeader MessageHeader; typedef struct MessageLayout MessageLayout; typedef struct RepeatedField RepeatedField; +typedef struct RepeatedFieldIter RepeatedFieldIter; typedef struct MapField MapField; // ----------------------------------------------------------------------------- @@ -77,6 +82,7 @@ void descriptor_pool_init(TSRMLS_D); void gpb_type_init(TSRMLS_D); void map_field_init(TSRMLS_D); void repeated_field_init(TSRMLS_D); +void repeated_field_iter_init(TSRMLS_D); void util_init(TSRMLS_D); void message_init(TSRMLS_D); @@ -366,6 +372,12 @@ struct RepeatedField { // (for message field only). }; +struct RepeatedFieldIter { + zend_object std; + RepeatedField* repeated_field; + long position; +}; + void repeated_field_create_with_type(zend_class_entry* ce, const upb_fielddef* field, zval** repeated_field TSRMLS_DC); @@ -383,6 +395,13 @@ PHP_METHOD(RepeatedField, offsetGet); PHP_METHOD(RepeatedField, offsetSet); PHP_METHOD(RepeatedField, offsetUnset); PHP_METHOD(RepeatedField, count); +PHP_METHOD(RepeatedField, getIterator); + +PHP_METHOD(RepeatedFieldIter, rewind); +PHP_METHOD(RepeatedFieldIter, current); +PHP_METHOD(RepeatedFieldIter, key); +PHP_METHOD(RepeatedFieldIter, next); +PHP_METHOD(RepeatedFieldIter, valid); // ----------------------------------------------------------------------------- // Oneof Field. diff --git a/php/ext/google/protobuf/storage.c b/php/ext/google/protobuf/storage.c index e94aa319..1d25a91b 100644 --- a/php/ext/google/protobuf/storage.c +++ b/php/ext/google/protobuf/storage.c @@ -174,11 +174,31 @@ CASE(FLOAT, DOUBLE, float) CASE(DOUBLE, DOUBLE, double) CASE(BOOL, BOOL, int8_t) CASE(INT32, LONG, int32_t) -CASE(INT64, LONG, int64_t) -CASE(UINT64, LONG, uint64_t) CASE(ENUM, LONG, uint32_t) #undef CASE + +#if SIZEOF_LONG == 4 +#define CASE(upb_type, c_type) \ + case UPB_TYPE_##upb_type: { \ + SEPARATE_ZVAL_IF_NOT_REF(cache); \ + char buffer[MAX_LENGTH_OF_INT64]; \ + sprintf(buffer, "%lld", DEREF(memory, c_type)); \ + ZVAL_STRING(*cache, buffer, 1); \ + return; \ + } +#else +#define CASE(upb_type, c_type) \ + case UPB_TYPE_##upb_type: { \ + SEPARATE_ZVAL_IF_NOT_REF(cache); \ + ZVAL_LONG(*cache, DEREF(memory, c_type)); \ + return; \ + } +#endif +CASE(UINT64, uint64_t) +CASE(INT64, int64_t) +#undef CASE + case UPB_TYPE_UINT32: { // Prepend bit-1 for negative numbers, so that uint32 value will be // consistent on both 32-bit and 64-bit architectures. diff --git a/php/ext/google/protobuf/type_check.c b/php/ext/google/protobuf/type_check.c index c215d72e..d12d0025 100644 --- a/php/ext/google/protobuf/type_check.c +++ b/php/ext/google/protobuf/type_check.c @@ -34,6 +34,7 @@ #include "utf8.h" static zend_class_entry* util_type; +static const char int64_min_digits[] = "9223372036854775808"; ZEND_BEGIN_ARG_INFO_EX(arg_check_optional, 0, 0, 1) ZEND_ARG_INFO(1, val) @@ -78,8 +79,128 @@ void util_init(TSRMLS_D) { // Type checking/conversion. // ----------------------------------------------------------------------------- +// This is modified from is_numeric_string in zend_operators.h. The behavior of +// this function is the same as is_numeric_string, except that this takes +// int64_t as input instead of long. +static zend_uchar convert_numeric_string( + const char *str, int length, int64_t *lval, double *dval) { + const char *ptr; + int base = 10, digits = 0, dp_or_e = 0; + double local_dval = 0.0; + zend_uchar type; + + if (length == 0) { + return IS_NULL; + } + + while (*str == ' ' || *str == '\t' || *str == '\n' || + *str == '\r' || *str == '\v' || *str == '\f') { + str++; + length--; + } + ptr = str; + + if (*ptr == '-' || *ptr == '+') { + ptr++; + } + + if (ZEND_IS_DIGIT(*ptr)) { + // Handle hex numbers + // str is used instead of ptr to disallow signs and keep old behavior. + if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) { + base = 16; + ptr += 2; + } + + // Skip any leading 0s. + while (*ptr == '0') { + ptr++; + } + + // Count the number of digits. If a decimal point/exponent is found, + // it's a double. Otherwise, if there's a dval or no need to check for + // a full match, stop when there are too many digits for a int64 */ + for (type = IS_LONG; + !(digits >= MAX_LENGTH_OF_INT64 && dval); + digits++, ptr++) { +check_digits: + if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) { + continue; + } else if (base == 10) { + if (*ptr == '.' && dp_or_e < 1) { + goto process_double; + } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) { + const char *e = ptr + 1; + + if (*e == '-' || *e == '+') { + ptr = e++; + } + if (ZEND_IS_DIGIT(*e)) { + goto process_double; + } + } + } + break; + } + + if (base == 10) { + if (digits >= MAX_LENGTH_OF_INT64) { + dp_or_e = -1; + goto process_double; + } + } else if (!(digits < SIZEOF_INT64 * 2 || + (digits == SIZEOF_INT64 * 2 && ptr[-digits] <= '7'))) { + if (dval) { + local_dval = zend_hex_strtod(str, &ptr); + } + type = IS_DOUBLE; + } + } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) { +process_double: + type = IS_DOUBLE; + + // If there's a dval, do the conversion; else continue checking + // the digits if we need to check for a full match. + if (dval) { + local_dval = zend_strtod(str, &ptr); + } else if (dp_or_e != -1) { + dp_or_e = (*ptr++ == '.') ? 1 : 2; + goto check_digits; + } + } else { + return IS_NULL; + } + if (ptr != str + length) { + zend_error(E_NOTICE, "A non well formed numeric value encountered"); + return 0; + } + + if (type == IS_LONG) { + if (digits == MAX_LENGTH_OF_INT64 - 1) { + int cmp = strcmp(&ptr[-digits], int64_min_digits); + + if (!(cmp < 0 || (cmp == 0 && *str == '-'))) { + if (dval) { + *dval = zend_strtod(str, NULL); + } + + return IS_DOUBLE; + } + } + if (lval) { + *lval = strtoll(str, NULL, base); + } + return IS_LONG; + } else { + if (dval) { + *dval = local_dval; + } + return IS_DOUBLE; + } +} + #define CONVERT_TO_INTEGER(type) \ - static bool convert_long_to_##type(long val, type##_t* type##_value) { \ + static bool convert_int64_to_##type(int64_t val, type##_t* type##_value) { \ *type##_value = (type##_t)val; \ return true; \ } \ @@ -91,15 +212,15 @@ void util_init(TSRMLS_D) { \ static bool convert_string_to_##type(const char* val, int len, \ type##_t* type##_value) { \ - long lval; \ + int64_t lval; \ double dval; \ \ - switch (is_numeric_string(val, len, &lval, &dval, 0)) { \ + switch (convert_numeric_string(val, len, &lval, &dval)) { \ case IS_DOUBLE: { \ return convert_double_to_##type(dval, type##_value); \ } \ case IS_LONG: { \ - return convert_long_to_##type(lval, type##_value); \ + return convert_int64_to_##type(lval, type##_value); \ } \ default: \ zend_error(E_USER_ERROR, \ @@ -111,7 +232,7 @@ void util_init(TSRMLS_D) { bool protobuf_convert_to_##type(zval* from, type##_t* to) { \ switch (Z_TYPE_P(from)) { \ case IS_LONG: { \ - return convert_long_to_##type(Z_LVAL_P(from), to); \ + return convert_int64_to_##type(Z_LVAL_P(from), to); \ } \ case IS_DOUBLE: { \ return convert_double_to_##type(Z_DVAL_P(from), to); \ @@ -137,7 +258,7 @@ CONVERT_TO_INTEGER(uint64); #undef CONVERT_TO_INTEGER #define CONVERT_TO_FLOAT(type) \ - static bool convert_long_to_##type(long val, type* type##_value) { \ + static bool convert_int64_to_##type(int64_t val, type* type##_value) { \ *type##_value = (type)val; \ return true; \ } \ @@ -149,10 +270,10 @@ CONVERT_TO_INTEGER(uint64); \ static bool convert_string_to_##type(const char* val, int len, \ type* type##_value) { \ - long lval; \ + int64_t lval; \ double dval; \ \ - switch (is_numeric_string(val, len, &lval, &dval, 0)) { \ + switch (convert_numeric_string(val, len, &lval, &dval)) { \ case IS_DOUBLE: { \ *type##_value = (type)dval; \ return true; \ @@ -171,7 +292,7 @@ CONVERT_TO_INTEGER(uint64); bool protobuf_convert_to_##type(zval* from, type* to) { \ switch (Z_TYPE_P(from)) { \ case IS_LONG: { \ - return convert_long_to_##type(Z_LVAL_P(from), to); \ + return convert_int64_to_##type(Z_LVAL_P(from), to); \ } \ case IS_DOUBLE: { \ return convert_double_to_##type(Z_DVAL_P(from), to); \ diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php index 38513e91..3d1f1598 100644 --- a/php/src/Google/Protobuf/Internal/Message.php +++ b/php/src/Google/Protobuf/Internal/Message.php @@ -125,6 +125,16 @@ class Message $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()]; $oneof_name = $oneof->getName(); $this->$oneof_name = new OneofField($oneof); + } else if ($field->getLabel() === GPBLabel::OPTIONAL && + PHP_INT_SIZE == 4) { + switch ($field->getType()) { + case GPBType::INT64: + case GPBType::UINT64: + case GPBType::FIXED64: + case GPBType::SFIXED64: + case GPBType::SINT64: + $this->$setter("0"); + } } } } diff --git a/php/tests/array_test.php b/php/tests/array_test.php index a118b54c..a79a08bc 100644 --- a/php/tests/array_test.php +++ b/php/tests/array_test.php @@ -65,6 +65,17 @@ class RepeatedFieldTest extends PHPUnit_Framework_TestCase $this->assertSame(3, $arr[6]); $arr [7]= MAX_INT32_STRING; $this->assertSame(MAX_INT32, $arr[7]); + + // Test foreach. + $arr = new RepeatedField(GPBType::INT32); + for ($i = 0; $i < 3; $i++) { + $arr []= $i; + } + $i = 0; + foreach ($arr as $val) { + $this->assertSame($i++, $val); + } + $this->assertSame(3, $i); } /** diff --git a/php/tests/test.sh b/php/tests/test.sh index 888e93eb..fe3dc7f6 100755 --- a/php/tests/test.sh +++ b/php/tests/test.sh @@ -7,7 +7,8 @@ pushd ../ext/google/protobuf/ make clean set -e -phpize && ./configure --enable-debug CFLAGS='-g -O0' && make +# Add following in configure for debug: --enable-debug CFLAGS='-g -O0' +phpize && ./configure && make popd tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php ) diff --git a/php/tests/test_base.php b/php/tests/test_base.php index 49886050..d461f0f7 100644 --- a/php/tests/test_base.php +++ b/php/tests/test_base.php @@ -75,20 +75,28 @@ class TestBase extends PHPUnit_Framework_TestCase { $this->assertSame(0, $m->getOptionalInt32()); $this->assertSame(0, $m->getOptionalUint32()); - $this->assertSame(0, $m->getOptionalInt64()); - $this->assertSame(0, $m->getOptionalUint64()); $this->assertSame(0, $m->getOptionalSint32()); - $this->assertSame(0, $m->getOptionalSint64()); $this->assertSame(0, $m->getOptionalFixed32()); - $this->assertSame(0, $m->getOptionalFixed64()); $this->assertSame(0, $m->getOptionalSfixed32()); - $this->assertSame(0, $m->getOptionalSfixed64()); $this->assertSame(0.0, $m->getOptionalFloat()); $this->assertSame(0.0, $m->getOptionalDouble()); $this->assertSame(false, $m->getOptionalBool()); $this->assertSame('', $m->getOptionalString()); $this->assertSame('', $m->getOptionalBytes()); $this->assertNull($m->getOptionalMessage()); + if (PHP_INT_SIZE == 4) { + $this->assertSame("0", $m->getOptionalInt64()); + $this->assertSame("0", $m->getOptionalUint64()); + $this->assertSame("0", $m->getOptionalSint64()); + $this->assertSame("0", $m->getOptionalFixed64()); + $this->assertSame("0", $m->getOptionalSfixed64()); + } else { + $this->assertSame(0, $m->getOptionalInt64()); + $this->assertSame(0, $m->getOptionalUint64()); + $this->assertSame(0, $m->getOptionalSint64()); + $this->assertSame(0, $m->getOptionalFixed64()); + $this->assertSame(0, $m->getOptionalSfixed64()); + } } // This test is to avoid the warning of no test by php unit. diff --git a/src/Makefile.am b/src/Makefile.am index faee6d96..8d9e07ab 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -61,117 +61,117 @@ CLEANFILES = $(protoc_outputs) unittest_proto_middleman \ 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_atomicword_compat.h \ - google/protobuf/stubs/atomicops_internals_generic_gcc.h \ - google/protobuf/stubs/atomicops_internals_macosx.h \ - google/protobuf/stubs/atomicops_internals_mips_gcc.h \ - google/protobuf/stubs/atomicops_internals_pnacl.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 \ - google/protobuf/stubs/common.h \ - google/protobuf/stubs/fastmem.h \ - google/protobuf/stubs/hash.h \ - google/protobuf/stubs/logging.h \ - google/protobuf/stubs/macros.h \ - google/protobuf/stubs/mutex.h \ - 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 \ - google/protobuf/stubs/stringpiece.h \ - google/protobuf/stubs/template_util.h \ - google/protobuf/stubs/type_traits.h \ - google/protobuf/any.pb.h \ - google/protobuf/api.pb.h \ - google/protobuf/any.h \ - google/protobuf/arena.h \ - google/protobuf/arenastring.h \ - google/protobuf/descriptor_database.h \ - google/protobuf/descriptor.h \ - google/protobuf/descriptor.pb.h \ - google/protobuf/duration.pb.h \ - google/protobuf/dynamic_message.h \ - google/protobuf/empty.pb.h \ - google/protobuf/extension_set.h \ - google/protobuf/field_mask.pb.h \ - google/protobuf/generated_enum_reflection.h \ - google/protobuf/generated_enum_util.h \ - google/protobuf/generated_message_reflection.h \ - google/protobuf/generated_message_util.h \ - google/protobuf/has_bits.h \ - google/protobuf/map_entry.h \ - google/protobuf/map_entry_lite.h \ - google/protobuf/map_field.h \ - google/protobuf/map_field_inl.h \ - google/protobuf/map_field_lite.h \ - google/protobuf/map.h \ - google/protobuf/map_type_handler.h \ - google/protobuf/message.h \ - google/protobuf/message_lite.h \ - google/protobuf/metadata.h \ - google/protobuf/reflection.h \ - google/protobuf/reflection_ops.h \ - google/protobuf/repeated_field.h \ - google/protobuf/service.h \ - google/protobuf/source_context.pb.h \ - google/protobuf/struct.pb.h \ - google/protobuf/text_format.h \ - google/protobuf/timestamp.pb.h \ - google/protobuf/type.pb.h \ - google/protobuf/unknown_field_set.h \ - google/protobuf/wire_format.h \ - google/protobuf/wire_format_lite.h \ - google/protobuf/wire_format_lite_inl.h \ - google/protobuf/wrappers.pb.h \ - google/protobuf/io/coded_stream.h \ - $(GZHEADERS) \ - google/protobuf/io/printer.h \ - google/protobuf/io/strtod.h \ - google/protobuf/io/tokenizer.h \ - google/protobuf/io/zero_copy_stream.h \ - google/protobuf/io/zero_copy_stream_impl.h \ - google/protobuf/io/zero_copy_stream_impl_lite.h \ - google/protobuf/compiler/code_generator.h \ - google/protobuf/compiler/command_line_interface.h \ - google/protobuf/compiler/importer.h \ - google/protobuf/compiler/parser.h \ - google/protobuf/compiler/plugin.h \ - google/protobuf/compiler/plugin.pb.h \ - google/protobuf/compiler/cpp/cpp_generator.h \ - google/protobuf/compiler/csharp/csharp_generator.h \ - google/protobuf/compiler/csharp/csharp_names.h \ - google/protobuf/compiler/java/java_generator.h \ - google/protobuf/compiler/java/java_names.h \ - google/protobuf/compiler/javanano/javanano_generator.h \ - google/protobuf/compiler/js/js_generator.h \ - google/protobuf/compiler/objectivec/objectivec_generator.h \ - google/protobuf/compiler/objectivec/objectivec_helpers.h \ - google/protobuf/compiler/php/php_generator.h \ - google/protobuf/compiler/python/python_generator.h \ - google/protobuf/compiler/ruby/ruby_generator.h \ - google/protobuf/util/type_resolver.h \ - google/protobuf/util/field_comparator.h \ - google/protobuf/util/field_mask_util.h \ - google/protobuf/util/json_util.h \ - google/protobuf/util/time_util.h \ - google/protobuf/util/type_resolver_util.h \ +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_atomicword_compat.h \ + google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h \ + google/protobuf/stubs/atomicops_internals_generic_gcc.h \ + google/protobuf/stubs/atomicops_internals_macosx.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 \ + google/protobuf/stubs/common.h \ + google/protobuf/stubs/fastmem.h \ + google/protobuf/stubs/hash.h \ + google/protobuf/stubs/logging.h \ + google/protobuf/stubs/macros.h \ + google/protobuf/stubs/mutex.h \ + 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 \ + google/protobuf/stubs/stringpiece.h \ + google/protobuf/stubs/template_util.h \ + google/protobuf/stubs/type_traits.h \ + google/protobuf/any.pb.h \ + google/protobuf/api.pb.h \ + google/protobuf/any.h \ + google/protobuf/arena.h \ + google/protobuf/arenastring.h \ + google/protobuf/descriptor_database.h \ + google/protobuf/descriptor.h \ + google/protobuf/descriptor.pb.h \ + google/protobuf/duration.pb.h \ + google/protobuf/dynamic_message.h \ + google/protobuf/empty.pb.h \ + google/protobuf/extension_set.h \ + google/protobuf/field_mask.pb.h \ + google/protobuf/generated_enum_reflection.h \ + google/protobuf/generated_enum_util.h \ + google/protobuf/generated_message_reflection.h \ + google/protobuf/generated_message_util.h \ + google/protobuf/has_bits.h \ + google/protobuf/map_entry.h \ + google/protobuf/map_entry_lite.h \ + google/protobuf/map_field.h \ + google/protobuf/map_field_inl.h \ + google/protobuf/map_field_lite.h \ + google/protobuf/map.h \ + google/protobuf/map_type_handler.h \ + google/protobuf/message.h \ + google/protobuf/message_lite.h \ + google/protobuf/metadata.h \ + google/protobuf/reflection.h \ + google/protobuf/reflection_ops.h \ + google/protobuf/repeated_field.h \ + google/protobuf/service.h \ + google/protobuf/source_context.pb.h \ + google/protobuf/struct.pb.h \ + google/protobuf/text_format.h \ + google/protobuf/timestamp.pb.h \ + google/protobuf/type.pb.h \ + google/protobuf/unknown_field_set.h \ + google/protobuf/wire_format.h \ + google/protobuf/wire_format_lite.h \ + google/protobuf/wire_format_lite_inl.h \ + google/protobuf/wrappers.pb.h \ + google/protobuf/io/coded_stream.h \ + $(GZHEADERS) \ + google/protobuf/io/printer.h \ + google/protobuf/io/strtod.h \ + google/protobuf/io/tokenizer.h \ + google/protobuf/io/zero_copy_stream.h \ + google/protobuf/io/zero_copy_stream_impl.h \ + google/protobuf/io/zero_copy_stream_impl_lite.h \ + google/protobuf/compiler/code_generator.h \ + google/protobuf/compiler/command_line_interface.h \ + google/protobuf/compiler/importer.h \ + google/protobuf/compiler/parser.h \ + google/protobuf/compiler/plugin.h \ + google/protobuf/compiler/plugin.pb.h \ + google/protobuf/compiler/cpp/cpp_generator.h \ + google/protobuf/compiler/csharp/csharp_generator.h \ + google/protobuf/compiler/csharp/csharp_names.h \ + google/protobuf/compiler/java/java_generator.h \ + google/protobuf/compiler/java/java_names.h \ + google/protobuf/compiler/javanano/javanano_generator.h \ + google/protobuf/compiler/js/js_generator.h \ + google/protobuf/compiler/objectivec/objectivec_generator.h \ + google/protobuf/compiler/objectivec/objectivec_helpers.h \ + google/protobuf/compiler/php/php_generator.h \ + google/protobuf/compiler/python/python_generator.h \ + google/protobuf/compiler/ruby/ruby_generator.h \ + google/protobuf/util/type_resolver.h \ + google/protobuf/util/field_comparator.h \ + google/protobuf/util/field_mask_util.h \ + google/protobuf/util/json_util.h \ + google/protobuf/util/time_util.h \ + google/protobuf/util/type_resolver_util.h \ google/protobuf/util/message_differencer.h lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index f05277ed..87066507 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -83,6 +83,7 @@ inline void arena_free(void* object, size_t size) { #if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) ::operator delete(object, size); #else + (void)size; ::operator delete(object); #endif } diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc index 58597b4c..47ecc537 100755 --- a/src/google/protobuf/compiler/js/js_generator.cc +++ b/src/google/protobuf/compiler/js/js_generator.cc @@ -28,7 +28,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "google/protobuf/compiler/js/js_generator.h" +#include <google/protobuf/compiler/js/js_generator.h> #include <assert.h> #include <algorithm> diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index d3c3b1f0..88455669 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -244,7 +244,7 @@ class LIBPROTOBUF_EXPORT MessageLite { // // ByteSize() is generally linear in the number of fields defined for the // proto. - virtual int ByteSize() const { return ByteSizeLong(); } + virtual int ByteSize() const { return static_cast<int>(ByteSizeLong()); } virtual size_t ByteSizeLong() const; // Serializes the message without recomputing the size. The message must diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 0a41495f..6ede0e1a 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -681,17 +681,7 @@ inline const Message& GenericTypeHandler<Message>::default_instance() { return *null; } - -// HACK: If a class is declared as DLL-exported in MSVC, it insists on -// generating copies of all its methods -- even inline ones -- to include -// in the DLL. But SpaceUsed() calls StringSpaceUsedExcludingSelf() which -// isn't in the lite library, therefore the lite library cannot link if -// StringTypeHandler is exported. So, we factor out StringTypeHandlerBase, -// export that, then make StringTypeHandler be a subclass which is NOT -// exported. -// TODO(kenton): Now that StringSpaceUsedExcludingSelf() is in the lite -// library, this can be cleaned up. -class LIBPROTOBUF_EXPORT StringTypeHandlerBase { +class LIBPROTOBUF_EXPORT StringTypeHandler { public: typedef string Type; @@ -718,10 +708,6 @@ class LIBPROTOBUF_EXPORT StringTypeHandlerBase { static inline const Type& default_instance() { return ::google::protobuf::internal::GetEmptyString(); } -}; - -class StringTypeHandler : public StringTypeHandlerBase { - public: static int SpaceUsed(const string& value) { return static_cast<int>(sizeof(value)) + StringSpaceUsedExcludingSelf(value); } diff --git a/src/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h index 9b3d1e6b..10a71ed4 100644 --- a/src/google/protobuf/stubs/atomicops.h +++ b/src/google/protobuf/stubs/atomicops.h @@ -196,14 +196,22 @@ Atomic64 Release_Load(volatile const Atomic64* ptr); // Apple. #elif defined(GOOGLE_PROTOBUF_OS_APPLE) +#if __has_feature(cxx_atomic) || _GNUC_VER >= 407 +#include <google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h> +#else // __has_feature(cxx_atomic) || _GNUC_VER >= 407 #include <google/protobuf/stubs/atomicops_internals_macosx.h> +#endif // __has_feature(cxx_atomic) || _GNUC_VER >= 407 // GCC. #elif defined(__GNUC__) #if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64) #include <google/protobuf/stubs/atomicops_internals_x86_gcc.h> #elif defined(GOOGLE_PROTOBUF_ARCH_ARM) && defined(__linux__) +#if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)) +#include <google/protobuf/stubs/atomicops_internals_generic_gcc.h> +#else #include <google/protobuf/stubs/atomicops_internals_arm_gcc.h> +#endif #elif defined(GOOGLE_PROTOBUF_ARCH_AARCH64) #include <google/protobuf/stubs/atomicops_internals_arm64_gcc.h> #elif defined(GOOGLE_PROTOBUF_ARCH_ARM_QNX) @@ -213,7 +221,7 @@ Atomic64 Release_Load(volatile const Atomic64* ptr); #elif defined(GOOGLE_PROTOBUF_ARCH_POWER) #include <google/protobuf/stubs/atomicops_internals_power.h> #elif defined(__native_client__) -#include <google/protobuf/stubs/atomicops_internals_pnacl.h> +#include <google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h> #elif defined(GOOGLE_PROTOBUF_ARCH_PPC) #include <google/protobuf/stubs/atomicops_internals_ppc_gcc.h> #elif (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)) diff --git a/src/google/protobuf/stubs/atomicops_internals_pnacl.h b/src/google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h index 3b314fd0..7bc584eb 100644 --- a/src/google/protobuf/stubs/atomicops_internals_pnacl.h +++ b/src/google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h @@ -30,8 +30,8 @@ // This file is an internal atomic implementation, use atomicops.h instead. -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_C11_ATOMIC_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_C11_ATOMIC_H_ #include <atomic> @@ -228,4 +228,4 @@ inline Atomic64 Release_Load(volatile const Atomic64* ptr) { } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_C11_ATOMIC_H_ diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc index 150f3cf1..df0dbe1b 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -1024,8 +1024,11 @@ bool ProtoStreamObjectSource::IsMap( // TODO(xiaofeng): Unify option names. return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE && (GetBoolOptionOrDefault(field_type->options(), - "google.protobuf.MessageOptions.map_entry", false) || - GetBoolOptionOrDefault(field_type->options(), "map_entry", false)); + "google.protobuf.MessageOptions.map_entry", + false) || + GetBoolOptionOrDefault(field_type->options(), "map_entry", false) || + GetBoolOptionOrDefault(field_type->options(), + "proto2.MessageOptions.map_entry", false)); } std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos( @@ -1119,3 +1122,4 @@ const string FormatNanos(uint32 nanos) { } // namespace util } // namespace protobuf } // namespace google + diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc index 6c15e862..c37e671c 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -1240,8 +1240,11 @@ bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) { // TODO(xiaofeng): Unify option names. return GetBoolOptionOrDefault(field_type->options(), - "google.protobuf.MessageOptions.map_entry", false) || - GetBoolOptionOrDefault(field_type->options(), "map_entry", false); + "google.protobuf.MessageOptions.map_entry", + false) || + GetBoolOptionOrDefault(field_type->options(), "map_entry", false) || + GetBoolOptionOrDefault(field_type->options(), + "proto2.MessageOptions.map_entry", false); } bool ProtoStreamObjectWriter::IsAny(const google::protobuf::Field& field) { @@ -1266,3 +1269,4 @@ bool ProtoStreamObjectWriter::IsStructListValue( } // namespace util } // namespace protobuf } // namespace google + diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc index 9aab3481..05328255 100644 --- a/src/google/protobuf/util/internal/utility.cc +++ b/src/google/protobuf/util/internal/utility.cc @@ -356,15 +356,23 @@ bool IsValidBoolString(const string& bool_string) { bool IsMap(const google::protobuf::Field& field, const google::protobuf::Type& type) { - return (field.cardinality() == - google::protobuf::Field_Cardinality_CARDINALITY_REPEATED && - GetBoolOptionOrDefault(type.options(), - "google.protobuf.MessageOptions.map_entry", false)); + return ( + field.cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED && + (GetBoolOptionOrDefault( + type.options(), "google.protobuf.MessageOptions.map_entry", false) || + GetBoolOptionOrDefault(type.options(), "proto2.MessageOptions.map_entry", + false))); } bool IsMessageSetWireFormat(const google::protobuf::Type& type) { - return GetBoolOptionOrDefault( - type.options(), "google.protobuf.MessageOptions.message_set_wire_format", false); + return ( + GetBoolOptionOrDefault( + type.options(), + "google.protobuf.MessageOptions.message_set_wire_format", false) || + GetBoolOptionOrDefault(type.options(), + "proto2.MessageOptions.message_set_wire_format", + false)); } string DoubleAsString(double value) { @@ -404,3 +412,4 @@ bool SafeStrToFloat(StringPiece str, float* value) { } // namespace util } // namespace protobuf } // namespace google + @@ -393,6 +393,12 @@ build_php5.5_32() { ./vendor/bin/phpunit } +build_php5.5_c_32() { + use_php_bc 5.5 + wget https://phar.phpunit.de/phpunit-old.phar -O /usr/bin/phpunit + cd php/tests && /bin/bash ./test.sh && cd ../.. +} + build_php5.6() { use_php 5.6 rm -rf vendor @@ -408,7 +414,8 @@ build_php5.6_c() { build_php5.6_mac() { # Install PHP curl -s https://php-osx.liip.ch/install.sh | bash -s 5.6 - export PATH="/usr/local/php5-5.6.25-20160831-101628/bin:$PATH" + PHP_FOLDER=`find /usr/local -type d -name "php5-5.6*"` # The folder name may change upon time + export PATH="$PHP_FOLDER/bin:$PATH" # Install phpunit curl https://phar.phpunit.de/phpunit.phar -L -o phpunit.phar @@ -448,6 +455,7 @@ build_php_all() { build_php_all_32() { build_php5.5_32 + build_php5.5_c_32 } # Note: travis currently does not support testing more than one language so the |