Merge nano proto into protobuf repository.

Source: https://android.googlesource.com/platform/external/protobuf.git
This commit is contained in:
Feng Xiao 2014-11-19 17:14:29 -08:00
commit 95c25918aa
57 changed files with 15021 additions and 0 deletions

486
Android.mk Normal file
View File

@ -0,0 +1,486 @@
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
LOCAL_PATH := $(call my-dir)
IGNORED_WARNINGS := -Wno-sign-compare -Wno-unused-parameter -Wno-sign-promo
CC_LITE_SRC_FILES := \
src/google/protobuf/stubs/common.cc \
src/google/protobuf/stubs/once.cc \
src/google/protobuf/stubs/hash.cc \
src/google/protobuf/stubs/hash.h \
src/google/protobuf/stubs/map-util.h \
src/google/protobuf/stubs/stl_util-inl.h \
src/google/protobuf/extension_set.cc \
src/google/protobuf/generated_message_util.cc \
src/google/protobuf/message_lite.cc \
src/google/protobuf/repeated_field.cc \
src/google/protobuf/wire_format_lite.cc \
src/google/protobuf/io/coded_stream.cc \
src/google/protobuf/io/coded_stream_inl.h \
src/google/protobuf/io/zero_copy_stream.cc \
src/google/protobuf/io/zero_copy_stream_impl_lite.cc
JAVA_LITE_SRC_FILES := \
java/src/main/java/com/google/protobuf/UninitializedMessageException.java \
java/src/main/java/com/google/protobuf/MessageLite.java \
java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
java/src/main/java/com/google/protobuf/CodedOutputStream.java \
java/src/main/java/com/google/protobuf/ByteString.java \
java/src/main/java/com/google/protobuf/CodedInputStream.java \
java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java \
java/src/main/java/com/google/protobuf/AbstractMessageLite.java \
java/src/main/java/com/google/protobuf/FieldSet.java \
java/src/main/java/com/google/protobuf/Internal.java \
java/src/main/java/com/google/protobuf/WireFormat.java \
java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
COMPILER_SRC_FILES := \
src/google/protobuf/descriptor.cc \
src/google/protobuf/descriptor.pb.cc \
src/google/protobuf/descriptor_database.cc \
src/google/protobuf/dynamic_message.cc \
src/google/protobuf/extension_set.cc \
src/google/protobuf/extension_set_heavy.cc \
src/google/protobuf/generated_message_reflection.cc \
src/google/protobuf/generated_message_util.cc \
src/google/protobuf/message.cc \
src/google/protobuf/message_lite.cc \
src/google/protobuf/reflection_ops.cc \
src/google/protobuf/repeated_field.cc \
src/google/protobuf/service.cc \
src/google/protobuf/text_format.cc \
src/google/protobuf/unknown_field_set.cc \
src/google/protobuf/wire_format.cc \
src/google/protobuf/wire_format_lite.cc \
src/google/protobuf/compiler/code_generator.cc \
src/google/protobuf/compiler/command_line_interface.cc \
src/google/protobuf/compiler/importer.cc \
src/google/protobuf/compiler/main.cc \
src/google/protobuf/compiler/parser.cc \
src/google/protobuf/compiler/plugin.cc \
src/google/protobuf/compiler/plugin.pb.cc \
src/google/protobuf/compiler/subprocess.cc \
src/google/protobuf/compiler/zip_writer.cc \
src/google/protobuf/compiler/cpp/cpp_enum.cc \
src/google/protobuf/compiler/cpp/cpp_enum_field.cc \
src/google/protobuf/compiler/cpp/cpp_extension.cc \
src/google/protobuf/compiler/cpp/cpp_field.cc \
src/google/protobuf/compiler/cpp/cpp_file.cc \
src/google/protobuf/compiler/cpp/cpp_generator.cc \
src/google/protobuf/compiler/cpp/cpp_helpers.cc \
src/google/protobuf/compiler/cpp/cpp_message.cc \
src/google/protobuf/compiler/cpp/cpp_message_field.cc \
src/google/protobuf/compiler/cpp/cpp_primitive_field.cc \
src/google/protobuf/compiler/cpp/cpp_service.cc \
src/google/protobuf/compiler/cpp/cpp_string_field.cc \
src/google/protobuf/compiler/java/java_enum.cc \
src/google/protobuf/compiler/java/java_enum_field.cc \
src/google/protobuf/compiler/java/java_extension.cc \
src/google/protobuf/compiler/java/java_field.cc \
src/google/protobuf/compiler/java/java_file.cc \
src/google/protobuf/compiler/java/java_generator.cc \
src/google/protobuf/compiler/java/java_helpers.cc \
src/google/protobuf/compiler/java/java_message.cc \
src/google/protobuf/compiler/java/java_message_field.cc \
src/google/protobuf/compiler/java/java_primitive_field.cc \
src/google/protobuf/compiler/java/java_service.cc \
src/google/protobuf/compiler/javamicro/javamicro_enum.cc \
src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc \
src/google/protobuf/compiler/javamicro/javamicro_field.cc \
src/google/protobuf/compiler/javamicro/javamicro_file.cc \
src/google/protobuf/compiler/javamicro/javamicro_generator.cc \
src/google/protobuf/compiler/javamicro/javamicro_helpers.cc \
src/google/protobuf/compiler/javamicro/javamicro_message.cc \
src/google/protobuf/compiler/javamicro/javamicro_message_field.cc \
src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc \
src/google/protobuf/compiler/javanano/javanano_enum.cc \
src/google/protobuf/compiler/javanano/javanano_enum_field.cc \
src/google/protobuf/compiler/javanano/javanano_extension.cc \
src/google/protobuf/compiler/javanano/javanano_field.cc \
src/google/protobuf/compiler/javanano/javanano_file.cc \
src/google/protobuf/compiler/javanano/javanano_generator.cc \
src/google/protobuf/compiler/javanano/javanano_helpers.cc \
src/google/protobuf/compiler/javanano/javanano_message.cc \
src/google/protobuf/compiler/javanano/javanano_message_field.cc \
src/google/protobuf/compiler/javanano/javanano_primitive_field.cc \
src/google/protobuf/compiler/python/python_generator.cc \
src/google/protobuf/io/coded_stream.cc \
src/google/protobuf/io/gzip_stream.cc \
src/google/protobuf/io/printer.cc \
src/google/protobuf/io/tokenizer.cc \
src/google/protobuf/io/zero_copy_stream.cc \
src/google/protobuf/io/zero_copy_stream_impl.cc \
src/google/protobuf/io/zero_copy_stream_impl_lite.cc \
src/google/protobuf/stubs/common.cc \
src/google/protobuf/stubs/hash.cc \
src/google/protobuf/stubs/once.cc \
src/google/protobuf/stubs/structurally_valid.cc \
src/google/protobuf/stubs/strutil.cc \
src/google/protobuf/stubs/substitute.cc
# Java nano library (for device-side users)
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libprotobuf-java-nano
LOCAL_MODULE_TAGS := optional
LOCAL_SDK_VERSION := 8
LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/nano)
LOCAL_SRC_FILES += $(call all-java-files-under, java/src/device/main/java/com/google/protobuf/nano)
include $(BUILD_STATIC_JAVA_LIBRARY)
# Java nano library (for host-side users)
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := host-libprotobuf-java-nano
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/nano)
include $(BUILD_HOST_JAVA_LIBRARY)
# Java micro library (for device-side users)
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libprotobuf-java-micro
LOCAL_MODULE_TAGS := optional
LOCAL_SDK_VERSION := 8
LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/micro)
include $(BUILD_STATIC_JAVA_LIBRARY)
# Java micro library (for host-side users)
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := host-libprotobuf-java-micro
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/micro)
include $(BUILD_HOST_JAVA_LIBRARY)
# Java lite library (for device-side users)
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libprotobuf-java-lite
LOCAL_MODULE_TAGS := optional
LOCAL_SDK_VERSION := 8
LOCAL_SRC_FILES := $(JAVA_LITE_SRC_FILES)
include $(BUILD_STATIC_JAVA_LIBRARY)
# Java lite library (for host-side users)
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := host-libprotobuf-java-lite
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(JAVA_LITE_SRC_FILES)
include $(BUILD_HOST_JAVA_LIBRARY)
# C++ lite library
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libprotobuf-cpp-lite
LOCAL_MODULE_TAGS := optional
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := $(CC_LITE_SRC_FILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/android \
$(LOCAL_PATH)/src
# Define the header files to be copied
#LOCAL_COPY_HEADERS := \
# src/google/protobuf/stubs/once.h \
# src/google/protobuf/stubs/common.h \
# src/google/protobuf/io/coded_stream.h \
# src/google/protobuf/generated_message_util.h \
# src/google/protobuf/repeated_field.h \
# src/google/protobuf/extension_set.h \
# src/google/protobuf/wire_format_lite_inl.h
#
#LOCAL_COPY_HEADERS_TO := $(LOCAL_MODULE)
LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS)
# These are the minimum versions and don't need to be update.
ifeq ($(TARGET_ARCH),arm)
LOCAL_SDK_VERSION := 8
else
# x86/mips support only available from API 9.
LOCAL_SDK_VERSION := 9
endif
LOCAL_NDK_STL_VARIANT := stlport_static
include $(BUILD_STATIC_LIBRARY)
# C++ lite library (libc++ flavored for the platform)
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libprotobuf-cpp-lite
LOCAL_MODULE_TAGS := optional
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := $(CC_LITE_SRC_FILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/android \
$(LOCAL_PATH)/src
LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS)
include $(BUILD_SHARED_LIBRARY)
# C++ full library
# =======================================================
protobuf_cc_full_src_files := \
$(CC_LITE_SRC_FILES) \
src/google/protobuf/stubs/strutil.cc \
src/google/protobuf/stubs/strutil.h \
src/google/protobuf/stubs/substitute.cc \
src/google/protobuf/stubs/substitute.h \
src/google/protobuf/stubs/structurally_valid.cc \
src/google/protobuf/descriptor.cc \
src/google/protobuf/descriptor.pb.cc \
src/google/protobuf/descriptor_database.cc \
src/google/protobuf/dynamic_message.cc \
src/google/protobuf/extension_set_heavy.cc \
src/google/protobuf/generated_message_reflection.cc \
src/google/protobuf/message.cc \
src/google/protobuf/reflection_ops.cc \
src/google/protobuf/service.cc \
src/google/protobuf/text_format.cc \
src/google/protobuf/unknown_field_set.cc \
src/google/protobuf/wire_format.cc \
src/google/protobuf/io/gzip_stream.cc \
src/google/protobuf/io/printer.cc \
src/google/protobuf/io/tokenizer.cc \
src/google/protobuf/io/zero_copy_stream_impl.cc \
src/google/protobuf/compiler/importer.cc \
src/google/protobuf/compiler/parser.cc
# C++ full library - stlport version
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libprotobuf-cpp-full
LOCAL_MODULE_TAGS := optional
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := $(protobuf_cc_full_src_files)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/android \
external/zlib \
$(LOCAL_PATH)/src
# Define the header files to be copied
#LOCAL_COPY_HEADERS := \
# src/google/protobuf/stubs/once.h \
# src/google/protobuf/stubs/common.h \
# src/google/protobuf/io/coded_stream.h \
# src/google/protobuf/generated_message_util.h \
# src/google/protobuf/repeated_field.h \
# src/google/protobuf/extension_set.h \
# src/google/protobuf/wire_format_lite_inl.h
#
#LOCAL_COPY_HEADERS_TO := $(LOCAL_MODULE)
LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS)
# These are the minimum versions and don't need to be update.
ifeq ($(TARGET_ARCH),arm)
LOCAL_SDK_VERSION := 8
else
# x86/mips support only available from API 9.
LOCAL_SDK_VERSION := 9
endif
LOCAL_NDK_STL_VARIANT := stlport_static
include $(BUILD_STATIC_LIBRARY)
# C++ full library - Gnustl+rtti version
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libprotobuf-cpp-full-gnustl-rtti
LOCAL_MODULE_TAGS := optional
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := $(protobuf_cc_full_src_files)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/android \
external/zlib \
$(LOCAL_PATH)/src
LOCAL_CFLAGS := -frtti $(IGNORED_WARNINGS)
LOCAL_SDK_VERSION := 14
LOCAL_NDK_STL_VARIANT := gnustl_static
include $(BUILD_STATIC_LIBRARY)
# C++ full library - libc++ version for the platform
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libprotobuf-cpp-full
LOCAL_MODULE_TAGS := optional
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := $(protobuf_cc_full_src_files)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/android \
external/zlib \
$(LOCAL_PATH)/src
LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS)
LOCAL_SHARED_LIBRARIES := libz
include $(BUILD_SHARED_LIBRARY)
# Clean temp vars
protobuf_cc_full_src_files :=
# Android Protocol buffer compiler, aprotoc (host executable)
# used by the build systems as $(PROTOC) defined in
# build/core/config.mk
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := aprotoc
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE_TAGS := optional
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := $(COMPILER_SRC_FILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/android \
external/zlib \
$(LOCAL_PATH)/src
LOCAL_STATIC_LIBRARIES += libz
ifneq ($(HOST_OS),windows)
LOCAL_LDLIBS := -lpthread
endif
LOCAL_CFLAGS := $(IGNORED_WARNINGS)
include $(BUILD_HOST_EXECUTABLE)
# To test java proto params build rules.
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := aprotoc-test-nano-params
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
LOCAL_SRC_FILES := \
src/google/protobuf/unittest_import_nano.proto \
src/google/protobuf/unittest_simple_nano.proto \
src/google/protobuf/unittest_stringutf8_nano.proto \
src/google/protobuf/unittest_recursive_nano.proto
LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/src
LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \
java_package = $(LOCAL_PATH)/src/google/protobuf/unittest_import_nano.proto|com.google.protobuf.nano, \
java_outer_classname = $(LOCAL_PATH)/src/google/protobuf/unittest_import_nano.proto|UnittestImportNano
include $(BUILD_STATIC_JAVA_LIBRARY)
# To test Android-specific nanoproto features.
# =======================================================
include $(CLEAR_VARS)
# Parcelable messages
LOCAL_MODULE := android-nano-test-parcelable
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
LOCAL_SRC_FILES := src/google/protobuf/unittest_simple_nano.proto
LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/src
LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \
parcelable_messages = true
include $(BUILD_STATIC_JAVA_LIBRARY)
include $(CLEAR_VARS)
# Parcelable and extendable messages
LOCAL_MODULE := android-nano-test-parcelable-extendable
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
LOCAL_SRC_FILES := src/google/protobuf/unittest_extension_nano.proto
LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/src
LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \
parcelable_messages = true, \
store_unknown_fields = true
include $(BUILD_STATIC_JAVA_LIBRARY)
include $(CLEAR_VARS)
# Test APK
LOCAL_PACKAGE_NAME := NanoAndroidTest
LOCAL_SDK_VERSION := 8
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under, java/src/device/test/java/com/google/protobuf/nano)
LOCAL_MANIFEST_FILE := java/src/device/test/AndroidManifest.xml
LOCAL_STATIC_JAVA_LIBRARIES := libprotobuf-java-nano \
android-nano-test-parcelable \
android-nano-test-parcelable-extendable
LOCAL_DEX_PREOPT := false
include $(BUILD_PACKAGE)
# 2.3.0 prebuilts for backwards compatibility.
include $(LOCAL_PATH)/prebuilts/Android.mk

354
javanano/README.txt Normal file
View File

@ -0,0 +1,354 @@
Protocol Buffers - Google's data interchange format
Copyright 2008 Google Inc.
This directory contains the Java Protocol Buffers Nano runtime library.
Installation - With Maven
=========================
The Protocol Buffers build is managed using Maven. If you would
rather build without Maven, see below.
1) Install Apache Maven if you don't have it:
http://maven.apache.org/
2) Build the C++ code, or obtain a binary distribution of protoc. If
you install a binary distribution, make sure that it is the same
version as this package. If in doubt, run:
$ protoc --version
You will need to place the protoc executable in ../src. (If you
built it yourself, it should already be there.)
3) Run the tests:
$ mvn test
If some tests fail, this library may not work correctly on your
system. Continue at your own risk.
4) Install the library into your Maven repository:
$ mvn install
5) If you do not use Maven to manage your own build, you can build a
.jar file to use:
$ mvn package
The .jar will be placed in the "target" directory.
Installation - Without Maven
============================
If you would rather not install Maven to build the library, you may
follow these instructions instead. Note that these instructions skip
running unit tests.
1) Build the C++ code, or obtain a binary distribution of protoc. If
you install a binary distribution, make sure that it is the same
version as this package. If in doubt, run:
$ protoc --version
If you built the C++ code without installing, the compiler binary
should be located in ../src.
2) Invoke protoc to build DescriptorProtos.java:
$ protoc --java_out=src/main/java -I../src \
../src/google/protobuf/descriptor.proto
3) Compile the code in src/main/java using whatever means you prefer.
4) Install the classes wherever you prefer.
Nano version
============================
Nano is a special code generator and runtime library designed specially
for Android, and is very resource-friendly in both the amount of code
and the runtime overhead. An overview of Nano features:
- No descriptors or message builders.
- All messages are mutable; fields are public Java fields.
- For optional fields only, encapsulation behind setter/getter/hazzer/
clearer functions is opt-in, which provide proper 'has' state support.
- If not opted in, has state is not available. Serialization outputs
all fields not equal to their defaults (see important implications
below).
- Required fields are always serialized.
- Enum constants are integers; protection against invalid values only
when parsing from the wire.
- Enum constants can be generated into container interfaces bearing
the enum's name (so the referencing code is in Java style).
- CodedInputByteBufferNano can only take byte[] (not InputStream).
- Similarly CodedOutputByteBufferNano can only write to byte[].
- Repeated fields are in arrays, not ArrayList or Vector. Null array
elements are allowed and silently ignored.
- Full support of serializing/deserializing repeated packed fields.
- Support of extensions.
- Unset messages/groups are null, not an immutable empty default
instance.
- toByteArray(...) and mergeFrom(...) are now static functions of
MessageNano.
- The 'bytes' type translates to the Java type byte[].
The generated messages are not thread-safe for writes, but may be
used simultaneously from multiple threads in a read-only manner.
In other words, an appropriate synchronization mechanism (such as
a ReadWriteLock) must be used to ensure that a message, its
ancestors, and descendants are not accessed by any other threads
while the message is being modified. Field reads, getter methods
(but not getExtension(...)), toByteArray(...), writeTo(...),
getCachedSize(), and getSerializedSize() are all considered read-only
operations.
IMPORTANT: If you have fields with defaults and opt out of accessors
How fields with defaults are serialized has changed. Because we don't
keep "has" state, any field equal to its default is assumed to be not
set and therefore is not serialized. Consider the situation where we
change the default value of a field. Senders compiled against an older
version of the proto continue to match against the old default, and
don't send values to the receiver even though the receiver assumes the
new default value. Therefore, think carefully about the implications
of changing the default value. Alternatively, turn on accessors and
enjoy the benefit of the explicit has() checks.
IMPORTANT: If you have "bytes" fields with non-empty defaults
Because the byte buffer is now of mutable type byte[], the default
static final cannot be exposed through a public field. Each time a
message's constructor or clear() function is called, the default value
(kept in a private byte[]) is cloned. This causes a small memory
penalty. This is not a problem if the field has no default or is an
empty default.
Nano Generator options
java_package -> <file-name>|<package-name>
java_outer_classname -> <file-name>|<package-name>
java_multiple_files -> true or false
java_nano_generate_has -> true or false [DEPRECATED]
optional_field_style -> default or accessors
enum_style -> c or java
ignore_services -> true or false
parcelable_messages -> true or false
java_package=<file-name>|<package-name> (no default)
This allows overriding the 'java_package' option value
for the given file from the command line. Use multiple
java_package options to override the option for multiple
files. The final Java package for each file is the value
of this command line option if present, or the value of
the same option defined in the file if present, or the
proto package if present, or the default Java package.
java_outer_classname=<file-name>|<outer-classname> (no default)
This allows overriding the 'java_outer_classname' option
for the given file from the command line. Use multiple
java_outer_classname options to override the option for
multiple files. The final Java outer class name for each
file is the value of this command line option if present,
or the value of the same option defined in the file if
present, or the file name converted to CamelCase. This
outer class will nest all classes and integer constants
generated from file-scope messages and enums.
java_multiple_files={true,false} (no default)
This allows overriding the 'java_multiple_files' option
in all source files and their imported files from the
command line. The final value of this option for each
file is the value defined in this command line option, or
the value of the same option defined in the file if
present, or false. This specifies whether to generate
package-level classes for the file-scope messages in the
same Java package as the outer class (instead of nested
classes in the outer class). File-scope enum constants
are still generated as integer constants in the outer
class. This affects the fully qualified references in the
Java code. NOTE: because the command line option
overrides the value for all files and their imported
files, using this option inconsistently may result in
incorrect references to the imported messages and enum
constants.
java_nano_generate_has={true,false} (default: false)
DEPRECATED. Use optional_field_style=accessors.
If true, generates a public boolean variable has<fieldname>
accompanying each optional or required field (not present for
repeated fields, groups or messages). It is set to false initially
and upon clear(). If parseFrom(...) reads the field from the wire,
it is set to true. This is a way for clients to inspect the "has"
value upon parse. If it is set to true, writeTo(...) will ALWAYS
output that field (even if field value is equal to its
default).
IMPORTANT: This option costs an extra 4 bytes per primitive field in
the message. Think carefully about whether you really need this. In
many cases reading the default works and determining whether the
field was received over the wire is irrelevant.
optional_field_style={default,accessors,reftypes} (default: default)
Defines the style of the generated code for fields.
* default *
In the default style, optional fields translate into public mutable
Java fields, and the serialization process is as discussed in the
"IMPORTANT" section above.
* accessors *
When set to 'accessors', each optional field is encapsulated behind
4 accessors, namely get<fieldname>(), set<fieldname>(), has<fieldname>()
and clear<fieldname>() methods, with the standard semantics. The hazzer's
return value determines whether a field is serialized, so this style is
useful when you need to serialize a field with the default value, or check
if a field has been explicitly set to its default value from the wire.
In the 'accessors' style, required and nested message fields are still
translated to one public mutable Java field each, repeated fields are still
translated to arrays. No accessors are generated for them.
IMPORTANT: When using the 'accessors' style, ProGuard should always
be enabled with optimization (don't use -dontoptimize) and allowing
access modification (use -allowaccessmodification). This removes the
unused accessors and maybe inline the rest at the call sites,
reducing the final code size.
TODO(maxtroy): find ProGuard config that would work the best.
* reftypes *
When set to 'reftypes', each proto field is generated as a public Java
field. For primitive types, these fields use the Java reference types
such as java.lang.Integer instead of primitive types such as int.
In the 'reftypes' style, fields are initialized to null (or empty
arrays for repeated fields), and their default values are not available.
They are serialized over the wire based on equality to null.
The 'reftypes' mode has some additional cost due to autoboxing and usage
of reference types. In practice, many boxed types are cached, and so don't
result in object creation. However, references do take slightly more memory
than primitives.
The 'reftypes' mode is useful when you want to be able to serialize fields
with default values, or check if a field has been explicitly set to the
default over the wire without paying the extra method cost of the
'accessors' mode.
Note that if you attempt to write null to a required field in the reftypes
mode, serialization of the proto will cause a NullPointerException. This is
an intentional indicator that you must set required fields.
NOTE
optional_field_style=accessors or reftypes cannot be used together with
java_nano_generate_has=true. If you need the 'has' flag for any
required field (you have no reason to), you can only use
java_nano_generate_has=true.
enum_style={c,java} (default: c)
Defines where to put the int constants generated from enum members.
* c *
Use C-style, so the enum constants are available at the scope where
the enum is defined. A file-scope enum's members are referenced like
'FileOuterClass.ENUM_VALUE'; a message-scope enum's members are
referenced as 'Message.ENUM_VALUE'. The enum name is unavailable.
This complies with the Micro code generator's behavior.
* java *
Use Java-style, so the enum constants are available under the enum
name and referenced like 'EnumName.ENUM_VALUE' (they are still int
constants). The enum name becomes the name of a public interface, at
the scope where the enum is defined. If the enum is file-scope and
the java_multiple_files option is on, the interface will be defined
in its own file. To reduce code size, this interface should not be
implemented and ProGuard shrinking should be used, so after the Java
compiler inlines all referenced enum constants into the call sites,
the interface remains unused and can be removed by ProGuard.
ignore_services={true,false} (default: false)
Skips services definitions.
Nano doesn't support services. By default, if a service is defined
it will generate a compilation error. If this flag is set to true,
services will be silently ignored, instead.
parcelable_messages={true,false} (default: false)
Android-specific option to generate Parcelable messages.
To use nano protobufs within the Android repo:
- Set 'LOCAL_PROTOC_OPTIMIZE_TYPE := nano' in your local .mk file.
When building a Java library or an app (package) target, the build
system will add the Java nano runtime library to the
LOCAL_STATIC_JAVA_LIBRARIES variable, so you don't need to.
- Set 'LOCAL_PROTO_JAVA_OUTPUT_PARAMS := ...' in your local .mk file
for any command-line options you need. Use commas to join multiple
options. In the nano flavor only, whitespace surrounding the option
names and values are ignored, so you can use backslash-newline or
'+=' to structure your make files nicely.
- The options will be applied to *all* proto files in LOCAL_SRC_FILES
when you build a Java library or package. In case different options
are needed for different proto files, build separate Java libraries
and reference them in your main target. Note: you should make sure
that, for each separate target, all proto files imported from any
proto file in LOCAL_SRC_FILES are included in LOCAL_SRC_FILES. This
is because the generator has to assume that the imported files are
built using the same options, and will generate code that reference
the fields and enums from the imported files using the same code
style.
- Hint: 'include $(CLEAR_VARS)' resets all LOCAL_ variables, including
the two above.
To use nano protobufs outside of Android repo:
- Link with the generated jar file
<protobuf-root>java/target/protobuf-java-2.3.0-nano.jar.
- Invoke with --javanano_out, e.g.:
./protoc '--javanano_out=\
java_package=src/proto/simple-data.proto|my_package,\
java_outer_classname=src/proto/simple-data.proto|OuterName\
:.' src/proto/simple-data.proto
Contributing to nano:
Please add/edit tests in NanoTest.java.
Please run the following steps to test:
- cd external/protobuf
- ./configure
- Run "make -j12 check" and verify all tests pass.
- cd java
- Run "mvn test" and verify all tests pass.
- cd ../../..
- . build/envsetup.sh
- lunch 1
- "make -j12 aprotoc libprotobuf-java-2.3.0-nano aprotoc-test-nano-params NanoAndroidTest" and
check for build errors.
- Plug in an Android device or start an emulator.
- adb install -r out/target/product/generic/data/app/NanoAndroidTest.apk
- Run:
"adb shell am instrument -w com.google.protobuf.nano.test/android.test.InstrumentationTestRunner"
and verify all tests pass.
- repo sync -c -j256
- "make -j12" and check for build errors
Usage
=====
The complete documentation for Protocol Buffers is available via the
web at:
http://code.google.com/apis/protocolbuffers://developers.google.com/protocol-buffers/

164
javanano/pom.xml Normal file
View File

@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.google</groupId>
<artifactId>google</artifactId>
<version>1</version>
</parent>
<groupId>com.google.protobuf.nano</groupId>
<artifactId>protobuf-javanano</artifactId>
<version>2.6.2-pre</version>
<packaging>bundle</packaging>
<name>Protocol Buffer JavaNano API</name>
<description>
Protocol Buffers are a way of encoding structured data in an efficient yet
extensible format.
</description>
<inceptionYear>2008</inceptionYear>
<url>https://developers.google.com/protocol-buffers/</url>
<licenses>
<license>
<name>New BSD license</name>
<url>http://www.opensource.org/licenses/bsd-license.php</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<url>https://github.com/google/protobuf</url>
<connection>
scm:git:https://github.com/google/protobuf.git
</connection>
</scm>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymockclassextension</artifactId>
<version>2.2.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>generate-test-sources</id>
<phase>generate-test-sources</phase>
<configuration>
<tasks>
<mkdir dir="target/generated-test-sources" />
<exec executable="../src/protoc">
<arg value="--javanano_out=generate_equals=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_import_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_single_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=store_unknown_fields=true,generate_equals=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=store_unknown_fields=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=java_nano_generate_has=true,generate_equals=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_has_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=optional_field_style=accessors,generate_equals=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=enum_style=java:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=
optional_field_style=accessors,
java_outer_classname=google/protobuf/nano/unittest_enum_validity_nano.proto|EnumValidityAccessors
:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=optional_field_style=reftypes,generate_equals=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto" />
</exec>
</tasks>
<testSourceRoot>target/generated-test-sources</testSourceRoot>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
<Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
<Export-Package>com.google.protobuf;version=2.6.2-pre</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,641 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
import java.io.IOException;
/**
* Reads and decodes protocol message fields.
*
* This class contains two kinds of methods: methods that read specific
* protocol message constructs and field types (e.g. {@link #readTag()} and
* {@link #readInt32()}) and methods that read low-level values (e.g.
* {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading
* encoded protocol messages, you should use the former methods, but if you are
* reading some other format of your own design, use the latter.
*
* @author kenton@google.com Kenton Varda
*/
public final class CodedInputByteBufferNano {
/**
* Create a new CodedInputStream wrapping the given byte array.
*/
public static CodedInputByteBufferNano newInstance(final byte[] buf) {
return newInstance(buf, 0, buf.length);
}
/**
* Create a new CodedInputStream wrapping the given byte array slice.
*/
public static CodedInputByteBufferNano newInstance(final byte[] buf, final int off,
final int len) {
return new CodedInputByteBufferNano(buf, off, len);
}
// -----------------------------------------------------------------
/**
* Attempt to read a field tag, returning zero if we have reached EOF.
* Protocol message parsers use this to read tags, since a protocol message
* may legally end wherever a tag occurs, and zero is not a valid tag number.
*/
public int readTag() throws IOException {
if (isAtEnd()) {
lastTag = 0;
return 0;
}
lastTag = readRawVarint32();
if (lastTag == 0) {
// If we actually read zero, that's not a valid tag.
throw InvalidProtocolBufferNanoException.invalidTag();
}
return lastTag;
}
/**
* Verifies that the last call to readTag() returned the given tag value.
* This is used to verify that a nested group ended with the correct
* end tag.
*
* @throws InvalidProtocolBufferNanoException {@code value} does not match the
* last tag.
*/
public void checkLastTagWas(final int value)
throws InvalidProtocolBufferNanoException {
if (lastTag != value) {
throw InvalidProtocolBufferNanoException.invalidEndTag();
}
}
/**
* Reads and discards a single field, given its tag value.
*
* @return {@code false} if the tag is an endgroup tag, in which case
* nothing is skipped. Otherwise, returns {@code true}.
*/
public boolean skipField(final int tag) throws IOException {
switch (WireFormatNano.getTagWireType(tag)) {
case WireFormatNano.WIRETYPE_VARINT:
readInt32();
return true;
case WireFormatNano.WIRETYPE_FIXED64:
readRawLittleEndian64();
return true;
case WireFormatNano.WIRETYPE_LENGTH_DELIMITED:
skipRawBytes(readRawVarint32());
return true;
case WireFormatNano.WIRETYPE_START_GROUP:
skipMessage();
checkLastTagWas(
WireFormatNano.makeTag(WireFormatNano.getTagFieldNumber(tag),
WireFormatNano.WIRETYPE_END_GROUP));
return true;
case WireFormatNano.WIRETYPE_END_GROUP:
return false;
case WireFormatNano.WIRETYPE_FIXED32:
readRawLittleEndian32();
return true;
default:
throw InvalidProtocolBufferNanoException.invalidWireType();
}
}
/**
* Reads and discards an entire message. This will read either until EOF
* or until an endgroup tag, whichever comes first.
*/
public void skipMessage() throws IOException {
while (true) {
final int tag = readTag();
if (tag == 0 || !skipField(tag)) {
return;
}
}
}
// -----------------------------------------------------------------
/** Read a {@code double} field value from the stream. */
public double readDouble() throws IOException {
return Double.longBitsToDouble(readRawLittleEndian64());
}
/** Read a {@code float} field value from the stream. */
public float readFloat() throws IOException {
return Float.intBitsToFloat(readRawLittleEndian32());
}
/** Read a {@code uint64} field value from the stream. */
public long readUInt64() throws IOException {
return readRawVarint64();
}
/** Read an {@code int64} field value from the stream. */
public long readInt64() throws IOException {
return readRawVarint64();
}
/** Read an {@code int32} field value from the stream. */
public int readInt32() throws IOException {
return readRawVarint32();
}
/** Read a {@code fixed64} field value from the stream. */
public long readFixed64() throws IOException {
return readRawLittleEndian64();
}
/** Read a {@code fixed32} field value from the stream. */
public int readFixed32() throws IOException {
return readRawLittleEndian32();
}
/** Read a {@code bool} field value from the stream. */
public boolean readBool() throws IOException {
return readRawVarint32() != 0;
}
/** Read a {@code string} field value from the stream. */
public String readString() throws IOException {
final int size = readRawVarint32();
if (size <= (bufferSize - bufferPos) && size > 0) {
// Fast path: We already have the bytes in a contiguous buffer, so
// just copy directly from it.
final String result = new String(buffer, bufferPos, size, "UTF-8");
bufferPos += size;
return result;
} else {
// Slow path: Build a byte array first then copy it.
return new String(readRawBytes(size), "UTF-8");
}
}
/** Read a {@code group} field value from the stream. */
public void readGroup(final MessageNano msg, final int fieldNumber)
throws IOException {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferNanoException.recursionLimitExceeded();
}
++recursionDepth;
msg.mergeFrom(this);
checkLastTagWas(
WireFormatNano.makeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP));
--recursionDepth;
}
public void readMessage(final MessageNano msg)
throws IOException {
final int length = readRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferNanoException.recursionLimitExceeded();
}
final int oldLimit = pushLimit(length);
++recursionDepth;
msg.mergeFrom(this);
checkLastTagWas(0);
--recursionDepth;
popLimit(oldLimit);
}
/** Read a {@code bytes} field value from the stream. */
public byte[] readBytes() throws IOException {
final int size = readRawVarint32();
if (size <= (bufferSize - bufferPos) && size > 0) {
// Fast path: We already have the bytes in a contiguous buffer, so
// just copy directly from it.
final byte[] result = new byte[size];
System.arraycopy(buffer, bufferPos, result, 0, size);
bufferPos += size;
return result;
} else {
// Slow path: Build a byte array first then copy it.
return readRawBytes(size);
}
}
/** Read a {@code uint32} field value from the stream. */
public int readUInt32() throws IOException {
return readRawVarint32();
}
/**
* Read an enum field value from the stream. Caller is responsible
* for converting the numeric value to an actual enum.
*/
public int readEnum() throws IOException {
return readRawVarint32();
}
/** Read an {@code sfixed32} field value from the stream. */
public int readSFixed32() throws IOException {
return readRawLittleEndian32();
}
/** Read an {@code sfixed64} field value from the stream. */
public long readSFixed64() throws IOException {
return readRawLittleEndian64();
}
/** Read an {@code sint32} field value from the stream. */
public int readSInt32() throws IOException {
return decodeZigZag32(readRawVarint32());
}
/** Read an {@code sint64} field value from the stream. */
public long readSInt64() throws IOException {
return decodeZigZag64(readRawVarint64());
}
// =================================================================
/**
* Read a raw Varint from the stream. If larger than 32 bits, discard the
* upper bits.
*/
public int readRawVarint32() throws IOException {
byte tmp = readRawByte();
if (tmp >= 0) {
return tmp;
}
int result = tmp & 0x7f;
if ((tmp = readRawByte()) >= 0) {
result |= tmp << 7;
} else {
result |= (tmp & 0x7f) << 7;
if ((tmp = readRawByte()) >= 0) {
result |= tmp << 14;
} else {
result |= (tmp & 0x7f) << 14;
if ((tmp = readRawByte()) >= 0) {
result |= tmp << 21;
} else {
result |= (tmp & 0x7f) << 21;
result |= (tmp = readRawByte()) << 28;
if (tmp < 0) {
// Discard upper 32 bits.
for (int i = 0; i < 5; i++) {
if (readRawByte() >= 0) {
return result;
}
}
throw InvalidProtocolBufferNanoException.malformedVarint();
}
}
}
}
return result;
}
/** Read a raw Varint from the stream. */
public long readRawVarint64() throws IOException {
int shift = 0;
long result = 0;
while (shift < 64) {
final byte b = readRawByte();
result |= (long)(b & 0x7F) << shift;
if ((b & 0x80) == 0) {
return result;
}
shift += 7;
}
throw InvalidProtocolBufferNanoException.malformedVarint();
}
/** Read a 32-bit little-endian integer from the stream. */
public int readRawLittleEndian32() throws IOException {
final byte b1 = readRawByte();
final byte b2 = readRawByte();
final byte b3 = readRawByte();
final byte b4 = readRawByte();
return ((b1 & 0xff) ) |
((b2 & 0xff) << 8) |
((b3 & 0xff) << 16) |
((b4 & 0xff) << 24);
}
/** Read a 64-bit little-endian integer from the stream. */
public long readRawLittleEndian64() throws IOException {
final byte b1 = readRawByte();
final byte b2 = readRawByte();
final byte b3 = readRawByte();
final byte b4 = readRawByte();
final byte b5 = readRawByte();
final byte b6 = readRawByte();
final byte b7 = readRawByte();
final byte b8 = readRawByte();
return (((long)b1 & 0xff) ) |
(((long)b2 & 0xff) << 8) |
(((long)b3 & 0xff) << 16) |
(((long)b4 & 0xff) << 24) |
(((long)b5 & 0xff) << 32) |
(((long)b6 & 0xff) << 40) |
(((long)b7 & 0xff) << 48) |
(((long)b8 & 0xff) << 56);
}
/**
* Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
* into values that can be efficiently encoded with varint. (Otherwise,
* negative values must be sign-extended to 64 bits to be varint encoded,
* thus always taking 10 bytes on the wire.)
*
* @param n An unsigned 32-bit integer, stored in a signed int because
* Java has no explicit unsigned support.
* @return A signed 32-bit integer.
*/
public static int decodeZigZag32(final int n) {
return (n >>> 1) ^ -(n & 1);
}
/**
* Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
* into values that can be efficiently encoded with varint. (Otherwise,
* negative values must be sign-extended to 64 bits to be varint encoded,
* thus always taking 10 bytes on the wire.)
*
* @param n An unsigned 64-bit integer, stored in a signed int because
* Java has no explicit unsigned support.
* @return A signed 64-bit integer.
*/
public static long decodeZigZag64(final long n) {
return (n >>> 1) ^ -(n & 1);
}
// -----------------------------------------------------------------
private final byte[] buffer;
private int bufferStart;
private int bufferSize;
private int bufferSizeAfterLimit;
private int bufferPos;
private int lastTag;
/** The absolute position of the end of the current message. */
private int currentLimit = Integer.MAX_VALUE;
/** See setRecursionLimit() */
private int recursionDepth;
private int recursionLimit = DEFAULT_RECURSION_LIMIT;
/** See setSizeLimit() */
private int sizeLimit = DEFAULT_SIZE_LIMIT;
private static final int DEFAULT_RECURSION_LIMIT = 64;
private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB
private CodedInputByteBufferNano(final byte[] buffer, final int off, final int len) {
this.buffer = buffer;
bufferStart = off;
bufferSize = off + len;
bufferPos = off;
}
/**
* Set the maximum message recursion depth. In order to prevent malicious
* messages from causing stack overflows, {@code CodedInputStream} limits
* how deeply messages may be nested. The default limit is 64.
*
* @return the old limit.
*/
public int setRecursionLimit(final int limit) {
if (limit < 0) {
throw new IllegalArgumentException(
"Recursion limit cannot be negative: " + limit);
}
final int oldLimit = recursionLimit;
recursionLimit = limit;
return oldLimit;
}
/**
* Set the maximum message size. In order to prevent malicious
* messages from exhausting memory or causing integer overflows,
* {@code CodedInputStream} limits how large a message may be.
* The default limit is 64MB. You should set this limit as small
* as you can without harming your app's functionality. Note that
* size limits only apply when reading from an {@code InputStream}, not
* when constructed around a raw byte array.
* <p>
* If you want to read several messages from a single CodedInputStream, you
* could call {@link #resetSizeCounter()} after each one to avoid hitting the
* size limit.
*
* @return the old limit.
*/
public int setSizeLimit(final int limit) {
if (limit < 0) {
throw new IllegalArgumentException(
"Size limit cannot be negative: " + limit);
}
final int oldLimit = sizeLimit;
sizeLimit = limit;
return oldLimit;
}
/**
* Resets the current size counter to zero (see {@link #setSizeLimit(int)}).
*/
public void resetSizeCounter() {
}
/**
* Sets {@code currentLimit} to (current position) + {@code byteLimit}. This
* is called when descending into a length-delimited embedded message.
*
* @return the old limit.
*/
public int pushLimit(int byteLimit) throws InvalidProtocolBufferNanoException {
if (byteLimit < 0) {
throw InvalidProtocolBufferNanoException.negativeSize();
}
byteLimit += bufferPos;
final int oldLimit = currentLimit;
if (byteLimit > oldLimit) {
throw InvalidProtocolBufferNanoException.truncatedMessage();
}
currentLimit = byteLimit;
recomputeBufferSizeAfterLimit();
return oldLimit;
}
private void recomputeBufferSizeAfterLimit() {
bufferSize += bufferSizeAfterLimit;
final int bufferEnd = bufferSize;
if (bufferEnd > currentLimit) {
// Limit is in current buffer.
bufferSizeAfterLimit = bufferEnd - currentLimit;
bufferSize -= bufferSizeAfterLimit;
} else {
bufferSizeAfterLimit = 0;
}
}
/**
* Discards the current limit, returning to the previous limit.
*
* @param oldLimit The old limit, as returned by {@code pushLimit}.
*/
public void popLimit(final int oldLimit) {
currentLimit = oldLimit;
recomputeBufferSizeAfterLimit();
}
/**
* Returns the number of bytes to be read before the current limit.
* If no limit is set, returns -1.
*/
public int getBytesUntilLimit() {
if (currentLimit == Integer.MAX_VALUE) {
return -1;
}
final int currentAbsolutePosition = bufferPos;
return currentLimit - currentAbsolutePosition;
}
/**
* Returns true if the stream has reached the end of the input. This is the
* case if either the end of the underlying input source has been reached or
* if the stream has reached a limit created using {@link #pushLimit(int)}.
*/
public boolean isAtEnd() {
return bufferPos == bufferSize;
}
/**
* Get current position in buffer relative to beginning offset.
*/
public int getPosition() {
return bufferPos - bufferStart;
}
/**
* Retrieves a subset of data in the buffer. The returned array is not backed by the original
* buffer array.
*
* @param offset the position (relative to the buffer start position) to start at.
* @param length the number of bytes to retrieve.
*/
public byte[] getData(int offset, int length) {
if (length == 0) {
return WireFormatNano.EMPTY_BYTES;
}
byte[] copy = new byte[length];
int start = bufferStart + offset;
System.arraycopy(buffer, start, copy, 0, length);
return copy;
}
/**
* Rewind to previous position. Cannot go forward.
*/
public void rewindToPosition(int position) {
if (position > bufferPos - bufferStart) {
throw new IllegalArgumentException(
"Position " + position + " is beyond current " + (bufferPos - bufferStart));
}
if (position < 0) {
throw new IllegalArgumentException("Bad position " + position);
}
bufferPos = bufferStart + position;
}
/**
* Read one byte from the input.
*
* @throws InvalidProtocolBufferNanoException The end of the stream or the current
* limit was reached.
*/
public byte readRawByte() throws IOException {
if (bufferPos == bufferSize) {
throw InvalidProtocolBufferNanoException.truncatedMessage();
}
return buffer[bufferPos++];
}
/**
* Read a fixed size of bytes from the input.
*
* @throws InvalidProtocolBufferNanoException The end of the stream or the current
* limit was reached.
*/
public byte[] readRawBytes(final int size) throws IOException {
if (size < 0) {
throw InvalidProtocolBufferNanoException.negativeSize();
}
if (bufferPos + size > currentLimit) {
// Read to the end of the stream anyway.
skipRawBytes(currentLimit - bufferPos);
// Then fail.
throw InvalidProtocolBufferNanoException.truncatedMessage();
}
if (size <= bufferSize - bufferPos) {
// We have all the bytes we need already.
final byte[] bytes = new byte[size];
System.arraycopy(buffer, bufferPos, bytes, 0, size);
bufferPos += size;
return bytes;
} else {
throw InvalidProtocolBufferNanoException.truncatedMessage();
}
}
/**
* Reads and discards {@code size} bytes.
*
* @throws InvalidProtocolBufferNanoException The end of the stream or the current
* limit was reached.
*/
public void skipRawBytes(final int size) throws IOException {
if (size < 0) {
throw InvalidProtocolBufferNanoException.negativeSize();
}
if (bufferPos + size > currentLimit) {
// Read to the end of the stream anyway.
skipRawBytes(currentLimit - bufferPos);
// Then fail.
throw InvalidProtocolBufferNanoException.truncatedMessage();
}
if (size <= bufferSize - bufferPos) {
// We have all the bytes we need already.
bufferPos += size;
} else {
throw InvalidProtocolBufferNanoException.truncatedMessage();
}
}
}

View File

@ -0,0 +1,879 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
* Encodes and writes protocol message fields.
*
* <p>This class contains two kinds of methods: methods that write specific
* protocol message constructs and field types (e.g. {@link #writeTag} and
* {@link #writeInt32}) and methods that write low-level values (e.g.
* {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are
* writing encoded protocol messages, you should use the former methods, but if
* you are writing some other format of your own design, use the latter.
*
* <p>This class is totally unsynchronized.
*
* @author kneton@google.com Kenton Varda
*/
public final class CodedOutputByteBufferNano {
private final byte[] buffer;
private final int limit;
private int position;
private CodedOutputByteBufferNano(final byte[] buffer, final int offset,
final int length) {
this.buffer = buffer;
position = offset;
limit = offset + length;
}
/**
* Create a new {@code CodedOutputStream} that writes directly to the given
* byte array. If more bytes are written than fit in the array,
* {@link OutOfSpaceException} will be thrown. Writing directly to a flat
* array is faster than writing to an {@code OutputStream}.
*/
public static CodedOutputByteBufferNano newInstance(final byte[] flatArray) {
return newInstance(flatArray, 0, flatArray.length);
}
/**
* Create a new {@code CodedOutputStream} that writes directly to the given
* byte array slice. If more bytes are written than fit in the slice,
* {@link OutOfSpaceException} will be thrown. Writing directly to a flat
* array is faster than writing to an {@code OutputStream}.
*/
public static CodedOutputByteBufferNano newInstance(final byte[] flatArray,
final int offset,
final int length) {
return new CodedOutputByteBufferNano(flatArray, offset, length);
}
// -----------------------------------------------------------------
/** Write a {@code double} field, including tag, to the stream. */
public void writeDouble(final int fieldNumber, final double value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
writeDoubleNoTag(value);
}
/** Write a {@code float} field, including tag, to the stream. */
public void writeFloat(final int fieldNumber, final float value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
writeFloatNoTag(value);
}
/** Write a {@code uint64} field, including tag, to the stream. */
public void writeUInt64(final int fieldNumber, final long value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
writeUInt64NoTag(value);
}
/** Write an {@code int64} field, including tag, to the stream. */
public void writeInt64(final int fieldNumber, final long value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
writeInt64NoTag(value);
}
/** Write an {@code int32} field, including tag, to the stream. */
public void writeInt32(final int fieldNumber, final int value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
writeInt32NoTag(value);
}
/** Write a {@code fixed64} field, including tag, to the stream. */
public void writeFixed64(final int fieldNumber, final long value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
writeFixed64NoTag(value);
}
/** Write a {@code fixed32} field, including tag, to the stream. */
public void writeFixed32(final int fieldNumber, final int value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
writeFixed32NoTag(value);
}
/** Write a {@code bool} field, including tag, to the stream. */
public void writeBool(final int fieldNumber, final boolean value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
writeBoolNoTag(value);
}
/** Write a {@code string} field, including tag, to the stream. */
public void writeString(final int fieldNumber, final String value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
writeStringNoTag(value);
}
/** Write a {@code group} field, including tag, to the stream. */
public void writeGroup(final int fieldNumber, final MessageNano value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_START_GROUP);
writeGroupNoTag(value);
writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP);
}
/** Write an embedded message field, including tag, to the stream. */
public void writeMessage(final int fieldNumber, final MessageNano value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
writeMessageNoTag(value);
}
/** Write a {@code bytes} field, including tag, to the stream. */
public void writeBytes(final int fieldNumber, final byte[] value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
writeBytesNoTag(value);
}
/** Write a {@code uint32} field, including tag, to the stream. */
public void writeUInt32(final int fieldNumber, final int value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
writeUInt32NoTag(value);
}
/**
* Write an enum field, including tag, to the stream. Caller is responsible
* for converting the enum value to its numeric value.
*/
public void writeEnum(final int fieldNumber, final int value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
writeEnumNoTag(value);
}
/** Write an {@code sfixed32} field, including tag, to the stream. */
public void writeSFixed32(final int fieldNumber, final int value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
writeSFixed32NoTag(value);
}
/** Write an {@code sfixed64} field, including tag, to the stream. */
public void writeSFixed64(final int fieldNumber, final long value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
writeSFixed64NoTag(value);
}
/** Write an {@code sint32} field, including tag, to the stream. */
public void writeSInt32(final int fieldNumber, final int value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
writeSInt32NoTag(value);
}
/** Write an {@code sint64} field, including tag, to the stream. */
public void writeSInt64(final int fieldNumber, final long value)
throws IOException {
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
writeSInt64NoTag(value);
}
/**
* Write a MessageSet extension field to the stream. For historical reasons,
* the wire format differs from normal fields.
*/
// public void writeMessageSetExtension(final int fieldNumber,
// final MessageMicro value)
// throws IOException {
// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
// writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
// writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
// }
/**
* Write an unparsed MessageSet extension field to the stream. For
* historical reasons, the wire format differs from normal fields.
*/
// public void writeRawMessageSetExtension(final int fieldNumber,
// final ByteStringMicro value)
// throws IOException {
// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
// writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
// writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
// }
// -----------------------------------------------------------------
/** Write a {@code double} field to the stream. */
public void writeDoubleNoTag(final double value) throws IOException {
writeRawLittleEndian64(Double.doubleToLongBits(value));
}
/** Write a {@code float} field to the stream. */
public void writeFloatNoTag(final float value) throws IOException {
writeRawLittleEndian32(Float.floatToIntBits(value));
}
/** Write a {@code uint64} field to the stream. */
public void writeUInt64NoTag(final long value) throws IOException {
writeRawVarint64(value);
}
/** Write an {@code int64} field to the stream. */
public void writeInt64NoTag(final long value) throws IOException {
writeRawVarint64(value);
}
/** Write an {@code int32} field to the stream. */
public void writeInt32NoTag(final int value) throws IOException {
if (value >= 0) {
writeRawVarint32(value);
} else {
// Must sign-extend.
writeRawVarint64(value);
}
}
/** Write a {@code fixed64} field to the stream. */
public void writeFixed64NoTag(final long value) throws IOException {
writeRawLittleEndian64(value);
}
/** Write a {@code fixed32} field to the stream. */
public void writeFixed32NoTag(final int value) throws IOException {
writeRawLittleEndian32(value);
}
/** Write a {@code bool} field to the stream. */
public void writeBoolNoTag(final boolean value) throws IOException {
writeRawByte(value ? 1 : 0);
}
/** Write a {@code string} field to the stream. */
public void writeStringNoTag(final String value) throws IOException {
// Unfortunately there does not appear to be any way to tell Java to encode
// UTF-8 directly into our buffer, so we have to let it create its own byte
// array and then copy.
final byte[] bytes = value.getBytes("UTF-8");
writeRawVarint32(bytes.length);
writeRawBytes(bytes);
}
/** Write a {@code group} field to the stream. */
public void writeGroupNoTag(final MessageNano value) throws IOException {
value.writeTo(this);
}
/** Write an embedded message field to the stream. */
public void writeMessageNoTag(final MessageNano value) throws IOException {
writeRawVarint32(value.getCachedSize());
value.writeTo(this);
}
/** Write a {@code bytes} field to the stream. */
public void writeBytesNoTag(final byte[] value) throws IOException {
writeRawVarint32(value.length);
writeRawBytes(value);
}
/** Write a {@code uint32} field to the stream. */
public void writeUInt32NoTag(final int value) throws IOException {
writeRawVarint32(value);
}
/**
* Write an enum field to the stream. Caller is responsible
* for converting the enum value to its numeric value.
*/
public void writeEnumNoTag(final int value) throws IOException {
writeRawVarint32(value);
}
/** Write an {@code sfixed32} field to the stream. */
public void writeSFixed32NoTag(final int value) throws IOException {
writeRawLittleEndian32(value);
}
/** Write an {@code sfixed64} field to the stream. */
public void writeSFixed64NoTag(final long value) throws IOException {
writeRawLittleEndian64(value);
}
/** Write an {@code sint32} field to the stream. */
public void writeSInt32NoTag(final int value) throws IOException {
writeRawVarint32(encodeZigZag32(value));
}
/** Write an {@code sint64} field to the stream. */
public void writeSInt64NoTag(final long value) throws IOException {
writeRawVarint64(encodeZigZag64(value));
}
// =================================================================
/**
* Compute the number of bytes that would be needed to encode a
* {@code double} field, including tag.
*/
public static int computeDoubleSize(final int fieldNumber,
final double value) {
return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code float} field, including tag.
*/
public static int computeFloatSize(final int fieldNumber, final float value) {
return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code uint64} field, including tag.
*/
public static int computeUInt64Size(final int fieldNumber, final long value) {
return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode an
* {@code int64} field, including tag.
*/
public static int computeInt64Size(final int fieldNumber, final long value) {
return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode an
* {@code int32} field, including tag.
*/
public static int computeInt32Size(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code fixed64} field, including tag.
*/
public static int computeFixed64Size(final int fieldNumber,
final long value) {
return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code fixed32} field, including tag.
*/
public static int computeFixed32Size(final int fieldNumber,
final int value) {
return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code bool} field, including tag.
*/
public static int computeBoolSize(final int fieldNumber,
final boolean value) {
return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code string} field, including tag.
*/
public static int computeStringSize(final int fieldNumber,
final String value) {
return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code group} field, including tag.
*/
public static int computeGroupSize(final int fieldNumber,
final MessageNano value) {
return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode an
* embedded message field, including tag.
*/
public static int computeMessageSize(final int fieldNumber,
final MessageNano value) {
return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code bytes} field, including tag.
*/
public static int computeBytesSize(final int fieldNumber,
final byte[] value) {
return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code uint32} field, including tag.
*/
public static int computeUInt32Size(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode an
* enum field, including tag. Caller is responsible for converting the
* enum value to its numeric value.
*/
public static int computeEnumSize(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode an
* {@code sfixed32} field, including tag.
*/
public static int computeSFixed32Size(final int fieldNumber,
final int value) {
return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode an
* {@code sfixed64} field, including tag.
*/
public static int computeSFixed64Size(final int fieldNumber,
final long value) {
return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode an
* {@code sint32} field, including tag.
*/
public static int computeSInt32Size(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode an
* {@code sint64} field, including tag.
*/
public static int computeSInt64Size(final int fieldNumber, final long value) {
return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* MessageSet extension to the stream. For historical reasons,
* the wire format differs from normal fields.
*/
// public static int computeMessageSetExtensionSize(
// final int fieldNumber, final MessageMicro value) {
// return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
// computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
// computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
// }
/**
* Compute the number of bytes that would be needed to encode an
* unparsed MessageSet extension field to the stream. For
* historical reasons, the wire format differs from normal fields.
*/
// public static int computeRawMessageSetExtensionSize(
// final int fieldNumber, final ByteStringMicro value) {
// return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
// computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
// computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
// }
// -----------------------------------------------------------------
/**
* Compute the number of bytes that would be needed to encode a
* {@code double} field, including tag.
*/
public static int computeDoubleSizeNoTag(final double value) {
return LITTLE_ENDIAN_64_SIZE;
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code float} field, including tag.
*/
public static int computeFloatSizeNoTag(final float value) {
return LITTLE_ENDIAN_32_SIZE;
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code uint64} field, including tag.
*/
public static int computeUInt64SizeNoTag(final long value) {
return computeRawVarint64Size(value);
}
/**
* Compute the number of bytes that would be needed to encode an
* {@code int64} field, including tag.
*/
public static int computeInt64SizeNoTag(final long value) {
return computeRawVarint64Size(value);
}
/**
* Compute the number of bytes that would be needed to encode an
* {@code int32} field, including tag.
*/
public static int computeInt32SizeNoTag(final int value) {
if (value >= 0) {
return computeRawVarint32Size(value);
} else {
// Must sign-extend.
return 10;
}
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code fixed64} field.
*/
public static int computeFixed64SizeNoTag(final long value) {
return LITTLE_ENDIAN_64_SIZE;
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code fixed32} field.
*/
public static int computeFixed32SizeNoTag(final int value) {
return LITTLE_ENDIAN_32_SIZE;
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code bool} field.
*/
public static int computeBoolSizeNoTag(final boolean value) {
return 1;
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code string} field.
*/
public static int computeStringSizeNoTag(final String value) {
try {
final byte[] bytes = value.getBytes("UTF-8");
return computeRawVarint32Size(bytes.length) +
bytes.length;
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not supported.");
}
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code group} field.
*/
public static int computeGroupSizeNoTag(final MessageNano value) {
return value.getSerializedSize();
}
/**
* Compute the number of bytes that would be needed to encode an embedded
* message field.
*/
public static int computeMessageSizeNoTag(final MessageNano value) {
final int size = value.getSerializedSize();
return computeRawVarint32Size(size) + size;
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code bytes} field.
*/
public static int computeBytesSizeNoTag(final byte[] value) {
return computeRawVarint32Size(value.length) + value.length;
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code uint32} field.
*/
public static int computeUInt32SizeNoTag(final int value) {
return computeRawVarint32Size(value);
}
/**
* Compute the number of bytes that would be needed to encode an enum field.
* Caller is responsible for converting the enum value to its numeric value.
*/
public static int computeEnumSizeNoTag(final int value) {
return computeRawVarint32Size(value);
}
/**
* Compute the number of bytes that would be needed to encode an
* {@code sfixed32} field.
*/
public static int computeSFixed32SizeNoTag(final int value) {
return LITTLE_ENDIAN_32_SIZE;
}
/**
* Compute the number of bytes that would be needed to encode an
* {@code sfixed64} field.
*/
public static int computeSFixed64SizeNoTag(final long value) {
return LITTLE_ENDIAN_64_SIZE;
}
/**
* Compute the number of bytes that would be needed to encode an
* {@code sint32} field.
*/
public static int computeSInt32SizeNoTag(final int value) {
return computeRawVarint32Size(encodeZigZag32(value));
}
/**
* Compute the number of bytes that would be needed to encode an
* {@code sint64} field.
*/
public static int computeSInt64SizeNoTag(final long value) {
return computeRawVarint64Size(encodeZigZag64(value));
}
// =================================================================
/**
* If writing to a flat array, return the space left in the array.
* Otherwise, throws {@code UnsupportedOperationException}.
*/
public int spaceLeft() {
return limit - position;
}
/**
* Verifies that {@link #spaceLeft()} returns zero. It's common to create
* a byte array that is exactly big enough to hold a message, then write to
* it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()}
* after writing verifies that the message was actually as big as expected,
* which can help catch bugs.
*/
public void checkNoSpaceLeft() {
if (spaceLeft() != 0) {
throw new IllegalStateException(
"Did not write as much data as expected.");
}
}
/**
* If you create a CodedOutputStream around a simple flat array, you must
* not attempt to write more bytes than the array has space. Otherwise,
* this exception will be thrown.
*/
public static class OutOfSpaceException extends IOException {
private static final long serialVersionUID = -6947486886997889499L;
OutOfSpaceException(int position, int limit) {
super("CodedOutputStream was writing to a flat byte array and ran " +
"out of space (pos " + position + " limit " + limit + ").");
}
}
/** Write a single byte. */
public void writeRawByte(final byte value) throws IOException {
if (position == limit) {
// We're writing to a single buffer.
throw new OutOfSpaceException(position, limit);
}
buffer[position++] = value;
}
/** Write a single byte, represented by an integer value. */
public void writeRawByte(final int value) throws IOException {
writeRawByte((byte) value);
}
/** Write an array of bytes. */
public void writeRawBytes(final byte[] value) throws IOException {
writeRawBytes(value, 0, value.length);
}
/** Write part of an array of bytes. */
public void writeRawBytes(final byte[] value, int offset, int length)
throws IOException {
if (limit - position >= length) {
// We have room in the current buffer.
System.arraycopy(value, offset, buffer, position, length);
position += length;
} else {
// We're writing to a single buffer.
throw new OutOfSpaceException(position, limit);
}
}
/** Encode and write a tag. */
public void writeTag(final int fieldNumber, final int wireType)
throws IOException {
writeRawVarint32(WireFormatNano.makeTag(fieldNumber, wireType));
}
/** Compute the number of bytes that would be needed to encode a tag. */
public static int computeTagSize(final int fieldNumber) {
return computeRawVarint32Size(WireFormatNano.makeTag(fieldNumber, 0));
}
/**
* Encode and write a varint. {@code value} is treated as
* unsigned, so it won't be sign-extended if negative.
*/
public void writeRawVarint32(int value) throws IOException {
while (true) {
if ((value & ~0x7F) == 0) {
writeRawByte(value);
return;
} else {
writeRawByte((value & 0x7F) | 0x80);
value >>>= 7;
}
}
}
/**
* Compute the number of bytes that would be needed to encode a varint.
* {@code value} is treated as unsigned, so it won't be sign-extended if
* negative.
*/
public static int computeRawVarint32Size(final int value) {
if ((value & (0xffffffff << 7)) == 0) return 1;
if ((value & (0xffffffff << 14)) == 0) return 2;
if ((value & (0xffffffff << 21)) == 0) return 3;
if ((value & (0xffffffff << 28)) == 0) return 4;
return 5;
}
/** Encode and write a varint. */
public void writeRawVarint64(long value) throws IOException {
while (true) {
if ((value & ~0x7FL) == 0) {
writeRawByte((int)value);
return;
} else {
writeRawByte(((int)value & 0x7F) | 0x80);
value >>>= 7;
}
}
}
/** Compute the number of bytes that would be needed to encode a varint. */
public static int computeRawVarint64Size(final long value) {
if ((value & (0xffffffffffffffffL << 7)) == 0) return 1;
if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
return 10;
}
/** Write a little-endian 32-bit integer. */
public void writeRawLittleEndian32(final int value) throws IOException {
writeRawByte((value ) & 0xFF);
writeRawByte((value >> 8) & 0xFF);
writeRawByte((value >> 16) & 0xFF);
writeRawByte((value >> 24) & 0xFF);
}
public static final int LITTLE_ENDIAN_32_SIZE = 4;
/** Write a little-endian 64-bit integer. */
public void writeRawLittleEndian64(final long value) throws IOException {
writeRawByte((int)(value ) & 0xFF);
writeRawByte((int)(value >> 8) & 0xFF);
writeRawByte((int)(value >> 16) & 0xFF);
writeRawByte((int)(value >> 24) & 0xFF);
writeRawByte((int)(value >> 32) & 0xFF);
writeRawByte((int)(value >> 40) & 0xFF);
writeRawByte((int)(value >> 48) & 0xFF);
writeRawByte((int)(value >> 56) & 0xFF);
}
public static final int LITTLE_ENDIAN_64_SIZE = 8;
/**
* Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
* into values that can be efficiently encoded with varint. (Otherwise,
* negative values must be sign-extended to 64 bits to be varint encoded,
* thus always taking 10 bytes on the wire.)
*
* @param n A signed 32-bit integer.
* @return An unsigned 32-bit integer, stored in a signed int because
* Java has no explicit unsigned support.
*/
public static int encodeZigZag32(final int n) {
// Note: the right-shift must be arithmetic
return (n << 1) ^ (n >> 31);
}
/**
* Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
* into values that can be efficiently encoded with varint. (Otherwise,
* negative values must be sign-extended to 64 bits to be varint encoded,
* thus always taking 10 bytes on the wire.)
*
* @param n A signed 64-bit integer.
* @return An unsigned 64-bit integer, stored in a signed int because
* Java has no explicit unsigned support.
*/
public static long encodeZigZag64(final long n) {
// Note: the right-shift must be arithmetic
return (n << 1) ^ (n >> 63);
}
}

View File

@ -0,0 +1,187 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
import java.io.IOException;
/**
* Base class of those Protocol Buffer messages that need to store unknown fields,
* such as extensions.
*/
public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
extends MessageNano {
/**
* A container for fields unknown to the message, including extensions. Extension fields can
* can be accessed through the {@link #getExtension} and {@link #setExtension} methods.
*/
protected FieldArray unknownFieldData;
@Override
protected int computeSerializedSize() {
int size = 0;
if (unknownFieldData != null) {
for (int i = 0; i < unknownFieldData.size(); i++) {
FieldData field = unknownFieldData.dataAt(i);
size += field.computeSerializedSize();
}
}
return size;
}
@Override
public void writeTo(CodedOutputByteBufferNano output) throws IOException {
if (unknownFieldData == null) {
return;
}
for (int i = 0; i < unknownFieldData.size(); i++) {
FieldData field = unknownFieldData.dataAt(i);
field.writeTo(output);
}
}
/**
* Checks if there is a value stored for the specified extension in this
* message.
*/
public final boolean hasExtension(Extension<M, ?> extension) {
if (unknownFieldData == null) {
return false;
}
FieldData field = unknownFieldData.get(WireFormatNano.getTagFieldNumber(extension.tag));
return field != null;
}
/**
* Gets the value stored in the specified extension of this message.
*/
public final <T> T getExtension(Extension<M, T> extension) {
if (unknownFieldData == null) {
return null;
}
FieldData field = unknownFieldData.get(WireFormatNano.getTagFieldNumber(extension.tag));
return field == null ? null : field.getValue(extension);
}
/**
* Sets the value of the specified extension of this message.
*/
public final <T> M setExtension(Extension<M, T> extension, T value) {
int fieldNumber = WireFormatNano.getTagFieldNumber(extension.tag);
if (value == null) {
if (unknownFieldData != null) {
unknownFieldData.remove(fieldNumber);
if (unknownFieldData.isEmpty()) {
unknownFieldData = null;
}
}
} else {
FieldData field = null;
if (unknownFieldData == null) {
unknownFieldData = new FieldArray();
} else {
field = unknownFieldData.get(fieldNumber);
}
if (field == null) {
unknownFieldData.put(fieldNumber, new FieldData(extension, value));
} else {
field.setValue(extension, value);
}
}
@SuppressWarnings("unchecked") // Generated code should guarantee type safety
M typedThis = (M) this;
return typedThis;
}
/**
* Stores the binary data of an unknown field.
*
* <p>Generated messages will call this for unknown fields if the store_unknown_fields
* option is on.
*
* <p>Note that the tag might be a end-group tag (rather than the start of an unknown field) in
* which case we do not want to add an unknown field entry.
*
* @param input the input buffer.
* @param tag the tag of the field.
* @return {@literal true} unless the tag is an end-group tag.
*/
protected final boolean storeUnknownField(CodedInputByteBufferNano input, int tag)
throws IOException {
int startPos = input.getPosition();
if (!input.skipField(tag)) {
return false; // This wasn't an unknown field, it's an end-group tag.
}
int fieldNumber = WireFormatNano.getTagFieldNumber(tag);
int endPos = input.getPosition();
byte[] bytes = input.getData(startPos, endPos - startPos);
UnknownFieldData unknownField = new UnknownFieldData(tag, bytes);
FieldData field = null;
if (unknownFieldData == null) {
unknownFieldData = new FieldArray();
} else {
field = unknownFieldData.get(fieldNumber);
}
if (field == null) {
field = new FieldData();
unknownFieldData.put(fieldNumber, field);
}
field.addUnknownField(unknownField);
return true;
}
/**
* Returns whether the stored unknown field data in this message is equivalent to that in the
* other message.
*
* @param other the other message.
* @return whether the two sets of unknown field data are equal.
*/
protected final boolean unknownFieldDataEquals(M other) {
if (unknownFieldData == null || unknownFieldData.isEmpty()) {
return other.unknownFieldData == null || other.unknownFieldData.isEmpty();
} else {
return unknownFieldData.equals(other.unknownFieldData);
}
}
/**
* Computes the hashcode representing the unknown field data stored in this message.
*
* @return the hashcode for the unknown field data.
*/
protected final int unknownFieldDataHashCode() {
return (unknownFieldData == null || unknownFieldData.isEmpty()
? 0 : unknownFieldData.hashCode());
}
}

View File

@ -0,0 +1,722 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
/**
* Represents an extension.
*
* @author bduff@google.com (Brian Duff)
* @author maxtroy@google.com (Max Cai)
* @param <M> the type of the extendable message this extension is for.
* @param <T> the Java type of the extension; see {@link #clazz}.
*/
public class Extension<M extends ExtendableMessageNano<M>, T> {
/*
* Because we typically only define message-typed extensions, the Extension class hierarchy is
* designed as follows, to allow a big amount of code in this file to be removed by ProGuard:
*
* Extension // ready to use for message/group typed extensions
* Δ
* |
* PrimitiveExtension // for primitive/enum typed extensions
*/
public static final int TYPE_DOUBLE = 1;
public static final int TYPE_FLOAT = 2;
public static final int TYPE_INT64 = 3;
public static final int TYPE_UINT64 = 4;
public static final int TYPE_INT32 = 5;
public static final int TYPE_FIXED64 = 6;
public static final int TYPE_FIXED32 = 7;
public static final int TYPE_BOOL = 8;
public static final int TYPE_STRING = 9;
public static final int TYPE_GROUP = 10;
public static final int TYPE_MESSAGE = 11;
public static final int TYPE_BYTES = 12;
public static final int TYPE_UINT32 = 13;
public static final int TYPE_ENUM = 14;
public static final int TYPE_SFIXED32 = 15;
public static final int TYPE_SFIXED64 = 16;
public static final int TYPE_SINT32 = 17;
public static final int TYPE_SINT64 = 18;
/**
* Creates an {@code Extension} of the given message type and tag number.
* Should be used by the generated code only.
*
* @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
*/
public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
Extension<M, T> createMessageTyped(int type, Class<T> clazz, int tag) {
return new Extension<M, T>(type, clazz, tag, false);
}
/**
* Creates a repeated {@code Extension} of the given message type and tag number.
* Should be used by the generated code only.
*
* @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
*/
public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
Extension<M, T[]> createRepeatedMessageTyped(int type, Class<T[]> clazz, int tag) {
return new Extension<M, T[]>(type, clazz, tag, true);
}
/**
* Creates an {@code Extension} of the given primitive type and tag number.
* Should be used by the generated code only.
*
* @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP}
* @param clazz the boxed Java type of this extension
*/
public static <M extends ExtendableMessageNano<M>, T>
Extension<M, T> createPrimitiveTyped(int type, Class<T> clazz, int tag) {
return new PrimitiveExtension<M, T>(type, clazz, tag, false, 0, 0);
}
/**
* Creates a repeated {@code Extension} of the given primitive type and tag number.
* Should be used by the generated code only.
*
* @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP}
* @param clazz the Java array type of this extension, with an unboxed component type
*/
public static <M extends ExtendableMessageNano<M>, T>
Extension<M, T> createRepeatedPrimitiveTyped(
int type, Class<T> clazz, int tag, int nonPackedTag, int packedTag) {
return new PrimitiveExtension<M, T>(type, clazz, tag, true, nonPackedTag, packedTag);
}
/**
* Protocol Buffer type of this extension; one of the {@code TYPE_} constants.
*/
protected final int type;
/**
* Java type of this extension. For a singular extension, this is the boxed Java type for the
* Protocol Buffer {@link #type}; for a repeated extension, this is an array type whose
* component type is the unboxed Java type for {@link #type}. For example, for a singular
* {@code int32}/{@link #TYPE_INT32} extension, this equals {@code Integer.class}; for a
* repeated {@code int32} extension, this equals {@code int[].class}.
*/
protected final Class<T> clazz;
/**
* Tag number of this extension.
*/
public final int tag;
/**
* Whether this extension is repeated.
*/
protected final boolean repeated;
private Extension(int type, Class<T> clazz, int tag, boolean repeated) {
this.type = type;
this.clazz = clazz;
this.tag = tag;
this.repeated = repeated;
}
/**
* Returns the value of this extension stored in the given list of unknown fields, or
* {@code null} if no unknown fields matches this extension.
*
* @param unknownFields a list of {@link UnknownFieldData}. All of the elements must have a tag
* that matches this Extension's tag.
*
*/
final T getValueFrom(List<UnknownFieldData> unknownFields) {
if (unknownFields == null) {
return null;
}
return repeated ? getRepeatedValueFrom(unknownFields) : getSingularValueFrom(unknownFields);
}
private T getRepeatedValueFrom(List<UnknownFieldData> unknownFields) {
// For repeated extensions, read all matching unknown fields in their original order.
List<Object> resultList = new ArrayList<Object>();
for (int i = 0; i < unknownFields.size(); i++) {
UnknownFieldData data = unknownFields.get(i);
if (data.bytes.length != 0) {
readDataInto(data, resultList);
}
}
int resultSize = resultList.size();
if (resultSize == 0) {
return null;
} else {
T result = clazz.cast(Array.newInstance(clazz.getComponentType(), resultSize));
for (int i = 0; i < resultSize; i++) {
Array.set(result, i, resultList.get(i));
}
return result;
}
}
private T getSingularValueFrom(List<UnknownFieldData> unknownFields) {
// For singular extensions, get the last piece of data stored under this extension.
if (unknownFields.isEmpty()) {
return null;
}
UnknownFieldData lastData = unknownFields.get(unknownFields.size() - 1);
return clazz.cast(readData(CodedInputByteBufferNano.newInstance(lastData.bytes)));
}
protected Object readData(CodedInputByteBufferNano input) {
// This implementation is for message/group extensions.
Class<?> messageType = repeated ? clazz.getComponentType() : clazz;
try {
switch (type) {
case TYPE_GROUP:
MessageNano group = (MessageNano) messageType.newInstance();
input.readGroup(group, WireFormatNano.getTagFieldNumber(tag));
return group;
case TYPE_MESSAGE:
MessageNano message = (MessageNano) messageType.newInstance();
input.readMessage(message);
return message;
default:
throw new IllegalArgumentException("Unknown type " + type);
}
} catch (InstantiationException e) {
throw new IllegalArgumentException(
"Error creating instance of class " + messageType, e);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(
"Error creating instance of class " + messageType, e);
} catch (IOException e) {
throw new IllegalArgumentException("Error reading extension field", e);
}
}
protected void readDataInto(UnknownFieldData data, List<Object> resultList) {
// This implementation is for message/group extensions.
resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes)));
}
void writeTo(Object value, CodedOutputByteBufferNano output) throws IOException {
if (repeated) {
writeRepeatedData(value, output);
} else {
writeSingularData(value, output);
}
}
protected void writeSingularData(Object value, CodedOutputByteBufferNano out) {
// This implementation is for message/group extensions.
try {
out.writeRawVarint32(tag);
switch (type) {
case TYPE_GROUP:
MessageNano groupValue = (MessageNano) value;
int fieldNumber = WireFormatNano.getTagFieldNumber(tag);
out.writeGroupNoTag(groupValue);
// The endgroup tag must be included in the data payload.
out.writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP);
break;
case TYPE_MESSAGE:
MessageNano messageValue = (MessageNano) value;
out.writeMessageNoTag(messageValue);
break;
default:
throw new IllegalArgumentException("Unknown type " + type);
}
} catch (IOException e) {
// Should not happen
throw new IllegalStateException(e);
}
}
protected void writeRepeatedData(Object array, CodedOutputByteBufferNano output) {
// This implementation is for non-packed extensions.
int arrayLength = Array.getLength(array);
for (int i = 0; i < arrayLength; i++) {
Object element = Array.get(array, i);
if (element != null) {
writeSingularData(element, output);
}
}
}
int computeSerializedSize(Object value) {
if (repeated) {
return computeRepeatedSerializedSize(value);
} else {
return computeSingularSerializedSize(value);
}
}
protected int computeRepeatedSerializedSize(Object array) {
// This implementation is for non-packed extensions.
int size = 0;
int arrayLength = Array.getLength(array);
for (int i = 0; i < arrayLength; i++) {
Object element = Array.get(array, i);
if (element != null) {
size += computeSingularSerializedSize(Array.get(array, i));
}
}
return size;
}
protected int computeSingularSerializedSize(Object value) {
// This implementation is for message/group extensions.
int fieldNumber = WireFormatNano.getTagFieldNumber(tag);
switch (type) {
case TYPE_GROUP:
MessageNano groupValue = (MessageNano) value;
return CodedOutputByteBufferNano.computeGroupSize(fieldNumber, groupValue);
case TYPE_MESSAGE:
MessageNano messageValue = (MessageNano) value;
return CodedOutputByteBufferNano.computeMessageSize(fieldNumber, messageValue);
default:
throw new IllegalArgumentException("Unknown type " + type);
}
}
/**
* Represents an extension of a primitive (including enum) type. If there is no primitive
* extensions, this subclass will be removable by ProGuard.
*/
private static class PrimitiveExtension<M extends ExtendableMessageNano<M>, T>
extends Extension<M, T> {
/**
* Tag of a piece of non-packed data from the wire compatible with this extension.
*/
private final int nonPackedTag;
/**
* Tag of a piece of packed data from the wire compatible with this extension.
* 0 if the type of this extension is not packable.
*/
private final int packedTag;
public PrimitiveExtension(int type, Class<T> clazz, int tag, boolean repeated,
int nonPackedTag, int packedTag) {
super(type, clazz, tag, repeated);
this.nonPackedTag = nonPackedTag;
this.packedTag = packedTag;
}
@Override
protected Object readData(CodedInputByteBufferNano input) {
try {
switch (type) {
case TYPE_DOUBLE:
return input.readDouble();
case TYPE_FLOAT:
return input.readFloat();
case TYPE_INT64:
return input.readInt64();
case TYPE_UINT64:
return input.readUInt64();
case TYPE_INT32:
return input.readInt32();
case TYPE_FIXED64:
return input.readFixed64();
case TYPE_FIXED32:
return input.readFixed32();
case TYPE_BOOL:
return input.readBool();
case TYPE_STRING:
return input.readString();
case TYPE_BYTES:
return input.readBytes();
case TYPE_UINT32:
return input.readUInt32();
case TYPE_ENUM:
return input.readEnum();
case TYPE_SFIXED32:
return input.readSFixed32();
case TYPE_SFIXED64:
return input.readSFixed64();
case TYPE_SINT32:
return input.readSInt32();
case TYPE_SINT64:
return input.readSInt64();
default:
throw new IllegalArgumentException("Unknown type " + type);
}
} catch (IOException e) {
throw new IllegalArgumentException("Error reading extension field", e);
}
}
@Override
protected void readDataInto(UnknownFieldData data, List<Object> resultList) {
// This implementation is for primitive typed extensions,
// which can read both packed and non-packed data.
if (data.tag == nonPackedTag) {
resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes)));
} else {
CodedInputByteBufferNano buffer =
CodedInputByteBufferNano.newInstance(data.bytes);
try {
buffer.pushLimit(buffer.readRawVarint32()); // length limit
} catch (IOException e) {
throw new IllegalArgumentException("Error reading extension field", e);
}
while (!buffer.isAtEnd()) {
resultList.add(readData(buffer));
}
}
}
@Override
protected final void writeSingularData(Object value, CodedOutputByteBufferNano output) {
try {
output.writeRawVarint32(tag);
switch (type) {
case TYPE_DOUBLE:
Double doubleValue = (Double) value;
output.writeDoubleNoTag(doubleValue);
break;
case TYPE_FLOAT:
Float floatValue = (Float) value;
output.writeFloatNoTag(floatValue);
break;
case TYPE_INT64:
Long int64Value = (Long) value;
output.writeInt64NoTag(int64Value);
break;
case TYPE_UINT64:
Long uint64Value = (Long) value;
output.writeUInt64NoTag(uint64Value);
break;
case TYPE_INT32:
Integer int32Value = (Integer) value;
output.writeInt32NoTag(int32Value);
break;
case TYPE_FIXED64:
Long fixed64Value = (Long) value;
output.writeFixed64NoTag(fixed64Value);
break;
case TYPE_FIXED32:
Integer fixed32Value = (Integer) value;
output.writeFixed32NoTag(fixed32Value);
break;
case TYPE_BOOL:
Boolean boolValue = (Boolean) value;
output.writeBoolNoTag(boolValue);
break;
case TYPE_STRING:
String stringValue = (String) value;
output.writeStringNoTag(stringValue);
break;
case TYPE_BYTES:
byte[] bytesValue = (byte[]) value;
output.writeBytesNoTag(bytesValue);
break;
case TYPE_UINT32:
Integer uint32Value = (Integer) value;
output.writeUInt32NoTag(uint32Value);
break;
case TYPE_ENUM:
Integer enumValue = (Integer) value;
output.writeEnumNoTag(enumValue);
break;
case TYPE_SFIXED32:
Integer sfixed32Value = (Integer) value;
output.writeSFixed32NoTag(sfixed32Value);
break;
case TYPE_SFIXED64:
Long sfixed64Value = (Long) value;
output.writeSFixed64NoTag(sfixed64Value);
break;
case TYPE_SINT32:
Integer sint32Value = (Integer) value;
output.writeSInt32NoTag(sint32Value);
break;
case TYPE_SINT64:
Long sint64Value = (Long) value;
output.writeSInt64NoTag(sint64Value);
break;
default:
throw new IllegalArgumentException("Unknown type " + type);
}
} catch (IOException e) {
// Should not happen
throw new IllegalStateException(e);
}
}
@Override
protected void writeRepeatedData(Object array, CodedOutputByteBufferNano output) {
if (tag == nonPackedTag) {
// Use base implementation for non-packed data
super.writeRepeatedData(array, output);
} else if (tag == packedTag) {
// Packed. Note that the array element type is guaranteed to be primitive, so there
// won't be any null elements, so no null check in this block.
int arrayLength = Array.getLength(array);
int dataSize = computePackedDataSize(array);
try {
output.writeRawVarint32(tag);
output.writeRawVarint32(dataSize);
switch (type) {
case TYPE_BOOL:
for (int i = 0; i < arrayLength; i++) {
output.writeBoolNoTag(Array.getBoolean(array, i));
}
break;
case TYPE_FIXED32:
for (int i = 0; i < arrayLength; i++) {
output.writeFixed32NoTag(Array.getInt(array, i));
}
break;
case TYPE_SFIXED32:
for (int i = 0; i < arrayLength; i++) {
output.writeSFixed32NoTag(Array.getInt(array, i));
}
break;
case TYPE_FLOAT:
for (int i = 0; i < arrayLength; i++) {
output.writeFloatNoTag(Array.getFloat(array, i));
}
break;
case TYPE_FIXED64:
for (int i = 0; i < arrayLength; i++) {
output.writeFixed64NoTag(Array.getLong(array, i));
}
break;
case TYPE_SFIXED64:
for (int i = 0; i < arrayLength; i++) {
output.writeSFixed64NoTag(Array.getLong(array, i));
}
break;
case TYPE_DOUBLE:
for (int i = 0; i < arrayLength; i++) {
output.writeDoubleNoTag(Array.getDouble(array, i));
}
break;
case TYPE_INT32:
for (int i = 0; i < arrayLength; i++) {
output.writeInt32NoTag(Array.getInt(array, i));
}
break;
case TYPE_SINT32:
for (int i = 0; i < arrayLength; i++) {
output.writeSInt32NoTag(Array.getInt(array, i));
}
break;
case TYPE_UINT32:
for (int i = 0; i < arrayLength; i++) {
output.writeUInt32NoTag(Array.getInt(array, i));
}
break;
case TYPE_INT64:
for (int i = 0; i < arrayLength; i++) {
output.writeInt64NoTag(Array.getLong(array, i));
}
break;
case TYPE_SINT64:
for (int i = 0; i < arrayLength; i++) {
output.writeSInt64NoTag(Array.getLong(array, i));
}
break;
case TYPE_UINT64:
for (int i = 0; i < arrayLength; i++) {
output.writeUInt64NoTag(Array.getLong(array, i));
}
break;
case TYPE_ENUM:
for (int i = 0; i < arrayLength; i++) {
output.writeEnumNoTag(Array.getInt(array, i));
}
break;
default:
throw new IllegalArgumentException("Unpackable type " + type);
}
} catch (IOException e) {
// Should not happen.
throw new IllegalStateException(e);
}
} else {
throw new IllegalArgumentException("Unexpected repeated extension tag " + tag
+ ", unequal to both non-packed variant " + nonPackedTag
+ " and packed variant " + packedTag);
}
}
private int computePackedDataSize(Object array) {
int dataSize = 0;
int arrayLength = Array.getLength(array);
switch (type) {
case TYPE_BOOL:
// Bools are stored as int32 but just as 0 or 1, so 1 byte each.
dataSize = arrayLength;
break;
case TYPE_FIXED32:
case TYPE_SFIXED32:
case TYPE_FLOAT:
dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_32_SIZE;
break;
case TYPE_FIXED64:
case TYPE_SFIXED64:
case TYPE_DOUBLE:
dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_64_SIZE;
break;
case TYPE_INT32:
for (int i = 0; i < arrayLength; i++) {
dataSize += CodedOutputByteBufferNano.computeInt32SizeNoTag(
Array.getInt(array, i));
}
break;
case TYPE_SINT32:
for (int i = 0; i < arrayLength; i++) {
dataSize += CodedOutputByteBufferNano.computeSInt32SizeNoTag(
Array.getInt(array, i));
}
break;
case TYPE_UINT32:
for (int i = 0; i < arrayLength; i++) {
dataSize += CodedOutputByteBufferNano.computeUInt32SizeNoTag(
Array.getInt(array, i));
}
break;
case TYPE_INT64:
for (int i = 0; i < arrayLength; i++) {
dataSize += CodedOutputByteBufferNano.computeInt64SizeNoTag(
Array.getLong(array, i));
}
break;
case TYPE_SINT64:
for (int i = 0; i < arrayLength; i++) {
dataSize += CodedOutputByteBufferNano.computeSInt64SizeNoTag(
Array.getLong(array, i));
}
break;
case TYPE_UINT64:
for (int i = 0; i < arrayLength; i++) {
dataSize += CodedOutputByteBufferNano.computeUInt64SizeNoTag(
Array.getLong(array, i));
}
break;
case TYPE_ENUM:
for (int i = 0; i < arrayLength; i++) {
dataSize += CodedOutputByteBufferNano.computeEnumSizeNoTag(
Array.getInt(array, i));
}
break;
default:
throw new IllegalArgumentException("Unexpected non-packable type " + type);
}
return dataSize;
}
@Override
protected int computeRepeatedSerializedSize(Object array) {
if (tag == nonPackedTag) {
// Use base implementation for non-packed data
return super.computeRepeatedSerializedSize(array);
} else if (tag == packedTag) {
// Packed.
int dataSize = computePackedDataSize(array);
int payloadSize =
dataSize + CodedOutputByteBufferNano.computeRawVarint32Size(dataSize);
return payloadSize + CodedOutputByteBufferNano.computeRawVarint32Size(tag);
} else {
throw new IllegalArgumentException("Unexpected repeated extension tag " + tag
+ ", unequal to both non-packed variant " + nonPackedTag
+ " and packed variant " + packedTag);
}
}
@Override
protected final int computeSingularSerializedSize(Object value) {
int fieldNumber = WireFormatNano.getTagFieldNumber(tag);
switch (type) {
case TYPE_DOUBLE:
Double doubleValue = (Double) value;
return CodedOutputByteBufferNano.computeDoubleSize(fieldNumber, doubleValue);
case TYPE_FLOAT:
Float floatValue = (Float) value;
return CodedOutputByteBufferNano.computeFloatSize(fieldNumber, floatValue);
case TYPE_INT64:
Long int64Value = (Long) value;
return CodedOutputByteBufferNano.computeInt64Size(fieldNumber, int64Value);
case TYPE_UINT64:
Long uint64Value = (Long) value;
return CodedOutputByteBufferNano.computeUInt64Size(fieldNumber, uint64Value);
case TYPE_INT32:
Integer int32Value = (Integer) value;
return CodedOutputByteBufferNano.computeInt32Size(fieldNumber, int32Value);
case TYPE_FIXED64:
Long fixed64Value = (Long) value;
return CodedOutputByteBufferNano.computeFixed64Size(fieldNumber, fixed64Value);
case TYPE_FIXED32:
Integer fixed32Value = (Integer) value;
return CodedOutputByteBufferNano.computeFixed32Size(fieldNumber, fixed32Value);
case TYPE_BOOL:
Boolean boolValue = (Boolean) value;
return CodedOutputByteBufferNano.computeBoolSize(fieldNumber, boolValue);
case TYPE_STRING:
String stringValue = (String) value;
return CodedOutputByteBufferNano.computeStringSize(fieldNumber, stringValue);
case TYPE_BYTES:
byte[] bytesValue = (byte[]) value;
return CodedOutputByteBufferNano.computeBytesSize(fieldNumber, bytesValue);
case TYPE_UINT32:
Integer uint32Value = (Integer) value;
return CodedOutputByteBufferNano.computeUInt32Size(fieldNumber, uint32Value);
case TYPE_ENUM:
Integer enumValue = (Integer) value;
return CodedOutputByteBufferNano.computeEnumSize(fieldNumber, enumValue);
case TYPE_SFIXED32:
Integer sfixed32Value = (Integer) value;
return CodedOutputByteBufferNano.computeSFixed32Size(fieldNumber,
sfixed32Value);
case TYPE_SFIXED64:
Long sfixed64Value = (Long) value;
return CodedOutputByteBufferNano.computeSFixed64Size(fieldNumber,
sfixed64Value);
case TYPE_SINT32:
Integer sint32Value = (Integer) value;
return CodedOutputByteBufferNano.computeSInt32Size(fieldNumber, sint32Value);
case TYPE_SINT64:
Long sint64Value = (Long) value;
return CodedOutputByteBufferNano.computeSInt64Size(fieldNumber, sint64Value);
default:
throw new IllegalArgumentException("Unknown type " + type);
}
}
}
}

View File

@ -0,0 +1,273 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2014 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
/**
* A custom version of {@link android.util.SparseArray} with the minimal API
* for storing {@link FieldData} objects.
*
* Based on {@link android.support.v4.util.SpareArrayCompat}.
*/
class FieldArray {
private static final FieldData DELETED = new FieldData();
private boolean mGarbage = false;
private int[] mFieldNumbers;
private FieldData[] mData;
private int mSize;
/**
* Creates a new FieldArray containing no fields.
*/
public FieldArray() {
this(10);
}
/**
* Creates a new FieldArray containing no mappings that will not
* require any additional memory allocation to store the specified
* number of mappings.
*/
public FieldArray(int initialCapacity) {
initialCapacity = idealIntArraySize(initialCapacity);
mFieldNumbers = new int[initialCapacity];
mData = new FieldData[initialCapacity];
mSize = 0;
}
/**
* Gets the FieldData mapped from the specified fieldNumber, or <code>null</code>
* if no such mapping has been made.
*/
public FieldData get(int fieldNumber) {
int i = binarySearch(fieldNumber);
if (i < 0 || mData[i] == DELETED) {
return null;
} else {
return mData[i];
}
}
/**
* Removes the data from the specified fieldNumber, if there was any.
*/
public void remove(int fieldNumber) {
int i = binarySearch(fieldNumber);
if (i >= 0 && mData[i] != DELETED) {
mData[i] = DELETED;
mGarbage = true;
}
}
private void gc() {
int n = mSize;
int o = 0;
int[] keys = mFieldNumbers;
FieldData[] values = mData;
for (int i = 0; i < n; i++) {
FieldData val = values[i];
if (val != DELETED) {
if (i != o) {
keys[o] = keys[i];
values[o] = val;
values[i] = null;
}
o++;
}
}
mGarbage = false;
mSize = o;
}
/**
* Adds a mapping from the specified fieldNumber to the specified data,
* replacing the previous mapping if there was one.
*/
public void put(int fieldNumber, FieldData data) {
int i = binarySearch(fieldNumber);
if (i >= 0) {
mData[i] = data;
} else {
i = ~i;
if (i < mSize && mData[i] == DELETED) {
mFieldNumbers[i] = fieldNumber;
mData[i] = data;
return;
}
if (mGarbage && mSize >= mFieldNumbers.length) {
gc();
// Search again because indices may have changed.
i = ~ binarySearch(fieldNumber);
}
if (mSize >= mFieldNumbers.length) {
int n = idealIntArraySize(mSize + 1);
int[] nkeys = new int[n];
FieldData[] nvalues = new FieldData[n];
System.arraycopy(mFieldNumbers, 0, nkeys, 0, mFieldNumbers.length);
System.arraycopy(mData, 0, nvalues, 0, mData.length);
mFieldNumbers = nkeys;
mData = nvalues;
}
if (mSize - i != 0) {
System.arraycopy(mFieldNumbers, i, mFieldNumbers, i + 1, mSize - i);
System.arraycopy(mData, i, mData, i + 1, mSize - i);
}
mFieldNumbers[i] = fieldNumber;
mData[i] = data;
mSize++;
}
}
/**
* Returns the number of key-value mappings that this FieldArray
* currently stores.
*/
public int size() {
if (mGarbage) {
gc();
}
return mSize;
}
public boolean isEmpty() {
return size() == 0;
}
/**
* Given an index in the range <code>0...size()-1</code>, returns
* the value from the <code>index</code>th key-value mapping that this
* FieldArray stores.
*/
public FieldData dataAt(int index) {
if (mGarbage) {
gc();
}
return mData[index];
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof FieldArray)) {
return false;
}
FieldArray other = (FieldArray) o;
if (size() != other.size()) { // size() will call gc() if necessary.
return false;
}
return arrayEquals(mFieldNumbers, other.mFieldNumbers, mSize) &&
arrayEquals(mData, other.mData, mSize);
}
@Override
public int hashCode() {
if (mGarbage) {
gc();
}
int result = 17;
for (int i = 0; i < mSize; i++) {
result = 31 * result + mFieldNumbers[i];
result = 31 * result + mData[i].hashCode();
}
return result;
}
private int idealIntArraySize(int need) {
return idealByteArraySize(need * 4) / 4;
}
private int idealByteArraySize(int need) {
for (int i = 4; i < 32; i++)
if (need <= (1 << i) - 12)
return (1 << i) - 12;
return need;
}
private int binarySearch(int value) {
int lo = 0;
int hi = mSize - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
int midVal = mFieldNumbers[mid];
if (midVal < value) {
lo = mid + 1;
} else if (midVal > value) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
private boolean arrayEquals(int[] a, int[] b, int size) {
for (int i = 0; i < size; i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}
private boolean arrayEquals(FieldData[] a, FieldData[] b, int size) {
for (int i = 0; i < size; i++) {
if (!a[i].equals(b[i])) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,190 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2014 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Stores unknown fields. These might be extensions or fields that the generated API doesn't
* know about yet.
*/
class FieldData {
private Extension<?, ?> cachedExtension;
private Object value;
/** The serialised values for this object. Will be cleared if getValue is called */
private List<UnknownFieldData> unknownFieldData;
<T> FieldData(Extension<?, T> extension, T newValue) {
cachedExtension = extension;
value = newValue;
}
FieldData() {
unknownFieldData = new ArrayList<UnknownFieldData>();
}
void addUnknownField(UnknownFieldData unknownField) {
unknownFieldData.add(unknownField);
}
UnknownFieldData getUnknownField(int index) {
if (unknownFieldData == null) {
return null;
}
if (index < unknownFieldData.size()) {
return unknownFieldData.get(index);
}
return null;
}
int getUnknownFieldSize() {
if (unknownFieldData == null) {
return 0;
}
return unknownFieldData.size();
}
<T> T getValue(Extension<?, T> extension) {
if (value != null){
if (cachedExtension != extension) { // Extension objects are singletons.
throw new IllegalStateException(
"Tried to getExtension with a differernt Extension.");
}
} else {
cachedExtension = extension;
value = extension.getValueFrom(unknownFieldData);
unknownFieldData = null;
}
return (T) value;
}
<T> void setValue(Extension<?, T> extension, T newValue) {
cachedExtension = extension;
value = newValue;
unknownFieldData = null;
}
int computeSerializedSize() {
int size = 0;
if (value != null) {
size = cachedExtension.computeSerializedSize(value);
} else {
for (UnknownFieldData unknownField : unknownFieldData) {
size += unknownField.computeSerializedSize();
}
}
return size;
}
void writeTo(CodedOutputByteBufferNano output) throws IOException {
if (value != null) {
cachedExtension.writeTo(value, output);
} else {
for (UnknownFieldData unknownField : unknownFieldData) {
unknownField.writeTo(output);
}
}
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof FieldData)) {
return false;
}
FieldData other = (FieldData) o;
if (value != null && other.value != null) {
// If both objects have deserialized values, compare those.
// Since unknown fields are only compared if messages have generated equals methods
// we know this will be a meaningful comparison (not identity) for all values.
if (cachedExtension != other.cachedExtension) { // Extension objects are singletons.
return false;
}
if (!cachedExtension.clazz.isArray()) {
// Can't test (!cachedExtension.repeated) due to 'bytes' -> 'byte[]'
return value.equals(other.value);
}
if (value instanceof byte[]) {
return Arrays.equals((byte[]) value, (byte[]) other.value);
} else if (value instanceof int[]) {
return Arrays.equals((int[]) value, (int[]) other.value);
} else if (value instanceof long[]) {
return Arrays.equals((long[]) value, (long[]) other.value);
} else if (value instanceof float[]) {
return Arrays.equals((float[]) value, (float[]) other.value);
} else if (value instanceof double[]) {
return Arrays.equals((double[]) value, (double[]) other.value);
} else if (value instanceof boolean[]) {
return Arrays.equals((boolean[]) value, (boolean[]) other.value);
} else {
return Arrays.deepEquals((Object[]) value, (Object[]) other.value);
}
}
if (unknownFieldData != null && other.unknownFieldData != null) {
// If both objects have byte arrays compare those directly.
return unknownFieldData.equals(other.unknownFieldData);
}
try {
// As a last resort, serialize and compare the resulting byte arrays.
return Arrays.equals(toByteArray(), other.toByteArray());
} catch (IOException e) {
// Should not happen.
throw new IllegalStateException(e);
}
}
@Override
public int hashCode() {
int result = 17;
try {
// The only way to generate a consistent hash is to use the serialized form.
result = 31 * result + Arrays.hashCode(toByteArray());
} catch (IOException e) {
// Should not happen.
throw new IllegalStateException(e);
}
return result;
}
private byte[] toByteArray() throws IOException {
byte[] result = new byte[computeSerializedSize()];
CodedOutputByteBufferNano output = CodedOutputByteBufferNano.newInstance(result);
writeTo(output);
return result;
}
}

View File

@ -0,0 +1,333 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/**
* The classes contained within are used internally by the Protocol Buffer
* library and generated message implementations. They are public only because
* those generated messages do not reside in the {@code protobuf} package.
* Others should not use this class directly.
*
* @author kenton@google.com (Kenton Varda)
*/
public final class InternalNano {
private InternalNano() {}
/**
* An object to provide synchronization when lazily initializing static fields
* of {@link MessageNano} subclasses.
* <p>
* To enable earlier versions of ProGuard to inline short methods from a
* generated MessageNano subclass to the call sites, that class must not have
* a class initializer, which will be created if there is any static variable
* initializers. To lazily initialize the static variables in a thread-safe
* manner, the initialization code will synchronize on this object.
*/
public static final Object LAZY_INIT_LOCK = new Object();
/**
* Helper called by generated code to construct default values for string
* fields.
* <p>
* The protocol compiler does not actually contain a UTF-8 decoder -- it
* just pushes UTF-8-encoded text around without touching it. The one place
* where this presents a problem is when generating Java string literals.
* Unicode characters in the string literal would normally need to be encoded
* using a Unicode escape sequence, which would require decoding them.
* To get around this, protoc instead embeds the UTF-8 bytes into the
* generated code and leaves it to the runtime library to decode them.
* <p>
* It gets worse, though. If protoc just generated a byte array, like:
* new byte[] {0x12, 0x34, 0x56, 0x78}
* Java actually generates *code* which allocates an array and then fills
* in each value. This is much less efficient than just embedding the bytes
* directly into the bytecode. To get around this, we need another
* work-around. String literals are embedded directly, so protoc actually
* generates a string literal corresponding to the bytes. The easiest way
* to do this is to use the ISO-8859-1 character set, which corresponds to
* the first 256 characters of the Unicode range. Protoc can then use
* good old CEscape to generate the string.
* <p>
* So we have a string literal which represents a set of bytes which
* represents another string. This function -- stringDefaultValue --
* converts from the generated string to the string we actually want. The
* generated code calls this automatically.
*/
public static String stringDefaultValue(String bytes) {
try {
return new String(bytes.getBytes("ISO-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
// This should never happen since all JVMs are required to implement
// both of the above character sets.
throw new IllegalStateException(
"Java VM does not support a standard character set.", e);
}
}
/**
* Helper called by generated code to construct default values for bytes
* fields.
* <p>
* This is a lot like {@link #stringDefaultValue}, but for bytes fields.
* In this case we only need the second of the two hacks -- allowing us to
* embed raw bytes as a string literal with ISO-8859-1 encoding.
*/
public static byte[] bytesDefaultValue(String bytes) {
try {
return bytes.getBytes("ISO-8859-1");
} catch (UnsupportedEncodingException e) {
// This should never happen since all JVMs are required to implement
// ISO-8859-1.
throw new IllegalStateException(
"Java VM does not support a standard character set.", e);
}
}
/**
* Helper function to convert a string into UTF-8 while turning the
* UnsupportedEncodingException to a RuntimeException.
*/
public static byte[] copyFromUtf8(final String text) {
try {
return text.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not supported?");
}
}
/**
* Checks repeated int field equality; null-value and 0-length fields are
* considered equal.
*/
public static boolean equals(int[] field1, int[] field2) {
if (field1 == null || field1.length == 0) {
return field2 == null || field2.length == 0;
} else {
return Arrays.equals(field1, field2);
}
}
/**
* Checks repeated long field equality; null-value and 0-length fields are
* considered equal.
*/
public static boolean equals(long[] field1, long[] field2) {
if (field1 == null || field1.length == 0) {
return field2 == null || field2.length == 0;
} else {
return Arrays.equals(field1, field2);
}
}
/**
* Checks repeated float field equality; null-value and 0-length fields are
* considered equal.
*/
public static boolean equals(float[] field1, float[] field2) {
if (field1 == null || field1.length == 0) {
return field2 == null || field2.length == 0;
} else {
return Arrays.equals(field1, field2);
}
}
/**
* Checks repeated double field equality; null-value and 0-length fields are
* considered equal.
*/
public static boolean equals(double[] field1, double[] field2) {
if (field1 == null || field1.length == 0) {
return field2 == null || field2.length == 0;
} else {
return Arrays.equals(field1, field2);
}
}
/**
* Checks repeated boolean field equality; null-value and 0-length fields are
* considered equal.
*/
public static boolean equals(boolean[] field1, boolean[] field2) {
if (field1 == null || field1.length == 0) {
return field2 == null || field2.length == 0;
} else {
return Arrays.equals(field1, field2);
}
}
/**
* Checks repeated bytes field equality. Only non-null elements are tested.
* Returns true if the two fields have the same sequence of non-null
* elements. Null-value fields and fields of any length with only null
* elements are considered equal.
*/
public static boolean equals(byte[][] field1, byte[][] field2) {
int index1 = 0;
int length1 = field1 == null ? 0 : field1.length;
int index2 = 0;
int length2 = field2 == null ? 0 : field2.length;
while (true) {
while (index1 < length1 && field1[index1] == null) {
index1++;
}
while (index2 < length2 && field2[index2] == null) {
index2++;
}
boolean atEndOf1 = index1 >= length1;
boolean atEndOf2 = index2 >= length2;
if (atEndOf1 && atEndOf2) {
// no more non-null elements to test in both arrays
return true;
} else if (atEndOf1 != atEndOf2) {
// one of the arrays have extra non-null elements
return false;
} else if (!Arrays.equals(field1[index1], field2[index2])) {
// element mismatch
return false;
}
index1++;
index2++;
}
}
/**
* Checks repeated string/message field equality. Only non-null elements are
* tested. Returns true if the two fields have the same sequence of non-null
* elements. Null-value fields and fields of any length with only null
* elements are considered equal.
*/
public static boolean equals(Object[] field1, Object[] field2) {
int index1 = 0;
int length1 = field1 == null ? 0 : field1.length;
int index2 = 0;
int length2 = field2 == null ? 0 : field2.length;
while (true) {
while (index1 < length1 && field1[index1] == null) {
index1++;
}
while (index2 < length2 && field2[index2] == null) {
index2++;
}
boolean atEndOf1 = index1 >= length1;
boolean atEndOf2 = index2 >= length2;
if (atEndOf1 && atEndOf2) {
// no more non-null elements to test in both arrays
return true;
} else if (atEndOf1 != atEndOf2) {
// one of the arrays have extra non-null elements
return false;
} else if (!field1[index1].equals(field2[index2])) {
// element mismatch
return false;
}
index1++;
index2++;
}
}
/**
* Computes the hash code of a repeated int field. Null-value and 0-length
* fields have the same hash code.
*/
public static int hashCode(int[] field) {
return field == null || field.length == 0 ? 0 : Arrays.hashCode(field);
}
/**
* Computes the hash code of a repeated long field. Null-value and 0-length
* fields have the same hash code.
*/
public static int hashCode(long[] field) {
return field == null || field.length == 0 ? 0 : Arrays.hashCode(field);
}
/**
* Computes the hash code of a repeated float field. Null-value and 0-length
* fields have the same hash code.
*/
public static int hashCode(float[] field) {
return field == null || field.length == 0 ? 0 : Arrays.hashCode(field);
}
/**
* Computes the hash code of a repeated double field. Null-value and 0-length
* fields have the same hash code.
*/
public static int hashCode(double[] field) {
return field == null || field.length == 0 ? 0 : Arrays.hashCode(field);
}
/**
* Computes the hash code of a repeated boolean field. Null-value and 0-length
* fields have the same hash code.
*/
public static int hashCode(boolean[] field) {
return field == null || field.length == 0 ? 0 : Arrays.hashCode(field);
}
/**
* Computes the hash code of a repeated bytes field. Only the sequence of all
* non-null elements are used in the computation. Null-value fields and fields
* of any length with only null elements have the same hash code.
*/
public static int hashCode(byte[][] field) {
int result = 0;
for (int i = 0, size = field == null ? 0 : field.length; i < size; i++) {
byte[] element = field[i];
if (element != null) {
result = 31 * result + Arrays.hashCode(element);
}
}
return result;
}
/**
* Computes the hash code of a repeated string/message field. Only the
* sequence of all non-null elements are used in the computation. Null-value
* fields and fields of any length with only null elements have the same hash
* code.
*/
public static int hashCode(Object[] field) {
int result = 0;
for (int i = 0, size = field == null ? 0 : field.length; i < size; i++) {
Object element = field[i];
if (element != null) {
result = 31 * result + element.hashCode();
}
}
return result;
}
}

View File

@ -0,0 +1,93 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
import java.io.IOException;
/**
* Thrown when a protocol message being parsed is invalid in some way,
* e.g. it contains a malformed varint or a negative byte length.
*
* @author kenton@google.com Kenton Varda
*/
public class InvalidProtocolBufferNanoException extends IOException {
private static final long serialVersionUID = -1616151763072450476L;
public InvalidProtocolBufferNanoException(final String description) {
super(description);
}
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 " +
"input has been truncated or that an embedded message " +
"misreported its own length.");
}
static InvalidProtocolBufferNanoException negativeSize() {
return new InvalidProtocolBufferNanoException(
"CodedInputStream encountered an embedded string or message " +
"which claimed to have negative size.");
}
static InvalidProtocolBufferNanoException malformedVarint() {
return new InvalidProtocolBufferNanoException(
"CodedInputStream encountered a malformed varint.");
}
static InvalidProtocolBufferNanoException invalidTag() {
return new InvalidProtocolBufferNanoException(
"Protocol message contained an invalid tag (zero).");
}
static InvalidProtocolBufferNanoException invalidEndTag() {
return new InvalidProtocolBufferNanoException(
"Protocol message end-group tag did not match expected tag.");
}
static InvalidProtocolBufferNanoException invalidWireType() {
return new InvalidProtocolBufferNanoException(
"Protocol message tag had invalid wire type.");
}
static InvalidProtocolBufferNanoException recursionLimitExceeded() {
return new InvalidProtocolBufferNanoException(
"Protocol message had too many levels of nesting. May be malicious. " +
"Use CodedInputStream.setRecursionLimit() to increase the depth limit.");
}
static InvalidProtocolBufferNanoException sizeLimitExceeded() {
return new InvalidProtocolBufferNanoException(
"Protocol message was too large. May be malicious. " +
"Use CodedInputStream.setSizeLimit() to increase the size limit.");
}
}

View File

@ -0,0 +1,190 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
import java.io.IOException;
import java.util.Arrays;
/**
* Abstract interface implemented by Protocol Message objects.
*
* @author wink@google.com Wink Saville
*/
public abstract class MessageNano {
protected volatile int cachedSize = -1;
/**
* Get the number of bytes required to encode this message.
* Returns the cached size or calls getSerializedSize which
* sets the cached size. This is used internally when serializing
* so the size is only computed once. If a member is modified
* then this could be stale call getSerializedSize if in doubt.
*/
public int getCachedSize() {
if (cachedSize < 0) {
// getSerializedSize sets cachedSize
getSerializedSize();
}
return cachedSize;
}
/**
* Computes the number of bytes required to encode this message.
* The size is cached and the cached result can be retrieved
* using getCachedSize().
*/
public int getSerializedSize() {
int size = computeSerializedSize();
cachedSize = size;
return size;
}
/**
* Computes the number of bytes required to encode this message. This does not update the
* cached size.
*/
protected int computeSerializedSize() {
// This is overridden if the generated message has serialized fields.
return 0;
}
/**
* Serializes the message and writes it to {@code output}.
*
* @param output the output to receive the serialized form.
* @throws IOException if an error occurred writing to {@code output}.
*/
public void writeTo(CodedOutputByteBufferNano output) throws IOException {
// Does nothing by default. Overridden by subclasses which have data to write.
}
/**
* Parse {@code input} as a message of this type and merge it with the
* message being built.
*/
public abstract MessageNano mergeFrom(CodedInputByteBufferNano input) throws IOException;
/**
* Serialize to a byte array.
* @return byte array with the serialized data.
*/
public static final byte[] toByteArray(MessageNano msg) {
final byte[] result = new byte[msg.getSerializedSize()];
toByteArray(msg, result, 0, result.length);
return result;
}
/**
* Serialize to a byte array starting at offset through length. The
* method getSerializedSize must have been called prior to calling
* this method so the proper length is know. If an attempt to
* write more than length bytes OutOfSpaceException will be thrown
* and if length bytes are not written then IllegalStateException
* is thrown.
*/
public static final void toByteArray(MessageNano msg, byte[] data, int offset, int length) {
try {
final CodedOutputByteBufferNano output =
CodedOutputByteBufferNano.newInstance(data, offset, length);
msg.writeTo(output);
output.checkNoSpaceLeft();
} catch (IOException e) {
throw new RuntimeException("Serializing to a byte array threw an IOException "
+ "(should never happen).", e);
}
}
/**
* Parse {@code data} as a message of this type and merge it with the
* message being built.
*/
public static final <T extends MessageNano> T mergeFrom(T msg, final byte[] data)
throws InvalidProtocolBufferNanoException {
return mergeFrom(msg, data, 0, data.length);
}
/**
* Parse {@code data} as a message of this type and merge it with the
* message being built.
*/
public static final <T extends MessageNano> T mergeFrom(T msg, final byte[] data,
final int off, final int len) throws InvalidProtocolBufferNanoException {
try {
final CodedInputByteBufferNano input =
CodedInputByteBufferNano.newInstance(data, off, len);
msg.mergeFrom(input);
input.checkLastTagWas(0);
return msg;
} catch (InvalidProtocolBufferNanoException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException("Reading from a byte array threw an IOException (should "
+ "never happen).");
}
}
/**
* Compares two {@code MessageNano}s and returns true if the message's are the same class and
* have serialized form equality (i.e. all of the field values are the same).
*/
public static final boolean messageNanoEquals(MessageNano a, MessageNano b) {
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}
if (a.getClass() != b.getClass()) {
return false;
}
final int serializedSize = a.getSerializedSize();
if (b.getSerializedSize() != serializedSize) {
return false;
}
final byte[] aByteArray = new byte[serializedSize];
final byte[] bByteArray = new byte[serializedSize];
toByteArray(a, aByteArray, 0, serializedSize);
toByteArray(b, bByteArray, 0, serializedSize);
return Arrays.equals(aByteArray, bByteArray);
}
/**
* Returns a string that is (mostly) compatible with ProtoBuffer's TextFormat. Note that groups
* (which are deprecated) are not serialized with the correct field name.
*
* <p>This is implemented using reflection, so it is not especially fast nor is it guaranteed
* to find all fields if you have method removal turned on for proguard.
*/
@Override
public String toString() {
return MessageNanoPrinter.print(this);
}
}

View File

@ -0,0 +1,257 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* Static helper methods for printing nano protos.
*
* @author flynn@google.com Andrew Flynn
*/
public final class MessageNanoPrinter {
// Do not allow instantiation
private MessageNanoPrinter() {}
private static final String INDENT = " ";
private static final int MAX_STRING_LEN = 200;
/**
* Returns an text representation of a MessageNano suitable for debugging. The returned string
* is mostly compatible with Protocol Buffer's TextFormat (as provided by non-nano protocol
* buffers) -- groups (which are deprecated) are output with an underscore name (e.g. foo_bar
* instead of FooBar) and will thus not parse.
*
* <p>Employs Java reflection on the given object and recursively prints primitive fields,
* groups, and messages.</p>
*/
public static <T extends MessageNano> String print(T message) {
if (message == null) {
return "";
}
StringBuffer buf = new StringBuffer();
try {
print(null, message, new StringBuffer(), buf);
} catch (IllegalAccessException e) {
return "Error printing proto: " + e.getMessage();
} catch (InvocationTargetException e) {
return "Error printing proto: " + e.getMessage();
}
return buf.toString();
}
/**
* Function that will print the given message/field into the StringBuffer.
* Meant to be called recursively.
*
* @param identifier the identifier to use, or {@code null} if this is the root message to
* print.
* @param object the value to print. May in fact be a primitive value or byte array and not a
* message.
* @param indentBuf the indentation each line should begin with.
* @param buf the output buffer.
*/
private static void print(String identifier, Object object,
StringBuffer indentBuf, StringBuffer buf) throws IllegalAccessException,
InvocationTargetException {
if (object == null) {
// This can happen if...
// - we're about to print a message, String, or byte[], but it not present;
// - we're about to print a primitive, but "reftype" optional style is enabled, and
// the field is unset.
// In both cases the appropriate behavior is to output nothing.
} else if (object instanceof MessageNano) { // Nano proto message
int origIndentBufLength = indentBuf.length();
if (identifier != null) {
buf.append(indentBuf).append(deCamelCaseify(identifier)).append(" <\n");
indentBuf.append(INDENT);
}
Class<?> clazz = object.getClass();
// Proto fields follow one of two formats:
//
// 1) Public, non-static variables that do not begin or end with '_'
// Find and print these using declared public fields
for (Field field : clazz.getFields()) {
int modifiers = field.getModifiers();
String fieldName = field.getName();
if ((modifiers & Modifier.PUBLIC) == Modifier.PUBLIC
&& (modifiers & Modifier.STATIC) != Modifier.STATIC
&& !fieldName.startsWith("_")
&& !fieldName.endsWith("_")) {
Class<?> fieldType = field.getType();
Object value = field.get(object);
if (fieldType.isArray()) {
Class<?> arrayType = fieldType.getComponentType();
// bytes is special since it's not repeated, but is represented by an array
if (arrayType == byte.class) {
print(fieldName, value, indentBuf, buf);
} else {
int len = value == null ? 0 : Array.getLength(value);
for (int i = 0; i < len; i++) {
Object elem = Array.get(value, i);
print(fieldName, elem, indentBuf, buf);
}
}
} else {
print(fieldName, value, indentBuf, buf);
}
}
}
// 2) Fields that are accessed via getter methods (when accessors
// mode is turned on)
// Find and print these using getter methods.
for (Method method : clazz.getMethods()) {
String name = method.getName();
// Check for the setter accessor method since getters and hazzers both have
// non-proto-field name collisions (hashCode() and getSerializedSize())
if (name.startsWith("set")) {
String subfieldName = name.substring(3);
Method hazzer = null;
try {
hazzer = clazz.getMethod("has" + subfieldName);
} catch (NoSuchMethodException e) {
continue;
}
// If hazzer does't exist or returns false, no need to continue
if (!(Boolean) hazzer.invoke(object)) {
continue;
}
Method getter = null;
try {
getter = clazz.getMethod("get" + subfieldName);
} catch (NoSuchMethodException e) {
continue;
}
print(subfieldName, getter.invoke(object), indentBuf, buf);
}
}
if (identifier != null) {
indentBuf.setLength(origIndentBufLength);
buf.append(indentBuf).append(">\n");
}
} else {
// Non-null primitive value
identifier = deCamelCaseify(identifier);
buf.append(indentBuf).append(identifier).append(": ");
if (object instanceof String) {
String stringMessage = sanitizeString((String) object);
buf.append("\"").append(stringMessage).append("\"");
} else if (object instanceof byte[]) {
appendQuotedBytes((byte[]) object, buf);
} else {
buf.append(object);
}
buf.append("\n");
}
}
/**
* Converts an identifier of the format "FieldName" into "field_name".
*/
private static String deCamelCaseify(String identifier) {
StringBuffer out = new StringBuffer();
for (int i = 0; i < identifier.length(); i++) {
char currentChar = identifier.charAt(i);
if (i == 0) {
out.append(Character.toLowerCase(currentChar));
} else if (Character.isUpperCase(currentChar)) {
out.append('_').append(Character.toLowerCase(currentChar));
} else {
out.append(currentChar);
}
}
return out.toString();
}
/**
* Shortens and escapes the given string.
*/
private static String sanitizeString(String str) {
if (!str.startsWith("http") && str.length() > MAX_STRING_LEN) {
// Trim non-URL strings.
str = str.substring(0, MAX_STRING_LEN) + "[...]";
}
return escapeString(str);
}
/**
* Escape everything except for low ASCII code points.
*/
private static String escapeString(String str) {
int strLen = str.length();
StringBuilder b = new StringBuilder(strLen);
for (int i = 0; i < strLen; i++) {
char original = str.charAt(i);
if (original >= ' ' && original <= '~' && original != '"' && original != '\'') {
b.append(original);
} else {
b.append(String.format("\\u%04x", (int) original));
}
}
return b.toString();
}
/**
* Appends a quoted byte array to the provided {@code StringBuffer}.
*/
private static void appendQuotedBytes(byte[] bytes, StringBuffer builder) {
if (bytes == null) {
builder.append("\"\"");
return;
}
builder.append('"');
for (int i = 0; i < bytes.length; ++i) {
int ch = bytes[i] & 0xff;
if (ch == '\\' || ch == '"') {
builder.append('\\').append((char) ch);
} else if (ch >= 32 && ch < 127) {
builder.append((char) ch);
} else {
builder.append(String.format("\\%03o", ch));
}
}
builder.append('"');
}
}

View File

@ -0,0 +1,84 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
import java.io.IOException;
import java.util.Arrays;
/**
* Stores unknown fields. These might be extensions or fields that the generated
* API doesn't know about yet.
*
* @author bduff@google.com (Brian Duff)
*/
final class UnknownFieldData {
final int tag;
final byte[] bytes;
UnknownFieldData(int tag, byte[] bytes) {
this.tag = tag;
this.bytes = bytes;
}
int computeSerializedSize() {
int size = 0;
size += CodedOutputByteBufferNano.computeRawVarint32Size(tag);
size += bytes.length;
return size;
}
void writeTo(CodedOutputByteBufferNano output) throws IOException {
output.writeRawVarint32(tag);
output.writeRawBytes(bytes);
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof UnknownFieldData)) {
return false;
}
UnknownFieldData other = (UnknownFieldData) o;
return tag == other.tag && Arrays.equals(bytes, other.bytes);
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + tag;
result = 31 * result + Arrays.hashCode(bytes);
return result;
}
}

View File

@ -0,0 +1,124 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
import java.io.IOException;
/**
* This class is used internally by the Protocol Buffer library and generated
* message implementations. It is public only because those generated messages
* do not reside in the {@code protobuf} package. Others should not use this
* class directly.
*
* This class contains constants and helper functions useful for dealing with
* the Protocol Buffer wire format.
*
* @author kenton@google.com Kenton Varda
*/
public final class WireFormatNano {
// Do not allow instantiation.
private WireFormatNano() {}
static final int WIRETYPE_VARINT = 0;
static final int WIRETYPE_FIXED64 = 1;
static final int WIRETYPE_LENGTH_DELIMITED = 2;
static final int WIRETYPE_START_GROUP = 3;
static final int WIRETYPE_END_GROUP = 4;
static final int WIRETYPE_FIXED32 = 5;
static final int TAG_TYPE_BITS = 3;
static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
/** Given a tag value, determines the wire type (the lower 3 bits). */
static int getTagWireType(final int tag) {
return tag & TAG_TYPE_MASK;
}
/** Given a tag value, determines the field number (the upper 29 bits). */
public static int getTagFieldNumber(final int tag) {
return tag >>> TAG_TYPE_BITS;
}
/** Makes a tag value given a field number and wire type. */
static int makeTag(final int fieldNumber, final int wireType) {
return (fieldNumber << TAG_TYPE_BITS) | wireType;
}
public static final int EMPTY_INT_ARRAY[] = {};
public static final long EMPTY_LONG_ARRAY[] = {};
public static final float EMPTY_FLOAT_ARRAY[] = {};
public static final double EMPTY_DOUBLE_ARRAY[] = {};
public static final boolean EMPTY_BOOLEAN_ARRAY[] = {};
public static final String EMPTY_STRING_ARRAY[] = {};
public static final byte[] EMPTY_BYTES_ARRAY[] = {};
public static final byte[] EMPTY_BYTES = {};
/**
* Parses an unknown field. This implementation skips the field.
*
* <p>Generated messages will call this for unknown fields if the store_unknown_fields
* option is off.
*
* @return {@literal true} unless the tag is an end-group tag.
*/
public static boolean parseUnknownField(
final CodedInputByteBufferNano input,
final int tag) throws IOException {
return input.skipField(tag);
}
/**
* Computes the array length of a repeated field. We assume that in the common case repeated
* fields are contiguously serialized but we still correctly handle interspersed values of a
* repeated field (but with extra allocations).
*
* Rewinds to current input position before returning.
*
* @param input stream input, pointing to the byte after the first tag
* @param tag repeated field tag just read
* @return length of array
* @throws IOException
*/
public static final int getRepeatedFieldArrayLength(
final CodedInputByteBufferNano input,
final int tag) throws IOException {
int arrayLength = 1;
int startPos = input.getPosition();
input.skipField(tag);
while (input.readTag() == tag) {
input.skipField(tag);
arrayLength++;
}
input.rewindToPosition(startPos);
return arrayLength;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: maxtroy@google.com (Max Cai)
package protobuf_unittest;
option java_package = "com.google.protobuf.nano";
option java_outer_classname = "NanoAccessorsOuterClass";
message TestNanoAccessors {
message NestedMessage {
optional int32 bb = 1;
}
enum NestedEnum {
FOO = 1;
BAR = 2;
BAZ = 3;
}
// Singular
optional int32 optional_int32 = 1;
optional float optional_float = 11;
optional double optional_double = 12;
optional string optional_string = 14;
optional bytes optional_bytes = 15;
optional NestedMessage optional_nested_message = 18;
optional NestedEnum optional_nested_enum = 21;
// Repeated
repeated int32 repeated_int32 = 31;
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
repeated NestedMessage repeated_nested_message = 48;
repeated NestedEnum repeated_nested_enum = 51;
// Singular with defaults
optional int32 default_int32 = 61 [default = 41 ];
optional string default_string = 74 [default = "hello"];
optional bytes default_bytes = 75 [default = "world"];
optional float default_float_nan = 99 [default = nan];
optional NestedEnum default_nested_enum = 81 [default = BAR];
// Required
required int32 id = 86;
// Add enough optional fields to make 2 bit fields in total
optional int32 filler100 = 100;
optional int32 filler101 = 101;
optional int32 filler102 = 102;
optional int32 filler103 = 103;
optional int32 filler104 = 104;
optional int32 filler105 = 105;
optional int32 filler106 = 106;
optional int32 filler107 = 107;
optional int32 filler108 = 108;
optional int32 filler109 = 109;
optional int32 filler110 = 110;
optional int32 filler111 = 111;
optional int32 filler112 = 112;
optional int32 filler113 = 113;
optional int32 filler114 = 114;
optional int32 filler115 = 115;
optional int32 filler116 = 116;
optional int32 filler117 = 117;
optional int32 filler118 = 118;
optional int32 filler119 = 119;
optional int32 filler120 = 120;
optional int32 filler121 = 121;
optional int32 filler122 = 122;
optional int32 filler123 = 123;
optional int32 filler124 = 124;
optional int32 filler125 = 125;
optional int32 filler126 = 126;
optional int32 filler127 = 127;
optional int32 filler128 = 128;
optional int32 filler129 = 129;
optional int32 filler130 = 130;
optional int32 before_bit_field_check = 139;
optional int32 bit_field_check = 140;
optional int32 after_bit_field_check = 141;
}

View File

@ -0,0 +1,48 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: maxtroy@google.com (Max Cai)
package protobuf_unittest;
option java_package = "com.google.protobuf.nano";
option java_multiple_files = true;
enum FileScopeEnumMultiple {
THREE = 3;
}
message EnumClassNanoMultiple {
enum MessageScopeEnumMultiple {
FOUR = 4;
}
optional FileScopeEnumMultiple three = 3 [ default = THREE ];
optional MessageScopeEnumMultiple four = 4 [ default = FOUR ];
}

View File

@ -0,0 +1,48 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: maxtroy@google.com (Max Cai)
package protobuf_unittest;
option java_package = "com.google.protobuf.nano";
option java_outer_classname = "EnumClassNanos";
enum FileScopeEnum {
ONE = 1;
}
message EnumClassNano {
enum MessageScopeEnum {
TWO = 2;
}
optional FileScopeEnum one = 1 [ default = ONE ];
optional MessageScopeEnum two = 2 [ default = TWO ];
}

View File

@ -0,0 +1,28 @@
package protobuf_unittest;
option java_package = "com.google.protobuf.nano";
option java_outer_classname = "EnumValidity";
enum E {
default = 1; // test java keyword renaming
FOO = 2;
BAR = 3;
BAZ = 4;
}
message M {
optional E optional_e = 1;
optional E default_e = 2 [ default = BAZ ];
repeated E repeated_e = 3;
repeated E packed_e = 4 [ packed = true ];
repeated E repeated_e2 = 5;
repeated E packed_e2 = 6 [ packed = true ];
repeated E repeated_e3 = 7;
repeated E packed_e3 = 8 [ packed = true ];
}
message Alt {
optional E repeated_e2_as_optional = 5;
repeated E packed_e2_as_non_packed = 6;
repeated E non_packed_e3_as_packed = 7 [ packed = true ];
}

View File

@ -0,0 +1,33 @@
syntax = "proto2";
option java_outer_classname = "Extensions";
option java_package = "com.google.protobuf.nano.testext";
message ExtendableMessage {
optional int32 field = 1;
extensions 10 to max;
}
enum AnEnum {
FIRST_VALUE = 1;
SECOND_VALUE = 2;
}
message AnotherMessage {
optional string string = 1;
optional bool value = 2;
}
message ContainerMessage {
extend ExtendableMessage {
optional bool another_thing = 100;
}
}
// For testNanoOptionalGroupWithUnknownFieldsEnabled;
// not part of the extensions tests.
message MessageWithGroup {
optional group Group = 1 {
optional int32 a = 2;
}
}

View File

@ -0,0 +1,29 @@
syntax = "proto2";
option java_multiple_files = true;
option java_package = "com.google.protobuf.nano";
import "google/protobuf/nano/unittest_extension_nano.proto";
// Must be compiled separately due to extension number reuse.
// The reuse is deliberate, for testing wire compatibility.
message PackedExtensions {
extend ExtendableMessage {
repeated int32 packed_int32 = 10 [ packed = true ];
repeated uint32 packed_uint32 = 11 [ packed = true ];
repeated sint32 packed_sint32 = 12 [ packed = true ];
repeated int64 packed_int64 = 13 [ packed = true ];
repeated uint64 packed_uint64 = 14 [ packed = true ];
repeated sint64 packed_sint64 = 15 [ packed = true ];
repeated fixed32 packed_fixed32 = 16 [ packed = true ];
repeated sfixed32 packed_sfixed32 = 17 [ packed = true ];
repeated fixed64 packed_fixed64 = 18 [ packed = true ];
repeated sfixed64 packed_sfixed64 = 19 [ packed = true ];
repeated bool packed_bool = 20 [ packed = true ];
repeated float packed_float = 21 [ packed = true ];
repeated double packed_double = 22 [ packed = true ];
repeated AnEnum packed_enum = 23 [ packed = true ];
// Non-packable types omitted.
}
}

View File

@ -0,0 +1,34 @@
syntax = "proto2";
option java_multiple_files = true;
option java_package = "com.google.protobuf.nano";
import "google/protobuf/nano/unittest_extension_nano.proto";
// Must be compiled separately due to extension number reuse.
// The reuse is deliberate, for testing wire compatibility.
message RepeatedExtensions {
extend ExtendableMessage {
repeated int32 repeated_int32 = 10;
repeated uint32 repeated_uint32 = 11;
repeated sint32 repeated_sint32 = 12;
repeated int64 repeated_int64 = 13;
repeated uint64 repeated_uint64 = 14;
repeated sint64 repeated_sint64 = 15;
repeated fixed32 repeated_fixed32 = 16;
repeated sfixed32 repeated_sfixed32 = 17;
repeated fixed64 repeated_fixed64 = 18;
repeated sfixed64 repeated_sfixed64 = 19;
repeated bool repeated_bool = 20;
repeated float repeated_float = 21;
repeated double repeated_double = 22;
repeated AnEnum repeated_enum = 23;
repeated string repeated_string = 24;
repeated bytes repeated_bytes = 25;
repeated AnotherMessage repeated_message = 26;
repeated group RepeatedGroup = 27 {
optional int32 a = 1;
}
}
}

View File

@ -0,0 +1,34 @@
syntax = "proto2";
option java_multiple_files = true;
option java_package = "com.google.protobuf.nano";
import "google/protobuf/nano/unittest_extension_nano.proto";
// Must be compiled separately due to extension number reuse.
// The reuse is deliberate, for testing wire compatibility.
message SingularExtensions {
extend ExtendableMessage {
optional int32 some_int32 = 10;
optional uint32 some_uint32 = 11;
optional sint32 some_sint32 = 12;
optional int64 some_int64 = 13;
optional uint64 some_uint64 = 14;
optional sint64 some_sint64 = 15;
optional fixed32 some_fixed32 = 16;
optional sfixed32 some_sfixed32 = 17;
optional fixed64 some_fixed64 = 18;
optional sfixed64 some_sfixed64 = 19;
optional bool some_bool = 20;
optional float some_float = 21;
optional double some_double = 22;
optional AnEnum some_enum = 23;
optional string some_string = 24;
optional bytes some_bytes = 25;
optional AnotherMessage some_message = 26;
optional group SomeGroup = 27 {
optional int32 a = 1;
}
}
}

View File

@ -0,0 +1,82 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: ulas@google.com (Ulas Kirazci)
package protobuf_unittest;
option java_package = "com.google.protobuf.nano";
option java_outer_classname = "NanoHasOuterClass";
message TestAllTypesNanoHas {
message NestedMessage {
optional int32 bb = 1;
}
enum NestedEnum {
FOO = 1;
BAR = 2;
BAZ = 3;
}
// Singular
optional int32 optional_int32 = 1;
optional float optional_float = 11;
optional double optional_double = 12;
optional string optional_string = 14;
optional bytes optional_bytes = 15;
optional NestedMessage optional_nested_message = 18;
optional NestedEnum optional_nested_enum = 21;
// Repeated
repeated int32 repeated_int32 = 31;
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
repeated NestedMessage repeated_nested_message = 48;
repeated NestedEnum repeated_nested_enum = 51;
// Singular with defaults
optional int32 default_int32 = 61 [default = 41 ];
optional string default_string = 74 [default = "hello"];
optional bytes default_bytes = 75 [default = "world"];
optional float default_float_nan = 99 [default = nan];
optional NestedEnum default_nested_enum = 81 [default = BAR];
required int32 id = 86;
required NestedEnum required_enum = 87;
}

View File

@ -0,0 +1,48 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
//
// This is like unittest_import.proto but with optimize_for = NANO_RUNTIME.
package protobuf_unittest_import;
option java_package = "com.google.protobuf.nano.testimport";
option java_outer_classname = "UnittestImportNano";
message ImportMessageNano {
optional int32 d = 1;
}
enum ImportEnumNano {
IMPORT_NANO_FOO = 7;
IMPORT_NANO_BAR = 8;
IMPORT_NANO_BAZ = 9;
}

View File

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

View File

@ -0,0 +1,63 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: maxtroy@google.com (Max Cai)
package protobuf_unittest_import;
import "google/protobuf/nano/unittest_import_nano.proto";
option java_package = "com.google.protobuf.nano";
option java_multiple_files = true;
enum FileScopeEnum {
ONE = 1;
TWO = 2;
}
message FileScopeEnumRefNano {
optional FileScopeEnum enum_field = 1;
}
message MessageScopeEnumRefNano {
enum MessageScopeEnum {
ONE = 1;
TWO = 2;
}
optional MessageScopeEnum enum_field = 1;
}
message MultipleImportingNonMultipleNano1 {
optional ImportMessageNano field = 1;
}
message MultipleImportingNonMultipleNano2 {
optional MultipleImportingNonMultipleNano1 nano1 = 1;
}

View File

@ -0,0 +1,186 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: wink@google.com (Wink Saville)
package protobuf_unittest;
import "google/protobuf/nano/unittest_import_nano.proto";
option java_package = "com.google.protobuf.nano";
option java_outer_classname = "NanoOuterClass";
// Same as TestAllTypes but with the nano runtime.
message TestAllTypesNano {
message NestedMessage {
optional int32 bb = 1;
}
enum NestedEnum {
FOO = 1;
BAR = 2;
BAZ = 3;
}
// Singular
optional int32 optional_int32 = 1;
optional int64 optional_int64 = 2;
optional uint32 optional_uint32 = 3;
optional uint64 optional_uint64 = 4;
optional sint32 optional_sint32 = 5;
optional sint64 optional_sint64 = 6;
optional fixed32 optional_fixed32 = 7;
optional fixed64 optional_fixed64 = 8;
optional sfixed32 optional_sfixed32 = 9;
optional sfixed64 optional_sfixed64 = 10;
optional float optional_float = 11;
optional double optional_double = 12;
optional bool optional_bool = 13;
optional string optional_string = 14;
optional bytes optional_bytes = 15;
optional group OptionalGroup = 16 {
optional int32 a = 17;
}
optional NestedMessage optional_nested_message = 18;
optional ForeignMessageNano optional_foreign_message = 19;
optional protobuf_unittest_import.ImportMessageNano
optional_import_message = 20;
optional NestedEnum optional_nested_enum = 21;
optional ForeignEnumNano optional_foreign_enum = 22;
optional protobuf_unittest_import.ImportEnumNano optional_import_enum = 23;
optional string optional_string_piece = 24 [ctype=STRING_PIECE];
optional string optional_cord = 25 [ctype=CORD];
// Repeated
repeated int32 repeated_int32 = 31;
repeated int64 repeated_int64 = 32;
repeated uint32 repeated_uint32 = 33;
repeated uint64 repeated_uint64 = 34;
repeated sint32 repeated_sint32 = 35;
repeated sint64 repeated_sint64 = 36;
repeated fixed32 repeated_fixed32 = 37;
repeated fixed64 repeated_fixed64 = 38;
repeated sfixed32 repeated_sfixed32 = 39;
repeated sfixed64 repeated_sfixed64 = 40;
repeated float repeated_float = 41;
repeated double repeated_double = 42;
repeated bool repeated_bool = 43;
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
repeated group RepeatedGroup = 46 {
optional int32 a = 47;
}
repeated NestedMessage repeated_nested_message = 48;
repeated ForeignMessageNano repeated_foreign_message = 49;
repeated protobuf_unittest_import.ImportMessageNano
repeated_import_message = 50;
repeated NestedEnum repeated_nested_enum = 51;
repeated ForeignEnumNano repeated_foreign_enum = 52;
repeated protobuf_unittest_import.ImportEnumNano repeated_import_enum = 53;
repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
repeated string repeated_cord = 55 [ctype=CORD];
// Repeated packed
repeated int32 repeated_packed_int32 = 87 [packed=true];
repeated sfixed64 repeated_packed_sfixed64 = 88 [packed=true];
repeated NestedEnum repeated_packed_nested_enum = 89 [packed=true];
// Singular with defaults
optional int32 default_int32 = 61 [default = 41 ];
optional int64 default_int64 = 62 [default = 42 ];
optional uint32 default_uint32 = 63 [default = 43 ];
optional uint64 default_uint64 = 64 [default = 44 ];
optional sint32 default_sint32 = 65 [default = -45 ];
optional sint64 default_sint64 = 66 [default = 46 ];
optional fixed32 default_fixed32 = 67 [default = 47 ];
optional fixed64 default_fixed64 = 68 [default = 48 ];
optional sfixed32 default_sfixed32 = 69 [default = 49 ];
optional sfixed64 default_sfixed64 = 70 [default = -50 ];
optional float default_float = 71 [default = 51.5 ];
optional double default_double = 72 [default = 52e3 ];
optional bool default_bool = 73 [default = true ];
optional string default_string = 74 [default = "hello"];
optional bytes default_bytes = 75 [default = "world"];
optional string default_string_nonascii = 76 [default = "dünya"];
optional bytes default_bytes_nonascii = 77 [default = "dünyab"];
optional float default_float_inf = 97 [default = inf];
optional float default_float_neg_inf = 98 [default = -inf];
optional float default_float_nan = 99 [default = nan];
optional double default_double_inf = 100 [default = inf];
optional double default_double_neg_inf = 101 [default = -inf];
optional double default_double_nan = 102 [default = nan];
optional NestedEnum default_nested_enum = 81 [default = BAR];
optional ForeignEnumNano default_foreign_enum = 82
[default = FOREIGN_NANO_BAR];
optional protobuf_unittest_import.ImportEnumNano
default_import_enum = 83 [default = IMPORT_NANO_BAR];
optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
optional string default_cord = 85 [ctype=CORD,default="123"];
required int32 id = 86;
// Try to cause conflicts.
optional int32 tag = 93;
optional int32 get_serialized_size = 94;
optional int32 write_to = 95;
// Try to fail with java reserved keywords
optional int32 synchronized = 96;
}
message ForeignMessageNano {
optional int32 c = 1;
}
enum ForeignEnumNano {
FOREIGN_NANO_FOO = 4;
FOREIGN_NANO_BAR = 5;
FOREIGN_NANO_BAZ = 6;
}
// Test that deprecated fields work. We only verify that they compile (at one
// point this failed).
message TestDeprecatedNano {
optional int32 deprecated_field = 1 [deprecated = true];
}

View File

@ -0,0 +1,49 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: wink@google.com (Wink Saville)
//
package protobuf_unittest_import;
option java_package = "com.google.protobuf.nano";
// Explicit outer classname to suppress legacy info.
option java_outer_classname = "UnittestRecursiveNano";
message RecursiveMessageNano {
message NestedMessage {
optional RecursiveMessageNano a = 1;
}
required int32 id = 1;
optional NestedMessage nested_message = 2;
optional RecursiveMessageNano optional_recursive_message_nano = 3;
repeated RecursiveMessageNano repeated_recursive_message_nano = 4;
}

View File

@ -0,0 +1,116 @@
package protobuf_unittest;
option java_package = "com.google.protobuf.nano";
option java_outer_classname = "NanoReferenceTypes";
message TestAllTypesNano {
enum NestedEnum {
FOO = 1;
BAR = 2;
BAZ = 3;
}
message NestedMessage {
optional int32 foo = 1;
}
// Singular
optional int32 optional_int32 = 1;
optional int64 optional_int64 = 2;
optional uint32 optional_uint32 = 3;
optional uint64 optional_uint64 = 4;
optional sint32 optional_sint32 = 5;
optional sint64 optional_sint64 = 6;
optional fixed32 optional_fixed32 = 7;
optional fixed64 optional_fixed64 = 8;
optional sfixed32 optional_sfixed32 = 9;
optional sfixed64 optional_sfixed64 = 10;
optional float optional_float = 11;
optional double optional_double = 12;
optional bool optional_bool = 13;
optional string optional_string = 14;
optional bytes optional_bytes = 15;
optional group OptionalGroup = 16 {
optional int32 a = 17;
}
optional NestedMessage optional_nested_message = 18;
optional NestedEnum optional_nested_enum = 21;
optional string optional_string_piece = 24 [ctype=STRING_PIECE];
optional string optional_cord = 25 [ctype=CORD];
// Repeated
repeated int32 repeated_int32 = 31;
repeated int64 repeated_int64 = 32;
repeated uint32 repeated_uint32 = 33;
repeated uint64 repeated_uint64 = 34;
repeated sint32 repeated_sint32 = 35;
repeated sint64 repeated_sint64 = 36;
repeated fixed32 repeated_fixed32 = 37;
repeated fixed64 repeated_fixed64 = 38;
repeated sfixed32 repeated_sfixed32 = 39;
repeated sfixed64 repeated_sfixed64 = 40;
repeated float repeated_float = 41;
repeated double repeated_double = 42;
repeated bool repeated_bool = 43;
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
repeated group RepeatedGroup = 46 {
optional int32 a = 47;
}
repeated NestedMessage repeated_nested_message = 48;
repeated NestedEnum repeated_nested_enum = 51;
repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
repeated string repeated_cord = 55 [ctype=CORD];
// Repeated packed
repeated int32 repeated_packed_int32 = 87 [packed=true];
repeated sfixed64 repeated_packed_sfixed64 = 88 [packed=true];
repeated NestedEnum repeated_packed_nested_enum = 89 [packed=true];
// Singular with defaults
optional int32 default_int32 = 61 [default = 41 ];
optional int64 default_int64 = 62 [default = 42 ];
optional uint32 default_uint32 = 63 [default = 43 ];
optional uint64 default_uint64 = 64 [default = 44 ];
optional sint32 default_sint32 = 65 [default = -45 ];
optional sint64 default_sint64 = 66 [default = 46 ];
optional fixed32 default_fixed32 = 67 [default = 47 ];
optional fixed64 default_fixed64 = 68 [default = 48 ];
optional sfixed32 default_sfixed32 = 69 [default = 49 ];
optional sfixed64 default_sfixed64 = 70 [default = -50 ];
optional float default_float = 71 [default = 51.5 ];
optional double default_double = 72 [default = 52e3 ];
optional bool default_bool = 73 [default = true ];
optional string default_string = 74 [default = "hello"];
optional bytes default_bytes = 75 [default = "world"];
optional float default_float_inf = 97 [default = inf];
optional float default_float_neg_inf = 98 [default = -inf];
optional float default_float_nan = 99 [default = nan];
optional double default_double_inf = 100 [default = inf];
optional double default_double_neg_inf = 101 [default = -inf];
optional double default_double_nan = 102 [default = nan];
}
message ForeignMessageNano {
optional int32 c = 1;
}
enum ForeignEnumNano {
FOREIGN_NANO_FOO = 4;
FOREIGN_NANO_BAR = 5;
FOREIGN_NANO_BAZ = 6;
}

View File

@ -0,0 +1,47 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: maxtroy@google.com (Max Cai)
package protobuf_unittest;
import "google/protobuf/nano/unittest_nano.proto";
option java_package = "com.google.protobuf.nano";
option java_multiple_files = true;
// A container message for testing the merging of repeated fields at a
// nested level. Other tests will be done using the repeated fields in
// TestAllTypesNano.
message TestRepeatedMergeNano {
optional TestAllTypesNano contained = 1;
}

View File

@ -0,0 +1,95 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: maxtroy@google.com (Max Cai)
package protobuf_unittest;
option java_package = "com.google.protobuf.nano";
option java_outer_classname = "NanoRepeatedPackables";
enum Enum {
OPTION_ONE = 1;
OPTION_TWO = 2;
}
// Two almost identical messages with all packable repeated field types.
// One with none marked as packed and the other all packed. For
// compatibility, they should be able to parse each other's serialized
// forms.
message NonPacked {
// All packable types, none marked as packed.
repeated int32 int32s = 1;
repeated int64 int64s = 2;
repeated uint32 uint32s = 3;
repeated uint64 uint64s = 4;
repeated sint32 sint32s = 5;
repeated sint64 sint64s = 6;
repeated fixed32 fixed32s = 7;
repeated fixed64 fixed64s = 8;
repeated sfixed32 sfixed32s = 9;
repeated sfixed64 sfixed64s = 10;
repeated float floats = 11;
repeated double doubles = 12;
repeated bool bools = 13;
repeated Enum enums = 14;
// Noise for testing merged deserialization.
optional int32 noise = 15;
}
message Packed {
// All packable types, all matching the field numbers in NonPacked,
// all marked as packed.
repeated int32 int32s = 1 [ packed = true ];
repeated int64 int64s = 2 [ packed = true ];
repeated uint32 uint32s = 3 [ packed = true ];
repeated uint64 uint64s = 4 [ packed = true ];
repeated sint32 sint32s = 5 [ packed = true ];
repeated sint64 sint64s = 6 [ packed = true ];
repeated fixed32 fixed32s = 7 [ packed = true ];
repeated fixed64 fixed64s = 8 [ packed = true ];
repeated sfixed32 sfixed32s = 9 [ packed = true ];
repeated sfixed64 sfixed64s = 10 [ packed = true ];
repeated float floats = 11 [ packed = true ];
repeated double doubles = 12 [ packed = true ];
repeated bool bools = 13 [ packed = true ];
repeated Enum enums = 14 [ packed = true ];
// Noise for testing merged deserialization.
optional int32 noise = 15;
}

View File

@ -0,0 +1,54 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: wink@google.com (Wink Saville)
//
package protobuf_unittest_import;
option java_package = "com.google.protobuf.nano";
// Explicit outer classname to suppress legacy info.
option java_outer_classname = "UnittestSimpleNano";
message SimpleMessageNano {
message NestedMessage {
optional int32 bb = 1;
}
enum NestedEnum {
FOO = 1;
BAR = 2;
BAZ = 3;
}
optional int32 d = 1 [default = 123];
optional NestedMessage nested_msg = 2;
optional NestedEnum default_nested_enum = 3 [default = BAZ];
}

View File

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

View File

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

View File

@ -0,0 +1,111 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <map>
#include <string>
#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/compiler/javanano/javanano_enum.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Params& params)
: params_(params), descriptor_(descriptor) {
for (int i = 0; i < descriptor_->value_count(); i++) {
const EnumValueDescriptor* value = descriptor_->value(i);
const EnumValueDescriptor* canonical_value =
descriptor_->FindValueByNumber(value->number());
if (value == canonical_value) {
canonical_values_.push_back(value);
} else {
Alias alias;
alias.value = value;
alias.canonical_value = canonical_value;
aliases_.push_back(alias);
}
}
}
EnumGenerator::~EnumGenerator() {}
void EnumGenerator::Generate(io::Printer* printer) {
printer->Print(
"\n"
"// enum $classname$\n",
"classname", descriptor_->name());
// Start of container interface
bool use_shell_class = params_.java_enum_style();
if (use_shell_class) {
printer->Print(
"public interface $classname$ {\n",
"classname", RenameJavaKeywords(descriptor_->name()));
printer->Indent();
}
// Canonical values
for (int i = 0; i < canonical_values_.size(); i++) {
printer->Print(
"public static final int $name$ = $canonical_value$;\n",
"name", RenameJavaKeywords(canonical_values_[i]->name()),
"canonical_value", SimpleItoa(canonical_values_[i]->number()));
}
// Aliases
for (int i = 0; i < aliases_.size(); i++) {
printer->Print(
"public static final int $name$ = $canonical_name$;\n",
"name", RenameJavaKeywords(aliases_[i].value->name()),
"canonical_name", RenameJavaKeywords(aliases_[i].canonical_value->name()));
}
// End of container interface
if (use_shell_class) {
printer->Outdent();
printer->Print("}\n");
}
}
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,87 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__
#include <string>
#include <vector>
#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/descriptor.h>
namespace google {
namespace protobuf {
namespace io {
class Printer; // printer.h
}
}
namespace protobuf {
namespace compiler {
namespace javanano {
class EnumGenerator {
public:
explicit EnumGenerator(const EnumDescriptor* descriptor, const Params& params);
~EnumGenerator();
void Generate(io::Printer* printer);
private:
const Params& params_;
const EnumDescriptor* descriptor_;
// The proto language allows multiple enum constants to have the same numeric
// value. Java, however, does not allow multiple enum constants to be
// considered equivalent. We treat the first defined constant for any
// given numeric value as "canonical" and the rest as aliases of that
// canonical value.
vector<const EnumValueDescriptor*> canonical_values_;
struct Alias {
const EnumValueDescriptor* value;
const EnumValueDescriptor* canonical_value;
};
vector<Alias> aliases_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
};
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__

View File

@ -0,0 +1,520 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <map>
#include <string>
#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {
namespace {
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
// repeat code between this and the other field types.
void SetEnumVariables(const Params& params,
const FieldDescriptor* descriptor, map<string, string>* variables) {
(*variables)["name"] =
RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
(*variables)["capitalized_name"] =
RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
(*variables)["number"] = SimpleItoa(descriptor->number());
if (params.use_reference_types_for_primitives()
&& !params.reftypes_primitive_enums()
&& !descriptor->is_repeated()) {
(*variables)["type"] = "java.lang.Integer";
(*variables)["default"] = "null";
} else {
(*variables)["type"] = "int";
(*variables)["default"] = DefaultValue(params, descriptor);
}
(*variables)["repeated_default"] =
"com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
(*variables)["non_packed_tag"] = SimpleItoa(
internal::WireFormatLite::MakeTag(descriptor->number(),
internal::WireFormat::WireTypeForFieldType(descriptor->type())));
(*variables)["message_name"] = descriptor->containing_type()->name();
}
void LoadEnumValues(const Params& params,
const EnumDescriptor* enum_descriptor, vector<string>* canonical_values) {
string enum_class_name = ClassName(params, enum_descriptor);
for (int i = 0; i < enum_descriptor->value_count(); i++) {
const EnumValueDescriptor* value = enum_descriptor->value(i);
const EnumValueDescriptor* canonical_value =
enum_descriptor->FindValueByNumber(value->number());
if (value == canonical_value) {
canonical_values->push_back(
enum_class_name + "." + RenameJavaKeywords(value->name()));
}
}
}
void PrintCaseLabels(
io::Printer* printer, const vector<string>& canonical_values) {
for (int i = 0; i < canonical_values.size(); i++) {
printer->Print(
" case $value$:\n",
"value", canonical_values[i]);
}
}
} // namespace
// ===================================================================
EnumFieldGenerator::
EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
: FieldGenerator(params), descriptor_(descriptor) {
SetEnumVariables(params, descriptor, &variables_);
LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
}
EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_,
"public $type$ $name$;\n");
if (params_.generate_has()) {
printer->Print(variables_,
"public boolean has$capitalized_name$;\n");
}
}
void EnumFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$ = $default$;\n");
if (params_.generate_has()) {
printer->Print(variables_,
"has$capitalized_name$ = false;\n");
}
}
void EnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"int value = input.readInt32();\n"
"switch (value) {\n");
PrintCaseLabels(printer, canonical_values_);
printer->Print(variables_,
" this.$name$ = value;\n");
if (params_.generate_has()) {
printer->Print(variables_,
" has$capitalized_name$ = true;\n");
}
printer->Print(
" break;\n"
"}\n");
// No default case: in case of invalid value from the wire, preserve old
// field value. Also we are not storing the invalid value into the unknown
// fields, because there is no way to get the value out.
}
void EnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
if (descriptor_->is_required() && !params_.generate_has()) {
// Always serialize a required field if we don't have the 'has' signal.
printer->Print(variables_,
"output.writeInt32($number$, this.$name$);\n");
} else {
if (params_.generate_has()) {
printer->Print(variables_,
"if (this.$name$ != $default$ || has$capitalized_name$) {\n");
} else {
printer->Print(variables_,
"if (this.$name$ != $default$) {\n");
}
printer->Print(variables_,
" output.writeInt32($number$, this.$name$);\n"
"}\n");
}
}
void EnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
if (descriptor_->is_required() && !params_.generate_has()) {
printer->Print(variables_,
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeInt32Size($number$, this.$name$);\n");
} else {
if (params_.generate_has()) {
printer->Print(variables_,
"if (this.$name$ != $default$ || has$capitalized_name$) {\n");
} else {
printer->Print(variables_,
"if (this.$name$ != $default$) {\n");
}
printer->Print(variables_,
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeInt32Size($number$, this.$name$);\n"
"}\n");
}
}
void EnumFieldGenerator::GenerateEqualsCode(io::Printer* printer) const {
if (params_.use_reference_types_for_primitives()
&& !params_.reftypes_primitive_enums()) {
printer->Print(variables_,
"if (this.$name$ == null) {\n"
" if (other.$name$ != null) {\n"
" return false;\n"
" }\n"
"} else if (!this.$name$.equals(other.$name$)) {\n"
" return false;"
"}\n");
} else {
// We define equality as serialized form equality. If generate_has(),
// then if the field value equals the default value in both messages,
// but one's 'has' field is set and the other's is not, the serialized
// forms are different and we should return false.
printer->Print(variables_,
"if (this.$name$ != other.$name$");
if (params_.generate_has()) {
printer->Print(variables_,
"\n"
" || (this.$name$ == $default$\n"
" && this.has$capitalized_name$ != other.has$capitalized_name$)");
}
printer->Print(") {\n"
" return false;\n"
"}\n");
}
}
void EnumFieldGenerator::GenerateHashCodeCode(io::Printer* printer) const {
printer->Print(
"result = 31 * result + ");
if (params_.use_reference_types_for_primitives()
&& !params_.reftypes_primitive_enums()) {
printer->Print(variables_,
"(this.$name$ == null ? 0 : this.$name$)");
} else {
printer->Print(variables_,
"this.$name$");
}
printer->Print(";\n");
}
// ===================================================================
AccessorEnumFieldGenerator::
AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
const Params& params, int has_bit_index)
: FieldGenerator(params), descriptor_(descriptor) {
SetEnumVariables(params, descriptor, &variables_);
LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
SetBitOperationVariables("has", has_bit_index, &variables_);
}
AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
void AccessorEnumFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_,
"private int $name$_;\n"
"public int get$capitalized_name$() {\n"
" return $name$_;\n"
"}\n"
"public $message_name$ set$capitalized_name$(int value) {\n"
" $name$_ = value;\n"
" $set_has$;\n"
" return this;\n"
"}\n"
"public boolean has$capitalized_name$() {\n"
" return $get_has$;\n"
"}\n"
"public $message_name$ clear$capitalized_name$() {\n"
" $name$_ = $default$;\n"
" $clear_has$;\n"
" return this;\n"
"}\n");
}
void AccessorEnumFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$_ = $default$;\n");
}
void AccessorEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"int value = input.readInt32();\n"
"switch (value) {\n");
PrintCaseLabels(printer, canonical_values_);
printer->Print(variables_,
" $name$_ = value;\n"
" $set_has$;\n"
" break;\n"
"}\n");
// No default case: in case of invalid value from the wire, preserve old
// field value. Also we are not storing the invalid value into the unknown
// fields, because there is no way to get the value out.
}
void AccessorEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($get_has$) {\n"
" output.writeInt32($number$, $name$_);\n"
"}\n");
}
void AccessorEnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($get_has$) {\n"
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeInt32Size($number$, $name$_);\n"
"}\n");
}
void AccessorEnumFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($different_has$\n"
" || $name$_ != other.$name$_) {\n"
" return false;\n"
"}\n");
}
void AccessorEnumFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
printer->Print(variables_,
"result = 31 * result + $name$_;\n");
}
// ===================================================================
RepeatedEnumFieldGenerator::
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
: FieldGenerator(params), descriptor_(descriptor) {
SetEnumVariables(params, descriptor, &variables_);
LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
}
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
void RepeatedEnumFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_,
"public $type$[] $name$;\n");
}
void RepeatedEnumFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$ = $repeated_default$;\n");
}
void RepeatedEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
// First, figure out the maximum length of the array, then parse,
// and finally copy the valid values to the field.
printer->Print(variables_,
"int length = com.google.protobuf.nano.WireFormatNano\n"
" .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
"int[] validValues = new int[length];\n"
"int validCount = 0;\n"
"for (int i = 0; i < length; i++) {\n"
" if (i != 0) { // tag for first value already consumed.\n"
" input.readTag();\n"
" }\n"
" int value = input.readInt32();\n"
" switch (value) {\n");
printer->Indent();
PrintCaseLabels(printer, canonical_values_);
printer->Outdent();
printer->Print(variables_,
" validValues[validCount++] = value;\n"
" break;\n"
" }\n"
"}\n"
"if (validCount != 0) {\n"
" int i = this.$name$ == null ? 0 : this.$name$.length;\n"
" if (i == 0 && validCount == validValues.length) {\n"
" this.$name$ = validValues;\n"
" } else {\n"
" int[] newArray = new int[i + validCount];\n"
" if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
" }\n"
" java.lang.System.arraycopy(validValues, 0, newArray, i, validCount);\n"
" this.$name$ = newArray;\n"
" }\n"
"}\n");
}
void RepeatedEnumFieldGenerator::
GenerateMergingCodeFromPacked(io::Printer* printer) const {
printer->Print(variables_,
"int bytes = input.readRawVarint32();\n"
"int limit = input.pushLimit(bytes);\n"
"// First pass to compute array length.\n"
"int arrayLength = 0;\n"
"int startPos = input.getPosition();\n"
"while (input.getBytesUntilLimit() > 0) {\n"
" switch (input.readInt32()) {\n");
printer->Indent();
PrintCaseLabels(printer, canonical_values_);
printer->Outdent();
printer->Print(variables_,
" arrayLength++;\n"
" break;\n"
" }\n"
"}\n"
"if (arrayLength != 0) {\n"
" input.rewindToPosition(startPos);\n"
" int i = this.$name$ == null ? 0 : this.$name$.length;\n"
" int[] newArray = new int[i + arrayLength];\n"
" if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
" }\n"
" while (input.getBytesUntilLimit() > 0) {\n"
" int value = input.readInt32();\n"
" switch (value) {\n");
printer->Indent();
printer->Indent();
PrintCaseLabels(printer, canonical_values_);
printer->Outdent();
printer->Outdent();
printer->Print(variables_,
" newArray[i++] = value;\n"
" break;\n"
" }\n"
" }\n"
" this.$name$ = newArray;\n"
"}\n"
"input.popLimit(limit);\n");
}
void RepeatedEnumFieldGenerator::
GenerateRepeatedDataSizeCode(io::Printer* printer) const {
// Creates a variable dataSize and puts the serialized size in there.
printer->Print(variables_,
"int dataSize = 0;\n"
"for (int i = 0; i < this.$name$.length; i++) {\n"
" int element = this.$name$[i];\n"
" dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeInt32SizeNoTag(element);\n"
"}\n");
}
void RepeatedEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ != null && this.$name$.length > 0) {\n");
printer->Indent();
if (descriptor_->options().packed()) {
GenerateRepeatedDataSizeCode(printer);
printer->Print(variables_,
"output.writeRawVarint32($tag$);\n"
"output.writeRawVarint32(dataSize);\n"
"for (int i = 0; i < this.$name$.length; i++) {\n"
" output.writeRawVarint32(this.$name$[i]);\n"
"}\n");
} else {
printer->Print(variables_,
"for (int i = 0; i < this.$name$.length; i++) {\n"
" output.writeInt32($number$, this.$name$[i]);\n"
"}\n");
}
printer->Outdent();
printer->Print(variables_,
"}\n");
}
void RepeatedEnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ != null && this.$name$.length > 0) {\n");
printer->Indent();
GenerateRepeatedDataSizeCode(printer);
printer->Print(
"size += dataSize;\n");
if (descriptor_->options().packed()) {
printer->Print(variables_,
"size += $tag_size$;\n"
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeRawVarint32Size(dataSize);\n");
} else {
printer->Print(variables_,
"size += $tag_size$ * this.$name$.length;\n");
}
printer->Outdent();
printer->Print(
"}\n");
}
void RepeatedEnumFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!com.google.protobuf.nano.InternalNano.equals(\n"
" this.$name$, other.$name$)) {\n"
" return false;\n"
"}\n");
}
void RepeatedEnumFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
printer->Print(variables_,
"result = 31 * result\n"
" + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
}
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

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

View File

@ -0,0 +1,150 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: bduff@google.com (Brian Duff)
#include <google/protobuf/compiler/javanano/javanano_extension.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/wire_format.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {
using internal::WireFormat;
using internal::WireFormatLite;
namespace {
const char* GetTypeConstantName(const FieldDescriptor::Type type) {
switch (type) {
case FieldDescriptor::TYPE_INT32 : return "TYPE_INT32" ;
case FieldDescriptor::TYPE_UINT32 : return "TYPE_UINT32" ;
case FieldDescriptor::TYPE_SINT32 : return "TYPE_SINT32" ;
case FieldDescriptor::TYPE_FIXED32 : return "TYPE_FIXED32" ;
case FieldDescriptor::TYPE_SFIXED32: return "TYPE_SFIXED32";
case FieldDescriptor::TYPE_INT64 : return "TYPE_INT64" ;
case FieldDescriptor::TYPE_UINT64 : return "TYPE_UINT64" ;
case FieldDescriptor::TYPE_SINT64 : return "TYPE_SINT64" ;
case FieldDescriptor::TYPE_FIXED64 : return "TYPE_FIXED64" ;
case FieldDescriptor::TYPE_SFIXED64: return "TYPE_SFIXED64";
case FieldDescriptor::TYPE_FLOAT : return "TYPE_FLOAT" ;
case FieldDescriptor::TYPE_DOUBLE : return "TYPE_DOUBLE" ;
case FieldDescriptor::TYPE_BOOL : return "TYPE_BOOL" ;
case FieldDescriptor::TYPE_STRING : return "TYPE_STRING" ;
case FieldDescriptor::TYPE_BYTES : return "TYPE_BYTES" ;
case FieldDescriptor::TYPE_ENUM : return "TYPE_ENUM" ;
case FieldDescriptor::TYPE_GROUP : return "TYPE_GROUP" ;
case FieldDescriptor::TYPE_MESSAGE : return "TYPE_MESSAGE" ;
// No default because we want the compiler to complain if any new
// types are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return NULL;
}
} // namespace
void SetVariables(const FieldDescriptor* descriptor, const Params params,
map<string, string>* variables) {
(*variables)["extends"] = ClassName(params, descriptor->containing_type());
(*variables)["name"] = RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
bool repeated = descriptor->is_repeated();
(*variables)["repeated"] = repeated ? "Repeated" : "";
(*variables)["type"] = GetTypeConstantName(descriptor->type());
JavaType java_type = GetJavaType(descriptor->type());
string tag = SimpleItoa(WireFormat::MakeTag(descriptor));
if (java_type == JAVATYPE_MESSAGE) {
(*variables)["ext_type"] = "MessageTyped";
string message_type = ClassName(params, descriptor->message_type());
if (repeated) {
message_type += "[]";
}
(*variables)["class"] = message_type;
// For message typed extensions, tags_params contains a single tag
// for both singular and repeated cases.
(*variables)["tag_params"] = tag;
} else {
(*variables)["ext_type"] = "PrimitiveTyped";
if (!repeated) {
(*variables)["class"] = BoxedPrimitiveTypeName(java_type);
(*variables)["tag_params"] = tag;
} else {
(*variables)["class"] = PrimitiveTypeName(java_type) + "[]";
if (!descriptor->is_packable()) {
// Non-packable: nonPackedTag == tag, packedTag == 0
(*variables)["tag_params"] = tag + ", " + tag + ", 0";
} else if (descriptor->options().packed()) {
// Packable and packed: tag == packedTag
string non_packed_tag = SimpleItoa(WireFormatLite::MakeTag(
descriptor->number(),
WireFormat::WireTypeForFieldType(descriptor->type())));
(*variables)["tag_params"] = tag + ", " + non_packed_tag + ", " + tag;
} else {
// Packable and not packed: tag == nonPackedTag
string packed_tag = SimpleItoa(WireFormatLite::MakeTag(
descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
(*variables)["tag_params"] = tag + ", " + tag + ", " + packed_tag;
}
}
}
}
ExtensionGenerator::
ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params)
: params_(params), descriptor_(descriptor) {
SetVariables(descriptor, params, &variables_);
}
ExtensionGenerator::~ExtensionGenerator() {}
void ExtensionGenerator::Generate(io::Printer* printer) const {
printer->Print("\n");
PrintFieldComment(printer, descriptor_);
printer->Print(variables_,
"public static final com.google.protobuf.nano.Extension<\n"
" $extends$,\n"
" $class$> $name$ =\n"
" com.google.protobuf.nano.Extension.create$repeated$$ext_type$(\n"
" com.google.protobuf.nano.Extension.$type$,\n"
" $class$.class,\n"
" $tag_params$);\n");
}
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,74 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: bduff@google.com (Brian Duff)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/descriptor.pb.h>
namespace google {
namespace protobuf {
namespace io {
class Printer; // printer.h
}
}
namespace protobuf {
namespace compiler {
namespace javanano {
class ExtensionGenerator {
public:
explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params);
~ExtensionGenerator();
void Generate(io::Printer* printer) const;
private:
const Params& params_;
const FieldDescriptor* descriptor_;
map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
};
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_

View File

@ -0,0 +1,143 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/javanano/javanano_field.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
#include <google/protobuf/compiler/javanano/javanano_message_field.h>
#include <google/protobuf/stubs/common.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {
FieldGenerator::~FieldGenerator() {}
bool FieldGenerator::SavedDefaultNeeded() const {
// No saved default for this field by default.
// Subclasses whose instances may need saved defaults will override this
// and return the appropriate value.
return false;
}
void FieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
// No saved default for this field by default.
// Subclasses whose instances may need saved defaults will override this
// and generate the appropriate init code to the printer.
}
void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const {
// Reaching here indicates a bug. Cases are:
// - This FieldGenerator should support packing, but this method should be
// overridden.
// - This FieldGenerator doesn't support packing, and this method should
// never have been called.
GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
<< "called on field generator that does not support packing.";
}
// =============================================
FieldGeneratorMap::FieldGeneratorMap(
const Descriptor* descriptor, const Params &params)
: descriptor_(descriptor),
field_generators_(
new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
int next_has_bit_index = 0;
bool saved_defaults_needed = false;
// Construct all the FieldGenerators.
for (int i = 0; i < descriptor->field_count(); i++) {
FieldGenerator* field_generator = MakeGenerator(
descriptor->field(i), params, &next_has_bit_index);
saved_defaults_needed = saved_defaults_needed
|| field_generator->SavedDefaultNeeded();
field_generators_[i].reset(field_generator);
}
total_bits_ = next_has_bit_index;
saved_defaults_needed_ = saved_defaults_needed;
}
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
const Params &params, int* next_has_bit_index) {
JavaType java_type = GetJavaType(field);
if (field->is_repeated()) {
switch (java_type) {
case JAVATYPE_MESSAGE:
return new RepeatedMessageFieldGenerator(field, params);
case JAVATYPE_ENUM:
return new RepeatedEnumFieldGenerator(field, params);
default:
return new RepeatedPrimitiveFieldGenerator(field, params);
}
} else if (params.optional_field_accessors() && field->is_optional()
&& java_type != JAVATYPE_MESSAGE) {
// We need a has-bit for each primitive/enum field because their default
// values could be same as explicitly set values. But we don't need it
// for a message field because they have no defaults and Nano uses 'null'
// for unset messages, which cannot be set explicitly.
switch (java_type) {
case JAVATYPE_ENUM:
return new AccessorEnumFieldGenerator(
field, params, (*next_has_bit_index)++);
default:
return new AccessorPrimitiveFieldGenerator(
field, params, (*next_has_bit_index)++);
}
} else {
switch (java_type) {
case JAVATYPE_MESSAGE:
return new MessageFieldGenerator(field, params);
case JAVATYPE_ENUM:
return new EnumFieldGenerator(field, params);
default:
return new PrimitiveFieldGenerator(field, params);
}
}
}
FieldGeneratorMap::~FieldGeneratorMap() {}
const FieldGenerator& FieldGeneratorMap::get(
const FieldDescriptor* field) const {
GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
return *field_generators_[field->index()];
}
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,119 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/compiler/javanano/javanano_params.h>
namespace google {
namespace protobuf {
namespace io {
class Printer; // printer.h
}
}
namespace protobuf {
namespace compiler {
namespace javanano {
class FieldGenerator {
public:
FieldGenerator(const Params& params) : params_(params) {}
virtual ~FieldGenerator();
virtual bool SavedDefaultNeeded() const;
virtual void GenerateInitSavedDefaultCode(io::Printer* printer) const;
// Generates code for Java fields and methods supporting this field.
// If this field needs a saved default (SavedDefaultNeeded() is true),
// then @lazy_init controls how the static field for that default value
// and its initialization code should be generated. If @lazy_init is
// true, the static field is not declared final and the initialization
// code is generated only when GenerateInitSavedDefaultCode is called;
// otherwise, the static field is declared final and initialized inline.
// GenerateInitSavedDefaultCode will not be called in the latter case.
virtual void GenerateMembers(
io::Printer* printer, bool lazy_init) const = 0;
virtual void GenerateClearCode(io::Printer* printer) const = 0;
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
// Generates code to merge from packed serialized form. The default
// implementation will fail; subclasses which can handle packed serialized
// forms will override this and print appropriate code to the printer.
virtual void GenerateMergingCodeFromPacked(io::Printer* printer) const;
virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
virtual void GenerateHashCodeCode(io::Printer* printer) const = 0;
protected:
const Params& params_;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
};
// Convenience class which constructs FieldGenerators for a Descriptor.
class FieldGeneratorMap {
public:
explicit FieldGeneratorMap(const Descriptor* descriptor, const Params &params);
~FieldGeneratorMap();
const FieldGenerator& get(const FieldDescriptor* field) const;
int total_bits() const { return total_bits_; }
bool saved_defaults_needed() const { return saved_defaults_needed_; }
private:
const Descriptor* descriptor_;
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
int total_bits_;
bool saved_defaults_needed_;
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
const Params &params, int* next_has_bit_index);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__

View File

@ -0,0 +1,263 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <iostream>
#include <google/protobuf/compiler/javanano/javanano_file.h>
#include <google/protobuf/compiler/javanano/javanano_enum.h>
#include <google/protobuf/compiler/javanano/javanano_extension.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/compiler/javanano/javanano_message.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {
namespace {
// Recursively searches the given message to see if it contains any extensions.
bool UsesExtensions(const Message& message) {
const Reflection* reflection = message.GetReflection();
// We conservatively assume that unknown fields are extensions.
if (reflection->GetUnknownFields(message).field_count() > 0) return true;
vector<const FieldDescriptor*> fields;
reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
if (fields[i]->is_extension()) return true;
if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (fields[i]->is_repeated()) {
int size = reflection->FieldSize(message, fields[i]);
for (int j = 0; j < size; j++) {
const Message& sub_message =
reflection->GetRepeatedMessage(message, fields[i], j);
if (UsesExtensions(sub_message)) return true;
}
} else {
const Message& sub_message = reflection->GetMessage(message, fields[i]);
if (UsesExtensions(sub_message)) return true;
}
}
}
return false;
}
} // namespace
FileGenerator::FileGenerator(const FileDescriptor* file, const Params& params)
: file_(file),
params_(params),
java_package_(FileJavaPackage(params, file)),
classname_(FileClassName(params, file)) {}
FileGenerator::~FileGenerator() {}
bool FileGenerator::Validate(string* error) {
// Check for extensions
FileDescriptorProto file_proto;
file_->CopyTo(&file_proto);
if (UsesExtensions(file_proto) && !params_.store_unknown_fields()) {
error->assign(file_->name());
error->append(
": Java NANO_RUNTIME only supports extensions when the "
"'store_unknown_fields' generator option is 'true'.");
return false;
}
if (file_->service_count() != 0 && !params_.ignore_services()) {
error->assign(file_->name());
error->append(
": Java NANO_RUNTIME does not support services\"");
return false;
}
if (!IsOuterClassNeeded(params_, file_)) {
return true;
}
// Check whether legacy javanano generator would omit the outer class.
if (!params_.has_java_outer_classname(file_->name())
&& file_->message_type_count() == 1
&& file_->enum_type_count() == 0 && file_->extension_count() == 0) {
cout << "INFO: " << file_->name() << ":" << endl;
cout << "Javanano generator has changed to align with java generator. "
"An outer class will be created for this file and the single message "
"in the file will become a nested class. Use java_multiple_files to "
"skip generating the outer class, or set an explicit "
"java_outer_classname to suppress this message." << endl;
}
// Check that no class name matches the file's class name. This is a common
// problem that leads to Java compile errors that can be hard to understand.
// It's especially bad when using the java_multiple_files, since we would
// end up overwriting the outer class with one of the inner ones.
bool found_conflict = false;
for (int i = 0; !found_conflict && i < file_->message_type_count(); i++) {
if (file_->message_type(i)->name() == classname_) {
found_conflict = true;
}
}
if (params_.java_enum_style()) {
for (int i = 0; !found_conflict && i < file_->enum_type_count(); i++) {
if (file_->enum_type(i)->name() == classname_) {
found_conflict = true;
}
}
}
if (found_conflict) {
error->assign(file_->name());
error->append(
": Cannot generate Java output because the file's outer class name, \"");
error->append(classname_);
error->append(
"\", matches the name of one of the types declared inside it. "
"Please either rename the type or use the java_outer_classname "
"option to specify a different outer class name for the .proto file.");
return false;
}
return true;
}
void FileGenerator::Generate(io::Printer* printer) {
// We don't import anything because we refer to all classes by their
// fully-qualified names in the generated source.
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n");
if (!java_package_.empty()) {
printer->Print(
"\n"
"package $package$;\n",
"package", java_package_);
}
// Note: constants (from enums, emitted in the loop below) may have the same names as constants
// in the nested classes. This causes Java warnings, but is not fatal, so we suppress those
// warnings here in the top-most class declaration.
printer->Print(
"\n"
"@SuppressWarnings(\"hiding\")\n"
"public interface $classname$ {\n",
"classname", classname_);
printer->Indent();
// -----------------------------------------------------------------
// Extensions.
for (int i = 0; i < file_->extension_count(); i++) {
ExtensionGenerator(file_->extension(i), params_).Generate(printer);
}
// Enums.
for (int i = 0; i < file_->enum_type_count(); i++) {
EnumGenerator(file_->enum_type(i), params_).Generate(printer);
}
// Messages.
if (!params_.java_multiple_files(file_->name())) {
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator(file_->message_type(i), params_).Generate(printer);
}
}
// Static variables.
for (int i = 0; i < file_->message_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects?
MessageGenerator(file_->message_type(i), params_).GenerateStaticVariables(printer);
}
printer->Outdent();
printer->Print(
"}\n");
}
template<typename GeneratorClass, typename DescriptorClass>
static void GenerateSibling(const string& package_dir,
const string& java_package,
const DescriptorClass* descriptor,
GeneratorContext* output_directory,
vector<string>* file_list,
const Params& params) {
string filename = package_dir + descriptor->name() + ".java";
file_list->push_back(filename);
scoped_ptr<io::ZeroCopyOutputStream> output(
output_directory->Open(filename));
io::Printer printer(output.get(), '$');
printer.Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n");
if (!java_package.empty()) {
printer.Print(
"\n"
"package $package$;\n",
"package", java_package);
}
GeneratorClass(descriptor, params).Generate(&printer);
}
void FileGenerator::GenerateSiblings(const string& package_dir,
GeneratorContext* output_directory,
vector<string>* file_list) {
if (params_.java_multiple_files(file_->name())) {
for (int i = 0; i < file_->message_type_count(); i++) {
GenerateSibling<MessageGenerator>(package_dir, java_package_,
file_->message_type(i),
output_directory, file_list, params_);
}
if (params_.java_enum_style()) {
for (int i = 0; i < file_->enum_type_count(); i++) {
GenerateSibling<EnumGenerator>(package_dir, java_package_,
file_->enum_type(i),
output_directory, file_list, params_);
}
}
}
}
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,94 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/javanano/javanano_params.h>
namespace google {
namespace protobuf {
class FileDescriptor; // descriptor.h
namespace io {
class Printer; // printer.h
}
namespace compiler {
class GeneratorContext; // code_generator.h
}
}
namespace protobuf {
namespace compiler {
namespace javanano {
class FileGenerator {
public:
explicit FileGenerator(const FileDescriptor* file, const Params& params);
~FileGenerator();
// Checks for problems that would otherwise lead to cryptic compile errors.
// Returns true if there are no problems, or writes an error description to
// the given string and returns false otherwise.
bool Validate(string* error);
void Generate(io::Printer* printer);
// If we aren't putting everything into one file, this will write all the
// files other than the outer file (i.e. one for each message, enum, and
// service type).
void GenerateSiblings(const string& package_dir,
GeneratorContext* output_directory,
vector<string>* file_list);
const string& java_package() { return java_package_; }
const string& classname() { return classname_; }
private:
const FileDescriptor* file_;
const Params& params_;
string java_package_;
string classname_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
};
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__

View File

@ -0,0 +1,219 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/compiler/javanano/javanano_generator.h>
#include <google/protobuf/compiler/javanano/javanano_file.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {
namespace {
string TrimString(const string& s) {
string::size_type start = s.find_first_not_of(" \n\r\t");
if (start == string::npos) {
return "";
}
string::size_type end = s.find_last_not_of(" \n\r\t") + 1;
return s.substr(start, end - start);
}
} // namespace
void UpdateParamsRecursively(Params& params,
const FileDescriptor* file) {
// Add any parameters for this file
if (file->options().has_java_outer_classname()) {
params.set_java_outer_classname(
file->name(), file->options().java_outer_classname());
}
if (file->options().has_java_package()) {
params.set_java_package(
file->name(), file->options().java_package());
}
if (file->options().has_java_multiple_files()) {
params.set_java_multiple_files(
file->name(), file->options().java_multiple_files());
}
// Loop through all dependent files recursively
// adding dep
for (int i = 0; i < file->dependency_count(); i++) {
UpdateParamsRecursively(params, file->dependency(i));
}
}
JavaNanoGenerator::JavaNanoGenerator() {}
JavaNanoGenerator::~JavaNanoGenerator() {}
bool JavaNanoGenerator::Generate(const FileDescriptor* file,
const string& parameter,
GeneratorContext* output_directory,
string* error) const {
vector<pair<string, string> > options;
ParseGeneratorParameter(parameter, &options);
// -----------------------------------------------------------------
// parse generator options
// Name a file where we will write a list of generated file names, one
// per line.
string output_list_file;
Params params(file->name());
// Update per file params
UpdateParamsRecursively(params, file);
// Replace any existing options with ones from command line
for (int i = 0; i < options.size(); i++) {
string option_name = TrimString(options[i].first);
string option_value = TrimString(options[i].second);
if (option_name == "output_list_file") {
output_list_file = option_value;
} else if (option_name == "java_package") {
vector<string> parts;
SplitStringUsing(option_value, "|", &parts);
if (parts.size() != 2) {
*error = "Bad java_package, expecting filename|PackageName found '"
+ option_value + "'";
return false;
}
params.set_java_package(parts[0], parts[1]);
} else if (option_name == "java_outer_classname") {
vector<string> parts;
SplitStringUsing(option_value, "|", &parts);
if (parts.size() != 2) {
*error = "Bad java_outer_classname, "
"expecting filename|ClassName found '"
+ option_value + "'";
return false;
}
params.set_java_outer_classname(parts[0], parts[1]);
} else if (option_name == "store_unknown_fields") {
params.set_store_unknown_fields(option_value == "true");
} else if (option_name == "java_multiple_files") {
params.set_override_java_multiple_files(option_value == "true");
} else if (option_name == "java_nano_generate_has") {
params.set_generate_has(option_value == "true");
} else if (option_name == "enum_style") {
params.set_java_enum_style(option_value == "java");
} else if (option_name == "optional_field_style") {
params.set_optional_field_accessors(option_value == "accessors");
params.set_use_reference_types_for_primitives(option_value == "reftypes"
|| option_value == "reftypes_compat_mode");
params.set_reftypes_primitive_enums(
option_value == "reftypes_compat_mode");
if (option_value == "reftypes_compat_mode") {
params.set_generate_clear(false);
}
} else if (option_name == "generate_equals") {
params.set_generate_equals(option_value == "true");
} else if (option_name == "ignore_services") {
params.set_ignore_services(option_value == "true");
} else if (option_name == "parcelable_messages") {
params.set_parcelable_messages(option_value == "true");
} else {
*error = "Ignore unknown javanano generator option: " + option_name;
}
}
// Check illegal parameter combinations
// Note: the enum-like optional_field_style generator param ensures
// that we can never have illegal combinations of field styles
// (e.g. reftypes and accessors can't be on at the same time).
if (params.generate_has()
&& (params.optional_field_accessors()
|| params.use_reference_types_for_primitives())) {
error->assign("java_nano_generate_has=true cannot be used in conjunction"
" with optional_field_style=accessors or optional_field_style=reftypes");
return false;
}
// -----------------------------------------------------------------
FileGenerator file_generator(file, params);
if (!file_generator.Validate(error)) {
return false;
}
string package_dir =
StringReplace(file_generator.java_package(), ".", "/", true);
if (!package_dir.empty()) package_dir += "/";
vector<string> all_files;
if (IsOuterClassNeeded(params, file)) {
string java_filename = package_dir;
java_filename += file_generator.classname();
java_filename += ".java";
all_files.push_back(java_filename);
// Generate main java file.
scoped_ptr<io::ZeroCopyOutputStream> output(
output_directory->Open(java_filename));
io::Printer printer(output.get(), '$');
file_generator.Generate(&printer);
}
// Generate sibling files.
file_generator.GenerateSiblings(package_dir, output_directory, &all_files);
// Generate output list if requested.
if (!output_list_file.empty()) {
// Generate output list. This is just a simple text file placed in a
// deterministic location which lists the .java files being generated.
scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
output_directory->Open(output_list_file));
io::Printer srclist_printer(srclist_raw_output.get(), '$');
for (int i = 0; i < all_files.size(); i++) {
srclist_printer.Print("$filename$\n", "filename", all_files[i]);
}
}
return true;
}
} // namespace java
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

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

View File

@ -0,0 +1,566 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <limits>
#include <vector>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {
const char kThickSeparator[] =
"// ===================================================================\n";
const char kThinSeparator[] =
"// -------------------------------------------------------------------\n";
class RenameKeywords {
private:
hash_set<string> java_keywords_set_;
public:
RenameKeywords() {
static const char* kJavaKeywordsList[] = {
// Reserved Java Keywords
"abstract", "assert", "boolean", "break", "byte", "case", "catch",
"char", "class", "const", "continue", "default", "do", "double", "else",
"enum", "extends", "final", "finally", "float", "for", "goto", "if",
"implements", "import", "instanceof", "int", "interface", "long",
"native", "new", "package", "private", "protected", "public", "return",
"short", "static", "strictfp", "super", "switch", "synchronized",
"this", "throw", "throws", "transient", "try", "void", "volatile", "while",
// Reserved Keywords for Literals
"false", "null", "true"
};
for (int i = 0; i < GOOGLE_ARRAYSIZE(kJavaKeywordsList); i++) {
java_keywords_set_.insert(kJavaKeywordsList[i]);
}
}
// Used to rename the a field name if it's a java keyword. Specifically
// this is used to rename the ["name"] or ["capitalized_name"] field params.
// (http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html)
string RenameJavaKeywordsImpl(const string& input) {
string result = input;
if (java_keywords_set_.find(result) != java_keywords_set_.end()) {
result += "_";
}
return result;
}
};
static RenameKeywords sRenameKeywords;
namespace {
const char* kDefaultPackage = "";
const string& FieldName(const FieldDescriptor* field) {
// Groups are hacky: The name of the field is just the lower-cased name
// of the group type. In Java, though, we would like to retain the original
// capitalization of the type name.
if (field->type() == FieldDescriptor::TYPE_GROUP) {
return field->message_type()->name();
} else {
return field->name();
}
}
string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) {
string result;
// Note: I distrust ctype.h due to locales.
for (int i = 0; i < input.size(); i++) {
if ('a' <= input[i] && input[i] <= 'z') {
if (cap_next_letter) {
result += input[i] + ('A' - 'a');
} else {
result += input[i];
}
cap_next_letter = false;
} else if ('A' <= input[i] && input[i] <= 'Z') {
if (i == 0 && !cap_next_letter) {
// Force first letter to lower-case unless explicitly told to
// capitalize it.
result += input[i] + ('a' - 'A');
} else {
// Capital letters after the first are left as-is.
result += input[i];
}
cap_next_letter = false;
} else if ('0' <= input[i] && input[i] <= '9') {
result += input[i];
cap_next_letter = true;
} else {
cap_next_letter = true;
}
}
return result;
}
} // namespace
string UnderscoresToCamelCase(const FieldDescriptor* field) {
return UnderscoresToCamelCaseImpl(FieldName(field), false);
}
string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
return UnderscoresToCamelCaseImpl(FieldName(field), true);
}
string UnderscoresToCamelCase(const MethodDescriptor* method) {
return UnderscoresToCamelCaseImpl(method->name(), false);
}
string RenameJavaKeywords(const string& input) {
return sRenameKeywords.RenameJavaKeywordsImpl(input);
}
string StripProto(const string& filename) {
if (HasSuffixString(filename, ".protodevel")) {
return StripSuffixString(filename, ".protodevel");
} else {
return StripSuffixString(filename, ".proto");
}
}
string FileClassName(const Params& params, const FileDescriptor* file) {
if (params.has_java_outer_classname(file->name())) {
return params.java_outer_classname(file->name());
} else {
// Use the filename itself with underscores removed
// and a CamelCase style name.
string basename;
string::size_type last_slash = file->name().find_last_of('/');
if (last_slash == string::npos) {
basename = file->name();
} else {
basename = file->name().substr(last_slash + 1);
}
return UnderscoresToCamelCaseImpl(StripProto(basename), true);
}
}
string FileJavaPackage(const Params& params, const FileDescriptor* file) {
if (params.has_java_package(file->name())) {
return params.java_package(file->name());
} else {
string result = kDefaultPackage;
if (!file->package().empty()) {
if (!result.empty()) result += '.';
result += file->package();
}
return result;
}
}
bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file) {
// If java_multiple_files is false, the outer class is always needed.
if (!params.java_multiple_files(file->name())) {
return true;
}
// File-scope extensions need the outer class as the scope.
if (file->extension_count() != 0) {
return true;
}
// If container interfaces are not generated, file-scope enums need the
// outer class as the scope.
if (file->enum_type_count() != 0 && !params.java_enum_style()) {
return true;
}
return false;
}
string ToJavaName(const Params& params, const string& name, bool is_class,
const Descriptor* parent, const FileDescriptor* file) {
string result;
if (parent != NULL) {
result.append(ClassName(params, parent));
} else if (is_class && params.java_multiple_files(file->name())) {
result.append(FileJavaPackage(params, file));
} else {
result.append(ClassName(params, file));
}
if (!result.empty()) result.append(1, '.');
result.append(RenameJavaKeywords(name));
return result;
}
string ClassName(const Params& params, const FileDescriptor* descriptor) {
string result = FileJavaPackage(params, descriptor);
if (!result.empty()) result += '.';
result += FileClassName(params, descriptor);
return result;
}
string ClassName(const Params& params, const EnumDescriptor* descriptor) {
const Descriptor* parent = descriptor->containing_type();
// When using Java enum style, an enum's class name contains the enum name.
// Use the standard ToJavaName translation.
if (params.java_enum_style()) {
return ToJavaName(params, descriptor->name(), true, parent,
descriptor->file());
}
// Otherwise the enum members are accessed from the enclosing class.
if (parent != NULL) {
return ClassName(params, parent);
} else {
return ClassName(params, descriptor->file());
}
}
string FieldConstantName(const FieldDescriptor *field) {
string name = field->name() + "_FIELD_NUMBER";
UpperString(&name);
return name;
}
string FieldDefaultConstantName(const FieldDescriptor *field) {
return "_" + RenameJavaKeywords(UnderscoresToCamelCase(field)) + "Default";
}
void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
// We don't want to print group bodies so we cut off after the first line
// (the second line for extensions).
string def = field->DebugString();
string::size_type first_line_end = def.find_first_of('\n');
printer->Print("// $def$\n",
"def", def.substr(0, first_line_end));
if (field->is_extension()) {
string::size_type second_line_start = first_line_end + 1;
string::size_type second_line_length =
def.find('\n', second_line_start) - second_line_start;
printer->Print("// $def$\n",
"def", def.substr(second_line_start, second_line_length));
}
}
JavaType GetJavaType(FieldDescriptor::Type field_type) {
switch (field_type) {
case FieldDescriptor::TYPE_INT32:
case FieldDescriptor::TYPE_UINT32:
case FieldDescriptor::TYPE_SINT32:
case FieldDescriptor::TYPE_FIXED32:
case FieldDescriptor::TYPE_SFIXED32:
return JAVATYPE_INT;
case FieldDescriptor::TYPE_INT64:
case FieldDescriptor::TYPE_UINT64:
case FieldDescriptor::TYPE_SINT64:
case FieldDescriptor::TYPE_FIXED64:
case FieldDescriptor::TYPE_SFIXED64:
return JAVATYPE_LONG;
case FieldDescriptor::TYPE_FLOAT:
return JAVATYPE_FLOAT;
case FieldDescriptor::TYPE_DOUBLE:
return JAVATYPE_DOUBLE;
case FieldDescriptor::TYPE_BOOL:
return JAVATYPE_BOOLEAN;
case FieldDescriptor::TYPE_STRING:
return JAVATYPE_STRING;
case FieldDescriptor::TYPE_BYTES:
return JAVATYPE_BYTES;
case FieldDescriptor::TYPE_ENUM:
return JAVATYPE_ENUM;
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
return JAVATYPE_MESSAGE;
// No default because we want the compiler to complain if any new
// types are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return JAVATYPE_INT;
}
string PrimitiveTypeName(JavaType type) {
switch (type) {
case JAVATYPE_INT : return "int";
case JAVATYPE_LONG : return "long";
case JAVATYPE_FLOAT : return "float";
case JAVATYPE_DOUBLE : return "double";
case JAVATYPE_BOOLEAN: return "boolean";
case JAVATYPE_STRING : return "java.lang.String";
case JAVATYPE_BYTES : return "byte[]";
case JAVATYPE_ENUM : return "int";
case JAVATYPE_MESSAGE: return "";
// No default because we want the compiler to complain if any new
// JavaTypes are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
}
string BoxedPrimitiveTypeName(JavaType type) {
switch (type) {
case JAVATYPE_INT : return "java.lang.Integer";
case JAVATYPE_LONG : return "java.lang.Long";
case JAVATYPE_FLOAT : return "java.lang.Float";
case JAVATYPE_DOUBLE : return "java.lang.Double";
case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
case JAVATYPE_STRING : return "java.lang.String";
case JAVATYPE_BYTES : return "byte[]";
case JAVATYPE_ENUM : return "java.lang.Integer";
case JAVATYPE_MESSAGE: return "";
// No default because we want the compiler to complain if any new
// JavaTypes are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
}
string EmptyArrayName(const Params& params, const FieldDescriptor* field) {
switch (GetJavaType(field)) {
case JAVATYPE_INT : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
case JAVATYPE_LONG : return "com.google.protobuf.nano.WireFormatNano.EMPTY_LONG_ARRAY";
case JAVATYPE_FLOAT : return "com.google.protobuf.nano.WireFormatNano.EMPTY_FLOAT_ARRAY";
case JAVATYPE_DOUBLE : return "com.google.protobuf.nano.WireFormatNano.EMPTY_DOUBLE_ARRAY";
case JAVATYPE_BOOLEAN: return "com.google.protobuf.nano.WireFormatNano.EMPTY_BOOLEAN_ARRAY";
case JAVATYPE_STRING : return "com.google.protobuf.nano.WireFormatNano.EMPTY_STRING_ARRAY";
case JAVATYPE_BYTES : return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES_ARRAY";
case JAVATYPE_ENUM : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
case JAVATYPE_MESSAGE: return ClassName(params, field->message_type()) + ".EMPTY_ARRAY";
// No default because we want the compiler to complain if any new
// JavaTypes are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
}
string DefaultValue(const Params& params, const FieldDescriptor* field) {
if (field->label() == FieldDescriptor::LABEL_REPEATED) {
return EmptyArrayName(params, field);
}
if (params.use_reference_types_for_primitives()) {
if (params.reftypes_primitive_enums()
&& field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
return "Integer.MIN_VALUE";
}
return "null";
}
// Switch on cpp_type since we need to know which default_value_* method
// of FieldDescriptor to call.
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
return SimpleItoa(field->default_value_int32());
case FieldDescriptor::CPPTYPE_UINT32:
// Need to print as a signed int since Java has no unsigned.
return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
case FieldDescriptor::CPPTYPE_INT64:
return SimpleItoa(field->default_value_int64()) + "L";
case FieldDescriptor::CPPTYPE_UINT64:
return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
"L";
case FieldDescriptor::CPPTYPE_DOUBLE: {
double value = field->default_value_double();
if (value == numeric_limits<double>::infinity()) {
return "Double.POSITIVE_INFINITY";
} else if (value == -numeric_limits<double>::infinity()) {
return "Double.NEGATIVE_INFINITY";
} else if (value != value) {
return "Double.NaN";
} else {
return SimpleDtoa(value) + "D";
}
}
case FieldDescriptor::CPPTYPE_FLOAT: {
float value = field->default_value_float();
if (value == numeric_limits<float>::infinity()) {
return "Float.POSITIVE_INFINITY";
} else if (value == -numeric_limits<float>::infinity()) {
return "Float.NEGATIVE_INFINITY";
} else if (value != value) {
return "Float.NaN";
} else {
return SimpleFtoa(value) + "F";
}
}
case FieldDescriptor::CPPTYPE_BOOL:
return field->default_value_bool() ? "true" : "false";
case FieldDescriptor::CPPTYPE_STRING:
if (!field->default_value_string().empty()) {
// Point it to the static final in the generated code.
return FieldDefaultConstantName(field);
} else {
if (field->type() == FieldDescriptor::TYPE_BYTES) {
return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES";
} else {
return "\"\"";
}
}
case FieldDescriptor::CPPTYPE_ENUM:
return ClassName(params, field->enum_type()) + "." +
RenameJavaKeywords(field->default_value_enum()->name());
case FieldDescriptor::CPPTYPE_MESSAGE:
return "null";
// No default because we want the compiler to complain if any new
// types are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
}
static const char* kBitMasks[] = {
"0x00000001",
"0x00000002",
"0x00000004",
"0x00000008",
"0x00000010",
"0x00000020",
"0x00000040",
"0x00000080",
"0x00000100",
"0x00000200",
"0x00000400",
"0x00000800",
"0x00001000",
"0x00002000",
"0x00004000",
"0x00008000",
"0x00010000",
"0x00020000",
"0x00040000",
"0x00080000",
"0x00100000",
"0x00200000",
"0x00400000",
"0x00800000",
"0x01000000",
"0x02000000",
"0x04000000",
"0x08000000",
"0x10000000",
"0x20000000",
"0x40000000",
"0x80000000",
};
string GetBitFieldName(int index) {
string var_name = "bitField";
var_name += SimpleItoa(index);
var_name += "_";
return var_name;
}
string GetBitFieldNameForBit(int bit_index) {
return GetBitFieldName(bit_index / 32);
}
string GenerateGetBit(int bit_index) {
string var_name = GetBitFieldNameForBit(bit_index);
int bit_in_var_index = bit_index % 32;
string mask = kBitMasks[bit_in_var_index];
string result = "((" + var_name + " & " + mask + ") != 0)";
return result;
}
string GenerateSetBit(int bit_index) {
string var_name = GetBitFieldNameForBit(bit_index);
int bit_in_var_index = bit_index % 32;
string mask = kBitMasks[bit_in_var_index];
string result = var_name + " |= " + mask;
return result;
}
string GenerateClearBit(int bit_index) {
string var_name = GetBitFieldNameForBit(bit_index);
int bit_in_var_index = bit_index % 32;
string mask = kBitMasks[bit_in_var_index];
string result = var_name + " = (" + var_name + " & ~" + mask + ")";
return result;
}
string GenerateDifferentBit(int bit_index) {
string var_name = GetBitFieldNameForBit(bit_index);
int bit_in_var_index = bit_index % 32;
string mask = kBitMasks[bit_in_var_index];
string result = "((" + var_name + " & " + mask
+ ") != (other." + var_name + " & " + mask + "))";
return result;
}
void SetBitOperationVariables(const string name,
int bitIndex, map<string, string>* variables) {
(*variables)["get_" + name] = GenerateGetBit(bitIndex);
(*variables)["set_" + name] = GenerateSetBit(bitIndex);
(*variables)["clear_" + name] = GenerateClearBit(bitIndex);
(*variables)["different_" + name] = GenerateDifferentBit(bitIndex);
}
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,189 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__
#include <string>
#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/printer.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {
// Commonly-used separator comments. Thick is a line of '=', thin is a line
// of '-'.
extern const char kThickSeparator[];
extern const char kThinSeparator[];
// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
// "fooBarBaz" or "FooBarBaz", respectively.
string UnderscoresToCamelCase(const FieldDescriptor* field);
string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
// Appends an "_" to the end of a field where the name is a reserved java
// keyword. For example int32 public = 1 will generate int public_.
string RenameJavaKeywords(const string& input);
// Similar, but for method names. (Typically, this merely has the effect
// of lower-casing the first letter of the name.)
string UnderscoresToCamelCase(const MethodDescriptor* method);
// Strips ".proto" or ".protodevel" from the end of a filename.
string StripProto(const string& filename);
// Gets the unqualified class name for the file. Each .proto file becomes a
// single Java class, with all its contents nested in that class.
string FileClassName(const Params& params, const FileDescriptor* file);
// Returns the file's Java package name.
string FileJavaPackage(const Params& params, const FileDescriptor* file);
// Returns whether the Java outer class is needed, i.e. whether the option
// java_multiple_files is false, or the proto file contains any file-scope
// enums/extensions.
bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file);
// Converts the given simple name of a proto entity to its fully-qualified name
// in the Java namespace, given that it is in the given file enclosed in the
// given parent message (or NULL for file-scope entities). Whether the file's
// outer class name should be included in the return value depends on factors
// inferrable from the given arguments, including is_class which indicates
// whether the entity translates to a Java class.
string ToJavaName(const Params& params, const string& name, bool is_class,
const Descriptor* parent, const FileDescriptor* file);
// These return the fully-qualified class name corresponding to the given
// descriptor.
inline string ClassName(const Params& params, const Descriptor* descriptor) {
return ToJavaName(params, descriptor->name(), true,
descriptor->containing_type(), descriptor->file());
}
string ClassName(const Params& params, const EnumDescriptor* descriptor);
inline string ClassName(const Params& params,
const ServiceDescriptor* descriptor) {
return ToJavaName(params, descriptor->name(), true, NULL, descriptor->file());
}
inline string ExtensionIdentifierName(const Params& params,
const FieldDescriptor* descriptor) {
return ToJavaName(params, descriptor->name(), false,
descriptor->extension_scope(), descriptor->file());
}
string ClassName(const Params& params, const FileDescriptor* descriptor);
// Get the unqualified name that should be used for a field's field
// number constant.
string FieldConstantName(const FieldDescriptor *field);
string FieldDefaultConstantName(const FieldDescriptor *field);
// Print the field's proto-syntax definition as a comment.
void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field);
enum JavaType {
JAVATYPE_INT,
JAVATYPE_LONG,
JAVATYPE_FLOAT,
JAVATYPE_DOUBLE,
JAVATYPE_BOOLEAN,
JAVATYPE_STRING,
JAVATYPE_BYTES,
JAVATYPE_ENUM,
JAVATYPE_MESSAGE
};
JavaType GetJavaType(FieldDescriptor::Type field_type);
inline JavaType GetJavaType(const FieldDescriptor* field) {
return GetJavaType(field->type());
}
string PrimitiveTypeName(JavaType type);
// Get the fully-qualified class name for a boxed primitive type, e.g.
// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message
// types.
string BoxedPrimitiveTypeName(JavaType type);
string EmptyArrayName(const Params& params, const FieldDescriptor* field);
string DefaultValue(const Params& params, const FieldDescriptor* field);
// Methods for shared bitfields.
// Gets the name of the shared bitfield for the given field index.
string GetBitFieldName(int index);
// Gets the name of the shared bitfield for the given bit index.
// Effectively, GetBitFieldName(bit_index / 32)
string GetBitFieldNameForBit(int bit_index);
// Generates the java code for the expression that returns whether the bit at
// the given bit index is set.
// Example: "((bitField1_ & 0x04000000) != 0)"
string GenerateGetBit(int bit_index);
// Generates the java code for the expression that sets the bit at the given
// bit index.
// Example: "bitField1_ |= 0x04000000"
string GenerateSetBit(int bit_index);
// Generates the java code for the expression that clears the bit at the given
// bit index.
// Example: "bitField1_ = (bitField1_ & ~0x04000000)"
string GenerateClearBit(int bit_index);
// Generates the java code for the expression that returns whether the bit at
// the given bit index contains different values in the current object and
// another object accessible via the variable 'other'.
// Example: "((bitField1_ & 0x04000000) != (other.bitField1_ & 0x04000000))"
string GenerateDifferentBit(int bit_index);
// Sets the 'get_*', 'set_*', 'clear_*' and 'different_*' variables, where * is
// the given name of the bit, to the appropriate Java expressions for the given
// bit index.
void SetBitOperationVariables(const string name,
int bitIndex, map<string, string>* variables);
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__

View File

@ -0,0 +1,555 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <algorithm>
#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/compiler/javanano/javanano_message.h>
#include <google/protobuf/compiler/javanano/javanano_enum.h>
#include <google/protobuf/compiler/javanano/javanano_extension.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/descriptor.pb.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {
using internal::WireFormat;
using internal::WireFormatLite;
namespace {
struct FieldOrderingByNumber {
inline bool operator()(const FieldDescriptor* a,
const FieldDescriptor* b) const {
return a->number() < b->number();
}
};
// Sort the fields of the given Descriptor by number into a new[]'d array
// and return it.
const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
const FieldDescriptor** fields =
new const FieldDescriptor*[descriptor->field_count()];
for (int i = 0; i < descriptor->field_count(); i++) {
fields[i] = descriptor->field(i);
}
sort(fields, fields + descriptor->field_count(),
FieldOrderingByNumber());
return fields;
}
} // namespace
// ===================================================================
MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
: params_(params),
descriptor_(descriptor),
field_generators_(descriptor, params) {
}
MessageGenerator::~MessageGenerator() {}
void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
// Generate static members for all nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects?
MessageGenerator(descriptor_->nested_type(i), params_)
.GenerateStaticVariables(printer);
}
}
void MessageGenerator::GenerateStaticVariableInitializers(
io::Printer* printer) {
// Generate static member initializers for all nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects?
MessageGenerator(descriptor_->nested_type(i), params_)
.GenerateStaticVariableInitializers(printer);
}
}
void MessageGenerator::Generate(io::Printer* printer) {
if (!params_.store_unknown_fields() &&
(descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the "
"'store_unknown_fields' generator option is 'true'\n";
}
const string& file_name = descriptor_->file()->name();
bool is_own_file =
params_.java_multiple_files(file_name)
&& descriptor_->containing_type() == NULL;
if (is_own_file) {
// Note: constants (from enums and fields requiring stored defaults, emitted in the loop below)
// may have the same names as constants in the nested classes. This causes Java warnings, but
// is not fatal, so we suppress those warnings here in the top-most class declaration.
printer->Print(
"\n"
"@SuppressWarnings(\"hiding\")\n"
"public final class $classname$ extends\n",
"classname", descriptor_->name());
} else {
printer->Print(
"\n"
"public static final class $classname$ extends\n",
"classname", descriptor_->name());
}
if (params_.store_unknown_fields() && params_.parcelable_messages()) {
printer->Print(
" com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$> {\n",
"classname", descriptor_->name());
} else if (params_.store_unknown_fields()) {
printer->Print(
" com.google.protobuf.nano.ExtendableMessageNano<$classname$> {\n",
"classname", descriptor_->name());
} else if (params_.parcelable_messages()) {
printer->Print(
" com.google.protobuf.nano.android.ParcelableMessageNano {\n");
} else {
printer->Print(
" com.google.protobuf.nano.MessageNano {\n");
}
printer->Indent();
// Nested types and extensions
for (int i = 0; i < descriptor_->extension_count(); i++) {
ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
}
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
}
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
}
// Lazy initialization of otherwise static final fields can help prevent the
// class initializer from being generated. We want to prevent it because it
// stops ProGuard from inlining any methods in this class into call sites and
// therefore reducing the method count. However, extensions are best kept as
// public static final fields with initializers, so with their existence we
// won't bother with lazy initialization.
bool lazy_init = descriptor_->extension_count() == 0;
// Empty array
if (lazy_init) {
printer->Print(
"\n"
"private static volatile $classname$[] _emptyArray;\n"
"public static $classname$[] emptyArray() {\n"
" // Lazily initializes the empty array\n"
" if (_emptyArray == null) {\n"
" synchronized (\n"
" com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
" if (_emptyArray == null) {\n"
" _emptyArray = new $classname$[0];\n"
" }\n"
" }\n"
" }\n"
" return _emptyArray;\n"
"}\n",
"classname", descriptor_->name());
} else {
printer->Print(
"\n"
"private static final $classname$[] EMPTY_ARRAY = {};\n"
"public static $classname$[] emptyArray() {\n"
" return EMPTY_ARRAY;\n"
"}\n",
"classname", descriptor_->name());
}
// Integers for bit fields
int totalInts = (field_generators_.total_bits() + 31) / 32;
if (totalInts > 0) {
printer->Print("\n");
for (int i = 0; i < totalInts; i++) {
printer->Print("private int $bit_field_name$;\n",
"bit_field_name", GetBitFieldName(i));
}
}
// Fields and maybe their default values
for (int i = 0; i < descriptor_->field_count(); i++) {
printer->Print("\n");
PrintFieldComment(printer, descriptor_->field(i));
field_generators_.get(descriptor_->field(i)).GenerateMembers(
printer, lazy_init);
}
// Constructor, with lazy init code if needed
if (lazy_init && field_generators_.saved_defaults_needed()) {
printer->Print(
"\n"
"private static volatile boolean _classInitialized;\n"
"\n"
"public $classname$() {\n"
" // Lazily initializes the field defaults\n"
" if (!_classInitialized) {\n"
" synchronized (\n"
" com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
" if (!_classInitialized) {\n",
"classname", descriptor_->name());
printer->Indent();
printer->Indent();
printer->Indent();
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); i++) {
field_generators_.get(descriptor_->field(i))
.GenerateInitSavedDefaultCode(printer);
}
printer->Outdent();
printer->Outdent();
printer->Outdent();
printer->Outdent();
printer->Print(
" _classInitialized = true;\n"
" }\n"
" }\n"
" }\n");
if (params_.generate_clear()) {
printer->Print(" clear();\n");
}
printer->Print("}\n");
} else {
if (params_.generate_clear()) {
printer->Print(
"\n"
"public $classname$() {\n"
" clear();\n"
"}\n",
"classname", descriptor_->name());
}
}
// Other methods in this class
GenerateClear(printer);
if (params_.generate_equals()) {
GenerateEquals(printer);
GenerateHashCode(printer);
}
GenerateMessageSerializationMethods(printer);
GenerateMergeFromMethods(printer);
GenerateParseFromMethods(printer);
printer->Outdent();
printer->Print("}\n");
}
// ===================================================================
void MessageGenerator::
GenerateMessageSerializationMethods(io::Printer* printer) {
// Rely on the parent implementations of writeTo() and getSerializedSize()
// if there are no fields to serialize in this message.
if (descriptor_->field_count() == 0) {
return;
}
scoped_array<const FieldDescriptor*> sorted_fields(
SortFieldsByNumber(descriptor_));
printer->Print(
"\n"
"@Override\n"
"public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n"
" throws java.io.IOException {\n");
printer->Indent();
// Output the fields in sorted order
for (int i = 0; i < descriptor_->field_count(); i++) {
GenerateSerializeOneField(printer, sorted_fields[i]);
}
// The parent implementation will write any unknown fields if necessary.
printer->Print(
"super.writeTo(output);\n");
printer->Outdent();
printer->Print("}\n");
// The parent implementation will get the serialized size for unknown
// fields if necessary.
printer->Print(
"\n"
"@Override\n"
"protected int computeSerializedSize() {\n"
" int size = super.computeSerializedSize();\n");
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); i++) {
field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
}
printer->Outdent();
printer->Print(
" return size;\n"
"}\n");
}
void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
scoped_array<const FieldDescriptor*> sorted_fields(
SortFieldsByNumber(descriptor_));
printer->Print(
"\n"
"@Override\n"
"public $classname$ mergeFrom(\n"
" com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
" throws java.io.IOException {\n",
"classname", descriptor_->name());
printer->Indent();
printer->Print(
"while (true) {\n");
printer->Indent();
printer->Print(
"int tag = input.readTag();\n"
"switch (tag) {\n");
printer->Indent();
printer->Print(
"case 0:\n" // zero signals EOF / limit reached
" return this;\n"
"default: {\n");
printer->Indent();
if (params_.store_unknown_fields()) {
printer->Print(
"if (!storeUnknownField(input, tag)) {\n"
" return this;\n"
"}\n");
} else {
printer->Print(
"if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
" return this;\n" // it's an endgroup tag
"}\n");
}
printer->Print("break;\n");
printer->Outdent();
printer->Print("}\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = sorted_fields[i];
uint32 tag = WireFormatLite::MakeTag(field->number(),
WireFormat::WireTypeForFieldType(field->type()));
printer->Print(
"case $tag$: {\n",
"tag", SimpleItoa(tag));
printer->Indent();
field_generators_.get(field).GenerateMergingCode(printer);
printer->Outdent();
printer->Print(
" break;\n"
"}\n");
if (field->is_packable()) {
// To make packed = true wire compatible, we generate parsing code from a
// packed version of this field regardless of field->options().packed().
uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
printer->Print(
"case $tag$: {\n",
"tag", SimpleItoa(packed_tag));
printer->Indent();
field_generators_.get(field).GenerateMergingCodeFromPacked(printer);
printer->Outdent();
printer->Print(
" break;\n"
"}\n");
}
}
printer->Outdent();
printer->Outdent();
printer->Outdent();
printer->Print(
" }\n" // switch (tag)
" }\n" // while (true)
"}\n");
}
void MessageGenerator::
GenerateParseFromMethods(io::Printer* printer) {
// Note: These are separate from GenerateMessageSerializationMethods()
// because they need to be generated even for messages that are optimized
// for code size.
printer->Print(
"\n"
"public static $classname$ parseFrom(byte[] data)\n"
" throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
" return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
"}\n"
"\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
" throws java.io.IOException {\n"
" return new $classname$().mergeFrom(input);\n"
"}\n",
"classname", descriptor_->name());
}
void MessageGenerator::GenerateSerializeOneField(
io::Printer* printer, const FieldDescriptor* field) {
field_generators_.get(field).GenerateSerializationCode(printer);
}
void MessageGenerator::GenerateClear(io::Printer* printer) {
if (!params_.generate_clear()) {
return;
}
printer->Print(
"\n"
"public $classname$ clear() {\n",
"classname", descriptor_->name());
printer->Indent();
// Clear bit fields.
int totalInts = (field_generators_.total_bits() + 31) / 32;
for (int i = 0; i < totalInts; i++) {
printer->Print("$bit_field_name$ = 0;\n",
"bit_field_name", GetBitFieldName(i));
}
// Call clear for all of the fields.
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
field_generators_.get(field).GenerateClearCode(printer);
}
// Clear unknown fields.
if (params_.store_unknown_fields()) {
printer->Print("unknownFieldData = null;\n");
}
printer->Outdent();
printer->Print(
" cachedSize = -1;\n"
" return this;\n"
"}\n");
}
void MessageGenerator::GenerateEquals(io::Printer* printer) {
// Don't override if there are no fields. We could generate an
// equals method that compares types, but often empty messages
// are used as namespaces.
if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
return;
}
printer->Print(
"\n"
"@Override\n"
"public boolean equals(Object o) {\n");
printer->Indent();
printer->Print(
"if (o == this) {\n"
" return true;\n"
"}\n"
"if (!(o instanceof $classname$)) {\n"
" return false;\n"
"}\n"
"$classname$ other = ($classname$) o;\n",
"classname", descriptor_->name());
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
field_generators_.get(field).GenerateEqualsCode(printer);
}
if (params_.store_unknown_fields()) {
printer->Print(
"return unknownFieldDataEquals(other);\n");
} else {
printer->Print(
"return true;\n");
}
printer->Outdent();
printer->Print("}\n");
}
void MessageGenerator::GenerateHashCode(io::Printer* printer) {
if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
return;
}
printer->Print(
"\n"
"@Override\n"
"public int hashCode() {\n");
printer->Indent();
printer->Print("int result = 17;\n");
printer->Print("result = 31 * result + getClass().getName().hashCode();\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
field_generators_.get(field).GenerateHashCodeCode(printer);
}
if (params_.store_unknown_fields()) {
printer->Print(
"result = 31 * result + unknownFieldDataHashCode();\n");
}
printer->Print("return result;\n");
printer->Outdent();
printer->Print("}\n");
}
// ===================================================================
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

@ -0,0 +1,95 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__
#include <string>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/compiler/javanano/javanano_field.h>
#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/stubs/common.h>
namespace google {
namespace protobuf {
namespace io {
class Printer; // printer.h
}
}
namespace protobuf {
namespace compiler {
namespace javanano {
class MessageGenerator {
public:
explicit MessageGenerator(const Descriptor* descriptor, const Params& params);
~MessageGenerator();
// All static variables have to be declared at the top-level of the file
// so that we can control initialization order, which is important for
// DescriptorProto bootstrapping to work.
void GenerateStaticVariables(io::Printer* printer);
// Output code which initializes the static variables generated by
// GenerateStaticVariables().
void GenerateStaticVariableInitializers(io::Printer* printer);
// Generate the class itself.
void Generate(io::Printer* printer);
private:
void GenerateMessageSerializationMethods(io::Printer* printer);
void GenerateMergeFromMethods(io::Printer* printer);
void GenerateParseFromMethods(io::Printer* printer);
void GenerateSerializeOneField(io::Printer* printer,
const FieldDescriptor* field);
void GenerateClear(io::Printer* printer);
void GenerateEquals(io::Printer* printer);
void GenerateHashCode(io::Printer* printer);
const Params& params_;
const Descriptor* descriptor_;
FieldGeneratorMap field_generators_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
};
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__

View File

@ -0,0 +1,259 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <map>
#include <string>
#include <google/protobuf/compiler/javanano/javanano_message_field.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {
using internal::WireFormat;
using internal::WireFormatLite;
namespace {
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
// repeat code between this and the other field types.
void SetMessageVariables(const Params& params,
const FieldDescriptor* descriptor, map<string, string>* variables) {
(*variables)["name"] =
RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
(*variables)["capitalized_name"] =
RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
(*variables)["number"] = SimpleItoa(descriptor->number());
(*variables)["type"] = ClassName(params, descriptor->message_type());
(*variables)["group_or_message"] =
(descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
"Group" : "Message";
(*variables)["message_name"] = descriptor->containing_type()->name();
//(*variables)["message_type"] = descriptor->message_type()->name();
(*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
}
} // namespace
// ===================================================================
MessageFieldGenerator::
MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
: FieldGenerator(params), descriptor_(descriptor) {
SetMessageVariables(params, descriptor, &variables_);
}
MessageFieldGenerator::~MessageFieldGenerator() {}
void MessageFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_,
"public $type$ $name$;\n");
}
void MessageFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$ = null;\n");
}
void MessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ == null) {\n"
" this.$name$ = new $type$();\n"
"}\n");
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
"input.readGroup(this.$name$, $number$);\n");
} else {
printer->Print(variables_,
"input.readMessage(this.$name$);\n");
}
}
void MessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ != null) {\n"
" output.write$group_or_message$($number$, this.$name$);\n"
"}\n");
}
void MessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ != null) {\n"
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$group_or_message$Size($number$, this.$name$);\n"
"}\n");
}
void MessageFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ == null) { \n"
" if (other.$name$ != null) {\n"
" return false;\n"
" }\n"
"} else {\n"
" if (!this.$name$.equals(other.$name$)) {\n"
" return false;\n"
" }\n"
"}\n");
}
void MessageFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
printer->Print(variables_,
"result = 31 * result +\n"
" (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
}
// ===================================================================
RepeatedMessageFieldGenerator::
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
: FieldGenerator(params), descriptor_(descriptor) {
SetMessageVariables(params, descriptor, &variables_);
}
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
void RepeatedMessageFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_,
"public $type$[] $name$;\n");
}
void RepeatedMessageFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$ = $type$.emptyArray();\n");
}
void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
// First, figure out the length of the array, then parse.
printer->Print(variables_,
"int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
" .getRepeatedFieldArrayLength(input, $tag$);\n"
"int i = this.$name$ == null ? 0 : this.$name$.length;\n"
"$type$[] newArray =\n"
" new $type$[i + arrayLength];\n"
"if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
"}\n"
"for (; i < newArray.length - 1; i++) {\n"
" newArray[i] = new $type$();\n");
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
" input.readGroup(newArray[i], $number$);\n");
} else {
printer->Print(variables_,
" input.readMessage(newArray[i]);\n");
}
printer->Print(variables_,
" input.readTag();\n"
"}\n"
"// Last one without readTag.\n"
"newArray[i] = new $type$();\n");
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
"input.readGroup(newArray[i], $number$);\n");
} else {
printer->Print(variables_,
"input.readMessage(newArray[i]);\n");
}
printer->Print(variables_,
"this.$name$ = newArray;\n");
}
void RepeatedMessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ != null && this.$name$.length > 0) {\n"
" for (int i = 0; i < this.$name$.length; i++) {\n"
" $type$ element = this.$name$[i];\n"
" if (element != null) {\n"
" output.write$group_or_message$($number$, element);\n"
" }\n"
" }\n"
"}\n");
}
void RepeatedMessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ != null && this.$name$.length > 0) {\n"
" for (int i = 0; i < this.$name$.length; i++) {\n"
" $type$ element = this.$name$[i];\n"
" if (element != null) {\n"
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$group_or_message$Size($number$, element);\n"
" }\n"
" }\n"
"}\n");
}
void RepeatedMessageFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!com.google.protobuf.nano.InternalNano.equals(\n"
" this.$name$, other.$name$)) {\n"
" return false;\n"
"}\n");
}
void RepeatedMessageFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
printer->Print(variables_,
"result = 31 * result\n"
" + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
}
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

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

View File

@ -0,0 +1,240 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2010 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: wink@google.com (Wink Saville)
#ifndef PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
#define PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
#include <map>
#include <set>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {
enum eMultipleFiles { JAVANANO_MUL_UNSET, JAVANANO_MUL_FALSE, JAVANANO_MUL_TRUE };
// Parameters for used by the generators
class Params {
public:
typedef map<string, string> NameMap;
typedef set<string> NameSet;
private:
string empty_;
string base_name_;
eMultipleFiles override_java_multiple_files_;
bool store_unknown_fields_;
NameMap java_packages_;
NameMap java_outer_classnames_;
NameSet java_multiple_files_;
bool generate_has_;
bool java_enum_style_;
bool optional_field_accessors_;
bool use_reference_types_for_primitives_;
bool generate_equals_;
bool ignore_services_;
bool parcelable_messages_;
bool reftypes_primitive_enums_;
bool generate_clear_;
public:
Params(const string & base_name) :
empty_(""),
base_name_(base_name),
override_java_multiple_files_(JAVANANO_MUL_UNSET),
store_unknown_fields_(false),
generate_has_(false),
java_enum_style_(false),
optional_field_accessors_(false),
use_reference_types_for_primitives_(false),
generate_equals_(false),
ignore_services_(false),
parcelable_messages_(false),
reftypes_primitive_enums_(false),
generate_clear_(true) {
}
const string& base_name() const {
return base_name_;
}
bool has_java_package(const string& file_name) const {
return java_packages_.find(file_name)
!= java_packages_.end();
}
void set_java_package(const string& file_name,
const string& java_package) {
java_packages_[file_name] = java_package;
}
const string& java_package(const string& file_name) const {
NameMap::const_iterator itr;
itr = java_packages_.find(file_name);
if (itr == java_packages_.end()) {
return empty_;
} else {
return itr->second;
}
}
const NameMap& java_packages() {
return java_packages_;
}
bool has_java_outer_classname(const string& file_name) const {
return java_outer_classnames_.find(file_name)
!= java_outer_classnames_.end();
}
void set_java_outer_classname(const string& file_name,
const string& java_outer_classname) {
java_outer_classnames_[file_name] = java_outer_classname;
}
const string& java_outer_classname(const string& file_name) const {
NameMap::const_iterator itr;
itr = java_outer_classnames_.find(file_name);
if (itr == java_outer_classnames_.end()) {
return empty_;
} else {
return itr->second;
}
}
const NameMap& java_outer_classnames() {
return java_outer_classnames_;
}
void set_override_java_multiple_files(bool java_multiple_files) {
if (java_multiple_files) {
override_java_multiple_files_ = JAVANANO_MUL_TRUE;
} else {
override_java_multiple_files_ = JAVANANO_MUL_FALSE;
}
}
void clear_override_java_multiple_files() {
override_java_multiple_files_ = JAVANANO_MUL_UNSET;
}
void set_java_multiple_files(const string& file_name, bool value) {
if (value) {
java_multiple_files_.insert(file_name);
} else {
java_multiple_files_.erase(file_name);
}
}
bool java_multiple_files(const string& file_name) const {
switch (override_java_multiple_files_) {
case JAVANANO_MUL_FALSE:
return false;
case JAVANANO_MUL_TRUE:
return true;
default:
return java_multiple_files_.find(file_name)
!= java_multiple_files_.end();
}
}
void set_store_unknown_fields(bool value) {
store_unknown_fields_ = value;
}
bool store_unknown_fields() const {
return store_unknown_fields_;
}
void set_generate_has(bool value) {
generate_has_ = value;
}
bool generate_has() const {
return generate_has_;
}
void set_java_enum_style(bool value) {
java_enum_style_ = value;
}
bool java_enum_style() const {
return java_enum_style_;
}
void set_optional_field_accessors(bool value) {
optional_field_accessors_ = value;
}
bool optional_field_accessors() const {
return optional_field_accessors_;
}
void set_use_reference_types_for_primitives(bool value) {
use_reference_types_for_primitives_ = value;
}
bool use_reference_types_for_primitives() const {
return use_reference_types_for_primitives_;
}
void set_generate_equals(bool value) {
generate_equals_ = value;
}
bool generate_equals() const {
return generate_equals_;
}
void set_ignore_services(bool value) {
ignore_services_ = value;
}
bool ignore_services() const {
return ignore_services_;
}
void set_parcelable_messages(bool value) {
parcelable_messages_ = value;
}
bool parcelable_messages() const {
return parcelable_messages_;
}
void set_reftypes_primitive_enums(bool value) {
reftypes_primitive_enums_ = value;
}
bool reftypes_primitive_enums() const {
return reftypes_primitive_enums_;
}
void set_generate_clear(bool value) {
generate_clear_ = value;
}
bool generate_clear() const {
return generate_clear_;
}
};
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_

View File

@ -0,0 +1,910 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <map>
#include <math.h>
#include <string>
#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {
using internal::WireFormat;
using internal::WireFormatLite;
namespace {
bool IsReferenceType(JavaType type) {
switch (type) {
case JAVATYPE_INT : return false;
case JAVATYPE_LONG : return false;
case JAVATYPE_FLOAT : return false;
case JAVATYPE_DOUBLE : return false;
case JAVATYPE_BOOLEAN: return false;
case JAVATYPE_STRING : return true;
case JAVATYPE_BYTES : return true;
case JAVATYPE_ENUM : return false;
case JAVATYPE_MESSAGE: return true;
// No default because we want the compiler to complain if any new
// JavaTypes are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return false;
}
bool IsArrayType(JavaType type) {
switch (type) {
case JAVATYPE_INT : return false;
case JAVATYPE_LONG : return false;
case JAVATYPE_FLOAT : return false;
case JAVATYPE_DOUBLE : return false;
case JAVATYPE_BOOLEAN: return false;
case JAVATYPE_STRING : return false;
case JAVATYPE_BYTES : return true;
case JAVATYPE_ENUM : return false;
case JAVATYPE_MESSAGE: return false;
// No default because we want the compiler to complain if any new
// JavaTypes are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return false;
}
const char* GetCapitalizedType(const FieldDescriptor* field) {
switch (field->type()) {
case FieldDescriptor::TYPE_INT32 : return "Int32" ;
case FieldDescriptor::TYPE_UINT32 : return "UInt32" ;
case FieldDescriptor::TYPE_SINT32 : return "SInt32" ;
case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ;
case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
case FieldDescriptor::TYPE_INT64 : return "Int64" ;
case FieldDescriptor::TYPE_UINT64 : return "UInt64" ;
case FieldDescriptor::TYPE_SINT64 : return "SInt64" ;
case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ;
case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
case FieldDescriptor::TYPE_FLOAT : return "Float" ;
case FieldDescriptor::TYPE_DOUBLE : return "Double" ;
case FieldDescriptor::TYPE_BOOL : return "Bool" ;
case FieldDescriptor::TYPE_STRING : return "String" ;
case FieldDescriptor::TYPE_BYTES : return "Bytes" ;
case FieldDescriptor::TYPE_ENUM : return "Enum" ;
case FieldDescriptor::TYPE_GROUP : return "Group" ;
case FieldDescriptor::TYPE_MESSAGE : return "Message" ;
// No default because we want the compiler to complain if any new
// types are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return NULL;
}
// For encodings with fixed sizes, returns that size in bytes. Otherwise
// returns -1.
int FixedSize(FieldDescriptor::Type type) {
switch (type) {
case FieldDescriptor::TYPE_INT32 : return -1;
case FieldDescriptor::TYPE_INT64 : return -1;
case FieldDescriptor::TYPE_UINT32 : return -1;
case FieldDescriptor::TYPE_UINT64 : return -1;
case FieldDescriptor::TYPE_SINT32 : return -1;
case FieldDescriptor::TYPE_SINT64 : return -1;
case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
case FieldDescriptor::TYPE_ENUM : return -1;
case FieldDescriptor::TYPE_STRING : return -1;
case FieldDescriptor::TYPE_BYTES : return -1;
case FieldDescriptor::TYPE_GROUP : return -1;
case FieldDescriptor::TYPE_MESSAGE : return -1;
// No default because we want the compiler to complain if any new
// types are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return -1;
}
// Return true if the type is a that has variable length
// for instance String's.
bool IsVariableLenType(JavaType type) {
switch (type) {
case JAVATYPE_INT : return false;
case JAVATYPE_LONG : return false;
case JAVATYPE_FLOAT : return false;
case JAVATYPE_DOUBLE : return false;
case JAVATYPE_BOOLEAN: return false;
case JAVATYPE_STRING : return true;
case JAVATYPE_BYTES : return true;
case JAVATYPE_ENUM : return false;
case JAVATYPE_MESSAGE: return true;
// No default because we want the compiler to complain if any new
// JavaTypes are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return false;
}
bool AllAscii(const string& text) {
for (int i = 0; i < text.size(); i++) {
if ((text[i] & 0x80) != 0) {
return false;
}
}
return true;
}
void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
map<string, string>* variables) {
(*variables)["name"] =
RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
(*variables)["capitalized_name"] =
RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
(*variables)["number"] = SimpleItoa(descriptor->number());
if (params.use_reference_types_for_primitives()
&& !descriptor->is_repeated()) {
(*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
} else {
(*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
}
// Deals with defaults. For C++-string types (string and bytes),
// we might need to have the generated code do the unicode decoding
// (see comments in InternalNano.java for gory details.). We would
// like to do this once into a static field and re-use that from
// then on.
if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
!descriptor->default_value_string().empty() &&
!params.use_reference_types_for_primitives()) {
if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
(*variables)["default"] = DefaultValue(params, descriptor);
(*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
(*variables)["default_constant_value"] = strings::Substitute(
"com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")",
CEscape(descriptor->default_value_string()));
(*variables)["default_copy_if_needed"] =
(*variables)["default"] + ".clone()";
} else if (AllAscii(descriptor->default_value_string())) {
// All chars are ASCII. In this case directly referencing a
// CEscape()'d string literal works fine.
(*variables)["default"] =
"\"" + CEscape(descriptor->default_value_string()) + "\"";
(*variables)["default_copy_if_needed"] = (*variables)["default"];
} else {
// Strings where some chars are non-ASCII. We need to save the
// default value.
(*variables)["default"] = DefaultValue(params, descriptor);
(*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
(*variables)["default_constant_value"] = strings::Substitute(
"com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
CEscape(descriptor->default_value_string()));
(*variables)["default_copy_if_needed"] = (*variables)["default"];
}
} else {
// Non-string, non-bytes field. Defaults are literals.
(*variables)["default"] = DefaultValue(params, descriptor);
(*variables)["default_copy_if_needed"] = (*variables)["default"];
}
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
(*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
(*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
WireFormat::TagSize(descriptor->number(), descriptor->type()));
(*variables)["non_packed_tag"] = SimpleItoa(
internal::WireFormatLite::MakeTag(descriptor->number(),
internal::WireFormat::WireTypeForFieldType(descriptor->type())));
int fixed_size = FixedSize(descriptor->type());
if (fixed_size != -1) {
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
}
(*variables)["message_name"] = descriptor->containing_type()->name();
(*variables)["empty_array_name"] = EmptyArrayName(params, descriptor);
}
} // namespace
// ===================================================================
PrimitiveFieldGenerator::
PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
: FieldGenerator(params), descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, params, &variables_);
}
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
bool PrimitiveFieldGenerator::SavedDefaultNeeded() const {
return variables_.find("default_constant") != variables_.end();
}
void PrimitiveFieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
if (variables_.find("default_constant") != variables_.end()) {
printer->Print(variables_,
"$default_constant$ = $default_constant_value$;\n");
}
}
void PrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer, bool lazy_init) const {
if (variables_.find("default_constant") != variables_.end()) {
// Those primitive types that need a saved default.
if (lazy_init) {
printer->Print(variables_,
"private static $type$ $default_constant$;\n");
} else {
printer->Print(variables_,
"private static final $type$ $default_constant$ =\n"
" $default_constant_value$;\n");
}
}
printer->Print(variables_,
"public $type$ $name$;\n");
if (params_.generate_has()) {
printer->Print(variables_,
"public boolean has$capitalized_name$;\n");
}
}
void PrimitiveFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$ = $default_copy_if_needed$;\n");
if (params_.generate_has()) {
printer->Print(variables_,
"has$capitalized_name$ = false;\n");
}
}
void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"this.$name$ = input.read$capitalized_type$();\n");
if (params_.generate_has()) {
printer->Print(variables_,
"has$capitalized_name$ = true;\n");
}
}
void PrimitiveFieldGenerator::
GenerateSerializationConditional(io::Printer* printer) const {
if (params_.use_reference_types_for_primitives()) {
// For reference type mode, serialize based on equality
// to null.
printer->Print(variables_,
"if (this.$name$ != null) {\n");
return;
}
if (params_.generate_has()) {
printer->Print(variables_,
"if (has$capitalized_name$ || ");
} else {
printer->Print(variables_,
"if (");
}
JavaType java_type = GetJavaType(descriptor_);
if (IsArrayType(java_type)) {
printer->Print(variables_,
"!java.util.Arrays.equals(this.$name$, $default$)) {\n");
} else if (IsReferenceType(java_type)) {
printer->Print(variables_,
"!this.$name$.equals($default$)) {\n");
} else if (java_type == JAVATYPE_FLOAT) {
printer->Print(variables_,
"java.lang.Float.floatToIntBits(this.$name$)\n"
" != java.lang.Float.floatToIntBits($default$)) {\n");
} else if (java_type == JAVATYPE_DOUBLE) {
printer->Print(variables_,
"java.lang.Double.doubleToLongBits(this.$name$)\n"
" != java.lang.Double.doubleToLongBits($default$)) {\n");
} else {
printer->Print(variables_,
"this.$name$ != $default$) {\n");
}
}
void PrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
if (descriptor_->is_required() && !params_.generate_has()) {
// Always serialize a required field if we don't have the 'has' signal.
printer->Print(variables_,
"output.write$capitalized_type$($number$, this.$name$);\n");
} else {
GenerateSerializationConditional(printer);
printer->Print(variables_,
" output.write$capitalized_type$($number$, this.$name$);\n"
"}\n");
}
}
void PrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
if (descriptor_->is_required() && !params_.generate_has()) {
printer->Print(variables_,
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$capitalized_type$Size($number$, this.$name$);\n");
} else {
GenerateSerializationConditional(printer);
printer->Print(variables_,
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$capitalized_type$Size($number$, this.$name$);\n"
"}\n");
}
}
void PrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
// We define equality as serialized form equality. If generate_has(),
// then if the field value equals the default value in both messages,
// but one's 'has' field is set and the other's is not, the serialized
// forms are different and we should return false.
JavaType java_type = GetJavaType(descriptor_);
if (java_type == JAVATYPE_BYTES) {
printer->Print(variables_,
"if (!java.util.Arrays.equals(this.$name$, other.$name$)");
if (params_.generate_has()) {
printer->Print(variables_,
"\n"
" || (java.util.Arrays.equals(this.$name$, $default$)\n"
" && this.has$capitalized_name$ != other.has$capitalized_name$)");
}
printer->Print(") {\n"
" return false;\n"
"}\n");
} else if (java_type == JAVATYPE_STRING
|| params_.use_reference_types_for_primitives()) {
printer->Print(variables_,
"if (this.$name$ == null) {\n"
" if (other.$name$ != null) {\n"
" return false;\n"
" }\n"
"} else if (!this.$name$.equals(other.$name$)");
if (params_.generate_has()) {
printer->Print(variables_,
"\n"
" || (this.$name$.equals($default$)\n"
" && this.has$capitalized_name$ != other.has$capitalized_name$)");
}
printer->Print(") {\n"
" return false;\n"
"}\n");
} else if (java_type == JAVATYPE_FLOAT) {
printer->Print(variables_,
"{\n"
" int bits = java.lang.Float.floatToIntBits(this.$name$);\n"
" if (bits != java.lang.Float.floatToIntBits(other.$name$)");
if (params_.generate_has()) {
printer->Print(variables_,
"\n"
" || (bits == java.lang.Float.floatToIntBits($default$)\n"
" && this.has$capitalized_name$ != other.has$capitalized_name$)");
}
printer->Print(") {\n"
" return false;\n"
" }\n"
"}\n");
} else if (java_type == JAVATYPE_DOUBLE) {
printer->Print(variables_,
"{\n"
" long bits = java.lang.Double.doubleToLongBits(this.$name$);\n"
" if (bits != java.lang.Double.doubleToLongBits(other.$name$)");
if (params_.generate_has()) {
printer->Print(variables_,
"\n"
" || (bits == java.lang.Double.doubleToLongBits($default$)\n"
" && this.has$capitalized_name$ != other.has$capitalized_name$)");
}
printer->Print(") {\n"
" return false;\n"
" }\n"
"}\n");
} else {
printer->Print(variables_,
"if (this.$name$ != other.$name$");
if (params_.generate_has()) {
printer->Print(variables_,
"\n"
" || (this.$name$ == $default$\n"
" && this.has$capitalized_name$ != other.has$capitalized_name$)");
}
printer->Print(") {\n"
" return false;\n"
"}\n");
}
}
void PrimitiveFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
JavaType java_type = GetJavaType(descriptor_);
if (java_type == JAVATYPE_BYTES) {
printer->Print(variables_,
"result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n");
} else if (java_type == JAVATYPE_STRING
|| params_.use_reference_types_for_primitives()) {
printer->Print(variables_,
"result = 31 * result\n"
" + (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
} else {
switch (java_type) {
// For all Java primitive types below, the hash codes match the
// results of BoxedType.valueOf(primitiveValue).hashCode().
case JAVATYPE_INT:
printer->Print(variables_,
"result = 31 * result + this.$name$;\n");
break;
case JAVATYPE_LONG:
printer->Print(variables_,
"result = 31 * result\n"
" + (int) (this.$name$ ^ (this.$name$ >>> 32));\n");
break;
case JAVATYPE_FLOAT:
printer->Print(variables_,
"result = 31 * result\n"
" + java.lang.Float.floatToIntBits(this.$name$);\n");
break;
case JAVATYPE_DOUBLE:
printer->Print(variables_,
"{\n"
" long v = java.lang.Double.doubleToLongBits(this.$name$);\n"
" result = 31 * result + (int) (v ^ (v >>> 32));\n"
"}\n");
break;
case JAVATYPE_BOOLEAN:
printer->Print(variables_,
"result = 31 * result + (this.$name$ ? 1231 : 1237);\n");
break;
default:
GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
break;
}
}
}
// ===================================================================
AccessorPrimitiveFieldGenerator::
AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
const Params& params, int has_bit_index)
: FieldGenerator(params), descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, params, &variables_);
SetBitOperationVariables("has", has_bit_index, &variables_);
}
AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
return variables_.find("default_constant") != variables_.end();
}
void AccessorPrimitiveFieldGenerator::
GenerateInitSavedDefaultCode(io::Printer* printer) const {
if (variables_.find("default_constant") != variables_.end()) {
printer->Print(variables_,
"$default_constant$ = $default_constant_value$;\n");
}
}
void AccessorPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer, bool lazy_init) const {
if (variables_.find("default_constant") != variables_.end()) {
// Those primitive types that need a saved default.
if (lazy_init) {
printer->Print(variables_,
"private static $type$ $default_constant$;\n");
} else {
printer->Print(variables_,
"private static final $type$ $default_constant$ =\n"
" $default_constant_value$;\n");
}
}
printer->Print(variables_,
"private $type$ $name$_;\n"
"public $type$ get$capitalized_name$() {\n"
" return $name$_;\n"
"}\n"
"public $message_name$ set$capitalized_name$($type$ value) {\n");
if (IsReferenceType(GetJavaType(descriptor_))) {
printer->Print(variables_,
" if (value == null) {\n"
" throw new java.lang.NullPointerException();\n"
" }\n");
}
printer->Print(variables_,
" $name$_ = value;\n"
" $set_has$;\n"
" return this;\n"
"}\n"
"public boolean has$capitalized_name$() {\n"
" return $get_has$;\n"
"}\n"
"public $message_name$ clear$capitalized_name$() {\n"
" $name$_ = $default_copy_if_needed$;\n"
" $clear_has$;\n"
" return this;\n"
"}\n");
}
void AccessorPrimitiveFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$_ = $default_copy_if_needed$;\n");
}
void AccessorPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$_ = input.read$capitalized_type$();\n"
"$set_has$;\n");
}
void AccessorPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($get_has$) {\n"
" output.write$capitalized_type$($number$, $name$_);\n"
"}\n");
}
void AccessorPrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($get_has$) {\n"
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$capitalized_type$Size($number$, $name$_);\n"
"}\n");
}
void AccessorPrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
switch (GetJavaType(descriptor_)) {
// For all Java primitive types below, the equality checks match the
// results of BoxedType.valueOf(primitiveValue).equals(otherValue).
case JAVATYPE_FLOAT:
printer->Print(variables_,
"if ($different_has$\n"
" || java.lang.Float.floatToIntBits($name$_)\n"
" != java.lang.Float.floatToIntBits(other.$name$_)) {\n"
" return false;\n"
"}\n");
break;
case JAVATYPE_DOUBLE:
printer->Print(variables_,
"if ($different_has$\n"
" || java.lang.Double.doubleToLongBits($name$_)\n"
" != java.lang.Double.doubleToLongBits(other.$name$_)) {\n"
" return false;\n"
"}\n");
break;
case JAVATYPE_INT:
case JAVATYPE_LONG:
case JAVATYPE_BOOLEAN:
printer->Print(variables_,
"if ($different_has$\n"
" || $name$_ != other.$name$_) {\n"
" return false;\n"
"}\n");
break;
case JAVATYPE_STRING:
// Accessor style would guarantee $name$_ non-null
printer->Print(variables_,
"if ($different_has$\n"
" || !$name$_.equals(other.$name$_)) {\n"
" return false;\n"
"}\n");
break;
case JAVATYPE_BYTES:
// Accessor style would guarantee $name$_ non-null
printer->Print(variables_,
"if ($different_has$\n"
" || !java.util.Arrays.equals($name$_, other.$name$_)) {\n"
" return false;\n"
"}\n");
break;
default:
GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
break;
}
}
void AccessorPrimitiveFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
switch (GetJavaType(descriptor_)) {
// For all Java primitive types below, the hash codes match the
// results of BoxedType.valueOf(primitiveValue).hashCode().
case JAVATYPE_INT:
printer->Print(variables_,
"result = 31 * result + $name$_;\n");
break;
case JAVATYPE_LONG:
printer->Print(variables_,
"result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n");
break;
case JAVATYPE_FLOAT:
printer->Print(variables_,
"result = 31 * result +\n"
" java.lang.Float.floatToIntBits($name$_);\n");
break;
case JAVATYPE_DOUBLE:
printer->Print(variables_,
"{\n"
" long v = java.lang.Double.doubleToLongBits($name$_);\n"
" result = 31 * result + (int) (v ^ (v >>> 32));\n"
"}\n");
break;
case JAVATYPE_BOOLEAN:
printer->Print(variables_,
"result = 31 * result + ($name$_ ? 1231 : 1237);\n");
break;
case JAVATYPE_STRING:
// Accessor style would guarantee $name$_ non-null
printer->Print(variables_,
"result = 31 * result + $name$_.hashCode();\n");
break;
case JAVATYPE_BYTES:
// Accessor style would guarantee $name$_ non-null
printer->Print(variables_,
"result = 31 * result + java.util.Arrays.hashCode($name$_);\n");
break;
default:
GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
break;
}
}
// ===================================================================
RepeatedPrimitiveFieldGenerator::
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
: FieldGenerator(params), descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, params, &variables_);
}
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
void RepeatedPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
printer->Print(variables_,
"public $type$[] $name$;\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$ = $default$;\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
// First, figure out the length of the array, then parse.
printer->Print(variables_,
"int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
" .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
"int i = this.$name$ == null ? 0 : this.$name$.length;\n");
if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
printer->Print(variables_,
"byte[][] newArray = new byte[i + arrayLength][];\n");
} else {
printer->Print(variables_,
"$type$[] newArray = new $type$[i + arrayLength];\n");
}
printer->Print(variables_,
"if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
"}\n"
"for (; i < newArray.length - 1; i++) {\n"
" newArray[i] = input.read$capitalized_type$();\n"
" input.readTag();\n"
"}\n"
"// Last one without readTag.\n"
"newArray[i] = input.read$capitalized_type$();\n"
"this.$name$ = newArray;\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateMergingCodeFromPacked(io::Printer* printer) const {
printer->Print(
"int length = input.readRawVarint32();\n"
"int limit = input.pushLimit(length);\n");
// If we know the elements will all be of the same size, the arrayLength
// can be calculated much more easily. However, FixedSize() returns 1 for
// repeated bool fields, which are guaranteed to have the fixed size of
// 1 byte per value only if we control the output. On the wire they can
// legally appear as variable-size integers, so we need to use the slow
// way for repeated bool fields.
if (descriptor_->type() == FieldDescriptor::TYPE_BOOL
|| FixedSize(descriptor_->type()) == -1) {
printer->Print(variables_,
"// First pass to compute array length.\n"
"int arrayLength = 0;\n"
"int startPos = input.getPosition();\n"
"while (input.getBytesUntilLimit() > 0) {\n"
" input.read$capitalized_type$();\n"
" arrayLength++;\n"
"}\n"
"input.rewindToPosition(startPos);\n");
} else {
printer->Print(variables_,
"int arrayLength = length / $fixed_size$;\n");
}
printer->Print(variables_,
"int i = this.$name$ == null ? 0 : this.$name$.length;\n"
"$type$[] newArray = new $type$[i + arrayLength];\n"
"if (i != 0) {\n"
" java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
"}\n"
"for (; i < newArray.length; i++) {\n"
" newArray[i] = input.read$capitalized_type$();\n"
"}\n"
"this.$name$ = newArray;\n"
"input.popLimit(limit);\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateRepeatedDataSizeCode(io::Printer* printer) const {
// Creates a variable dataSize and puts the serialized size in there.
// If the element type is a Java reference type, also generates
// dataCount which stores the number of non-null elements in the field.
if (IsReferenceType(GetJavaType(descriptor_))) {
printer->Print(variables_,
"int dataCount = 0;\n"
"int dataSize = 0;\n"
"for (int i = 0; i < this.$name$.length; i++) {\n"
" $type$ element = this.$name$[i];\n"
" if (element != null) {\n"
" dataCount++;\n"
" dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$capitalized_type$SizeNoTag(element);\n"
" }\n"
"}\n");
} else if (FixedSize(descriptor_->type()) == -1) {
printer->Print(variables_,
"int dataSize = 0;\n"
"for (int i = 0; i < this.$name$.length; i++) {\n"
" $type$ element = this.$name$[i];\n"
" dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$capitalized_type$SizeNoTag(element);\n"
"}\n");
} else {
printer->Print(variables_,
"int dataSize = $fixed_size$ * this.$name$.length;\n");
}
}
void RepeatedPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ != null && this.$name$.length > 0) {\n");
printer->Indent();
if (descriptor_->is_packable() && descriptor_->options().packed()) {
GenerateRepeatedDataSizeCode(printer);
printer->Print(variables_,
"output.writeRawVarint32($tag$);\n"
"output.writeRawVarint32(dataSize);\n"
"for (int i = 0; i < this.$name$.length; i++) {\n"
" output.write$capitalized_type$NoTag(this.$name$[i]);\n"
"}\n");
} else if (IsReferenceType(GetJavaType(descriptor_))) {
printer->Print(variables_,
"for (int i = 0; i < this.$name$.length; i++) {\n"
" $type$ element = this.$name$[i];\n"
" if (element != null) {\n"
" output.write$capitalized_type$($number$, element);\n"
" }\n"
"}\n");
} else {
printer->Print(variables_,
"for (int i = 0; i < this.$name$.length; i++) {\n"
" output.write$capitalized_type$($number$, this.$name$[i]);\n"
"}\n");
}
printer->Outdent();
printer->Print("}\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ != null && this.$name$.length > 0) {\n");
printer->Indent();
GenerateRepeatedDataSizeCode(printer);
printer->Print(
"size += dataSize;\n");
if (descriptor_->is_packable() && descriptor_->options().packed()) {
printer->Print(variables_,
"size += $tag_size$;\n"
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeRawVarint32Size(dataSize);\n");
} else if (IsReferenceType(GetJavaType(descriptor_))) {
printer->Print(variables_,
"size += $tag_size$ * dataCount;\n");
} else {
printer->Print(variables_,
"size += $tag_size$ * this.$name$.length;\n");
}
printer->Outdent();
printer->Print(
"}\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!com.google.protobuf.nano.InternalNano.equals(\n"
" this.$name$, other.$name$)) {\n"
" return false;\n"
"}\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
printer->Print(variables_,
"result = 31 * result\n"
" + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
}
} // namespace javanano
} // namespace compiler
} // namespace protobuf
} // namespace google

View File

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