parent
d7339318a3
commit
bde4a3254a
66 changed files with 10128 additions and 968 deletions
@ -0,0 +1,139 @@ |
||||
// 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.
|
||||
|
||||
#include <Python.h> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace python { |
||||
|
||||
// Version constant.
|
||||
// This is either 0 for python, 1 for CPP V1, 2 for CPP V2.
|
||||
//
|
||||
// 0 is default and is equivalent to
|
||||
// PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
|
||||
//
|
||||
// 1 is set with -DPYTHON_PROTO2_CPP_IMPL_V1 and is equivalent to
|
||||
// PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
|
||||
// and
|
||||
// PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=1
|
||||
//
|
||||
// 2 is set with -DPYTHON_PROTO2_CPP_IMPL_V2 and is equivalent to
|
||||
// PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
|
||||
// and
|
||||
// PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2
|
||||
#ifdef PYTHON_PROTO2_CPP_IMPL_V1 |
||||
#if PY_MAJOR_VERSION >= 3 |
||||
#error "PYTHON_PROTO2_CPP_IMPL_V1 is not supported under Python 3." |
||||
#endif |
||||
static int kImplVersion = 1; |
||||
#else |
||||
#ifdef PYTHON_PROTO2_CPP_IMPL_V2 |
||||
static int kImplVersion = 2; |
||||
#else |
||||
#ifdef PYTHON_PROTO2_PYTHON_IMPL |
||||
static int kImplVersion = 0; |
||||
#else |
||||
|
||||
// The defaults are set here. Python 3 uses the fast C++ APIv2 by default.
|
||||
// Python 2 still uses the Python version by default until some compatibility
|
||||
// issues can be worked around.
|
||||
#if PY_MAJOR_VERSION >= 3 |
||||
static int kImplVersion = 2; |
||||
#else |
||||
static int kImplVersion = 0; |
||||
#endif |
||||
|
||||
#endif // PYTHON_PROTO2_PYTHON_IMPL
|
||||
#endif // PYTHON_PROTO2_CPP_IMPL_V2
|
||||
#endif // PYTHON_PROTO2_CPP_IMPL_V1
|
||||
|
||||
static const char* kImplVersionName = "api_version"; |
||||
|
||||
static const char* kModuleName = "_api_implementation"; |
||||
static const char kModuleDocstring[] = |
||||
"_api_implementation is a module that exposes compile-time constants that\n" |
||||
"determine the default API implementation to use for Python proto2.\n" |
||||
"\n" |
||||
"It complements api_implementation.py by setting defaults using compile-time\n" |
||||
"constants defined in C, such that one can set defaults at compilation\n" |
||||
"(e.g. with blaze flag --copt=-DPYTHON_PROTO2_CPP_IMPL_V2)."; |
||||
|
||||
#if PY_MAJOR_VERSION >= 3 |
||||
static struct PyModuleDef _module = { |
||||
PyModuleDef_HEAD_INIT, |
||||
kModuleName, |
||||
kModuleDocstring, |
||||
-1, |
||||
NULL, |
||||
NULL, |
||||
NULL, |
||||
NULL, |
||||
NULL |
||||
}; |
||||
#define INITFUNC PyInit__api_implementation |
||||
#define INITFUNC_ERRORVAL NULL |
||||
#else |
||||
#define INITFUNC init_api_implementation |
||||
#define INITFUNC_ERRORVAL |
||||
#endif |
||||
|
||||
extern "C" { |
||||
PyMODINIT_FUNC INITFUNC() { |
||||
#if PY_MAJOR_VERSION >= 3 |
||||
PyObject *module = PyModule_Create(&_module); |
||||
#else |
||||
PyObject *module = Py_InitModule3( |
||||
const_cast<char*>(kModuleName), |
||||
NULL, |
||||
const_cast<char*>(kModuleDocstring)); |
||||
#endif |
||||
if (module == NULL) { |
||||
return INITFUNC_ERRORVAL; |
||||
} |
||||
|
||||
// Adds the module variable "api_version".
|
||||
if (PyModule_AddIntConstant( |
||||
module, |
||||
const_cast<char*>(kImplVersionName), |
||||
kImplVersion)) |
||||
#if PY_MAJOR_VERSION < 3 |
||||
return; |
||||
#else |
||||
{ Py_DECREF(module); return NULL; } |
||||
|
||||
return module; |
||||
#endif |
||||
} |
||||
} |
||||
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,63 @@ |
||||
#! /usr/bin/python |
||||
# |
||||
# 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. |
||||
|
||||
"""Test that the api_implementation defaults are what we expect.""" |
||||
|
||||
import os |
||||
import sys |
||||
# Clear environment implementation settings before the google3 imports. |
||||
os.environ.pop('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION', None) |
||||
os.environ.pop('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', None) |
||||
|
||||
# pylint: disable=g-import-not-at-top |
||||
from google.apputils import basetest |
||||
from google.protobuf.internal import api_implementation |
||||
|
||||
|
||||
class ApiImplementationDefaultTest(basetest.TestCase): |
||||
|
||||
if sys.version_info.major <= 2: |
||||
|
||||
def testThatPythonIsTheDefault(self): |
||||
"""If -DPYTHON_PROTO_*IMPL* was given at build time, this may fail.""" |
||||
self.assertEqual('python', api_implementation.Type()) |
||||
|
||||
else: |
||||
|
||||
def testThatCppApiV2IsTheDefault(self): |
||||
"""If -DPYTHON_PROTO_*IMPL* was given at build time, this may fail.""" |
||||
self.assertEqual('cpp', api_implementation.Type()) |
||||
self.assertEqual(2, api_implementation.Version()) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
basetest.main() |
@ -0,0 +1,58 @@ |
||||
#! /usr/bin/python |
||||
# |
||||
# 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. |
||||
|
||||
"""Tests for google.protobuf.pyext behavior.""" |
||||
|
||||
__author__ = 'anuraag@google.com (Anuraag Agrawal)' |
||||
|
||||
import os |
||||
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' |
||||
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2' |
||||
|
||||
# We must set the implementation version above before the google3 imports. |
||||
# pylint: disable=g-import-not-at-top |
||||
from google.apputils import basetest |
||||
from google.protobuf.internal import api_implementation |
||||
# Run all tests from the original module by putting them in our namespace. |
||||
# pylint: disable=wildcard-import |
||||
from google.protobuf.internal.descriptor_test import * |
||||
|
||||
|
||||
class ConfirmCppApi2Test(basetest.TestCase): |
||||
|
||||
def testImplementationSetting(self): |
||||
self.assertEqual('cpp', api_implementation.Type()) |
||||
self.assertEqual(2, api_implementation.Version()) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
basetest.main() |
@ -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. |
||||
|
||||
package google.protobuf.python.internal; |
||||
|
||||
|
||||
message DescriptorPoolTest1 { |
||||
extensions 1000 to max; |
||||
|
||||
enum NestedEnum { |
||||
ALPHA = 1; |
||||
BETA = 2; |
||||
} |
||||
|
||||
optional NestedEnum nested_enum = 1 [default = BETA]; |
||||
|
||||
message NestedMessage { |
||||
enum NestedEnum { |
||||
EPSILON = 5; |
||||
ZETA = 6; |
||||
} |
||||
optional NestedEnum nested_enum = 1 [default = ZETA]; |
||||
optional string nested_field = 2 [default = "beta"]; |
||||
optional DeepNestedMessage deep_nested_message = 3; |
||||
|
||||
message DeepNestedMessage { |
||||
enum NestedEnum { |
||||
ETA = 7; |
||||
THETA = 8; |
||||
} |
||||
optional NestedEnum nested_enum = 1 [default = ETA]; |
||||
optional string nested_field = 2 [default = "theta"]; |
||||
} |
||||
} |
||||
|
||||
optional NestedMessage nested_message = 2; |
||||
} |
||||
|
||||
message DescriptorPoolTest2 { |
||||
enum NestedEnum { |
||||
GAMMA = 3; |
||||
DELTA = 4; |
||||
} |
||||
|
||||
optional NestedEnum nested_enum = 1 [default = GAMMA]; |
||||
|
||||
message NestedMessage { |
||||
enum NestedEnum { |
||||
IOTA = 9; |
||||
KAPPA = 10; |
||||
} |
||||
optional NestedEnum nested_enum = 1 [default = IOTA]; |
||||
optional string nested_field = 2 [default = "delta"]; |
||||
optional DeepNestedMessage deep_nested_message = 3; |
||||
|
||||
message DeepNestedMessage { |
||||
enum NestedEnum { |
||||
LAMBDA = 11; |
||||
MU = 12; |
||||
} |
||||
optional NestedEnum nested_enum = 1 [default = MU]; |
||||
optional string nested_field = 2 [default = "lambda"]; |
||||
} |
||||
} |
||||
|
||||
optional NestedMessage nested_message = 2; |
||||
} |
@ -0,0 +1,70 @@ |
||||
// 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 google.protobuf.python.internal; |
||||
|
||||
import "google/protobuf/internal/descriptor_pool_test1.proto"; |
||||
|
||||
|
||||
message DescriptorPoolTest3 { |
||||
|
||||
extend DescriptorPoolTest1 { |
||||
optional DescriptorPoolTest3 descriptor_pool_test = 1001; |
||||
} |
||||
|
||||
enum NestedEnum { |
||||
NU = 13; |
||||
XI = 14; |
||||
} |
||||
|
||||
optional NestedEnum nested_enum = 1 [default = XI]; |
||||
|
||||
message NestedMessage { |
||||
enum NestedEnum { |
||||
OMICRON = 15; |
||||
PI = 16; |
||||
} |
||||
optional NestedEnum nested_enum = 1 [default = PI]; |
||||
optional string nested_field = 2 [default = "nu"]; |
||||
optional DeepNestedMessage deep_nested_message = 3; |
||||
|
||||
message DeepNestedMessage { |
||||
enum NestedEnum { |
||||
RHO = 17; |
||||
SIGMA = 18; |
||||
} |
||||
optional NestedEnum nested_enum = 1 [default = RHO]; |
||||
optional string nested_field = 2 [default = "sigma"]; |
||||
} |
||||
} |
||||
|
||||
optional NestedMessage nested_message = 2; |
||||
} |
||||
|
@ -0,0 +1,54 @@ |
||||
#! /usr/bin/python |
||||
# |
||||
# 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. |
||||
|
||||
"""Unittest for descriptor.py for the pure Python implementation.""" |
||||
|
||||
import os |
||||
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python' |
||||
|
||||
# We must set the implementation version above before the google3 imports. |
||||
# pylint: disable=g-import-not-at-top |
||||
from google.apputils import basetest |
||||
from google.protobuf.internal import api_implementation |
||||
# Run all tests from the original module by putting them in our namespace. |
||||
# pylint: disable=wildcard-import |
||||
from google.protobuf.internal.descriptor_test import * |
||||
|
||||
|
||||
class ConfirmPurePythonTest(basetest.TestCase): |
||||
|
||||
def testImplementationSetting(self): |
||||
self.assertEqual('python', api_implementation.Type()) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
basetest.main() |
@ -0,0 +1,56 @@ |
||||
#! /usr/bin/python |
||||
# |
||||
# 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. |
||||
|
||||
"""Tests for google.protobuf.message_factory.""" |
||||
|
||||
import os |
||||
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' |
||||
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2' |
||||
|
||||
# We must set the implementation version above before the google3 imports. |
||||
# pylint: disable=g-import-not-at-top |
||||
from google.apputils import basetest |
||||
from google.protobuf.internal import api_implementation |
||||
# Run all tests from the original module by putting them in our namespace. |
||||
# pylint: disable=wildcard-import |
||||
from google.protobuf.internal.message_factory_test import * |
||||
|
||||
|
||||
class ConfirmCppApi2Test(basetest.TestCase): |
||||
|
||||
def testImplementationSetting(self): |
||||
self.assertEqual('cpp', api_implementation.Type()) |
||||
self.assertEqual(2, api_implementation.Version()) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
basetest.main() |
@ -0,0 +1,54 @@ |
||||
#! /usr/bin/python |
||||
# |
||||
# 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. |
||||
|
||||
"""Tests for ..public.message_factory for the pure Python implementation.""" |
||||
|
||||
import os |
||||
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python' |
||||
|
||||
# We must set the implementation version above before the google3 imports. |
||||
# pylint: disable=g-import-not-at-top |
||||
from google.apputils import basetest |
||||
from google.protobuf.internal import api_implementation |
||||
# Run all tests from the original module by putting them in our namespace. |
||||
# pylint: disable=wildcard-import |
||||
from google.protobuf.internal.message_factory_test import * |
||||
|
||||
|
||||
class ConfirmPurePythonTest(basetest.TestCase): |
||||
|
||||
def testImplementationSetting(self): |
||||
self.assertEqual('python', api_implementation.Type()) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
basetest.main() |
@ -0,0 +1,50 @@ |
||||
// 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 google.protobuf.python.internal; |
||||
|
||||
message TestEnumValues { |
||||
enum NestedEnum { |
||||
ZERO = 0; |
||||
ONE = 1; |
||||
} |
||||
optional NestedEnum optional_nested_enum = 1; |
||||
repeated NestedEnum repeated_nested_enum = 2; |
||||
repeated NestedEnum packed_nested_enum = 3 [packed = true]; |
||||
} |
||||
|
||||
message TestMissingEnumValues { |
||||
enum NestedEnum { |
||||
TWO = 2; |
||||
} |
||||
optional NestedEnum optional_nested_enum = 1; |
||||
repeated NestedEnum repeated_nested_enum = 2; |
||||
repeated NestedEnum packed_nested_enum = 3 [packed = true]; |
||||
} |
@ -0,0 +1,120 @@ |
||||
#! /usr/bin/python |
||||
# |
||||
# 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. |
||||
|
||||
"""Tests for google.protobuf.symbol_database.""" |
||||
|
||||
from google.apputils import basetest |
||||
from google.protobuf import unittest_pb2 |
||||
from google.protobuf import symbol_database |
||||
|
||||
|
||||
class SymbolDatabaseTest(basetest.TestCase): |
||||
|
||||
def _Database(self): |
||||
db = symbol_database.SymbolDatabase() |
||||
# Register representative types from unittest_pb2. |
||||
db.RegisterFileDescriptor(unittest_pb2.DESCRIPTOR) |
||||
db.RegisterMessage(unittest_pb2.TestAllTypes) |
||||
db.RegisterMessage(unittest_pb2.TestAllTypes.NestedMessage) |
||||
db.RegisterMessage(unittest_pb2.TestAllTypes.OptionalGroup) |
||||
db.RegisterMessage(unittest_pb2.TestAllTypes.RepeatedGroup) |
||||
db.RegisterEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR) |
||||
db.RegisterEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR) |
||||
return db |
||||
|
||||
def testGetPrototype(self): |
||||
instance = self._Database().GetPrototype( |
||||
unittest_pb2.TestAllTypes.DESCRIPTOR) |
||||
self.assertTrue(instance is unittest_pb2.TestAllTypes) |
||||
|
||||
def testGetMessages(self): |
||||
messages = self._Database().GetMessages( |
||||
['google/protobuf/unittest.proto']) |
||||
self.assertTrue( |
||||
unittest_pb2.TestAllTypes is |
||||
messages['protobuf_unittest.TestAllTypes']) |
||||
|
||||
def testGetSymbol(self): |
||||
self.assertEquals( |
||||
unittest_pb2.TestAllTypes, self._Database().GetSymbol( |
||||
'protobuf_unittest.TestAllTypes')) |
||||
self.assertEquals( |
||||
unittest_pb2.TestAllTypes.NestedMessage, self._Database().GetSymbol( |
||||
'protobuf_unittest.TestAllTypes.NestedMessage')) |
||||
self.assertEquals( |
||||
unittest_pb2.TestAllTypes.OptionalGroup, self._Database().GetSymbol( |
||||
'protobuf_unittest.TestAllTypes.OptionalGroup')) |
||||
self.assertEquals( |
||||
unittest_pb2.TestAllTypes.RepeatedGroup, self._Database().GetSymbol( |
||||
'protobuf_unittest.TestAllTypes.RepeatedGroup')) |
||||
|
||||
def testEnums(self): |
||||
# Check registration of types in the pool. |
||||
self.assertEquals( |
||||
'protobuf_unittest.ForeignEnum', |
||||
self._Database().pool.FindEnumTypeByName( |
||||
'protobuf_unittest.ForeignEnum').full_name) |
||||
self.assertEquals( |
||||
'protobuf_unittest.TestAllTypes.NestedEnum', |
||||
self._Database().pool.FindEnumTypeByName( |
||||
'protobuf_unittest.TestAllTypes.NestedEnum').full_name) |
||||
|
||||
def testFindMessageTypeByName(self): |
||||
self.assertEquals( |
||||
'protobuf_unittest.TestAllTypes', |
||||
self._Database().pool.FindMessageTypeByName( |
||||
'protobuf_unittest.TestAllTypes').full_name) |
||||
self.assertEquals( |
||||
'protobuf_unittest.TestAllTypes.NestedMessage', |
||||
self._Database().pool.FindMessageTypeByName( |
||||
'protobuf_unittest.TestAllTypes.NestedMessage').full_name) |
||||
|
||||
def testFindFindContainingSymbol(self): |
||||
# Lookup based on either enum or message. |
||||
self.assertEquals( |
||||
'google/protobuf/unittest.proto', |
||||
self._Database().pool.FindFileContainingSymbol( |
||||
'protobuf_unittest.TestAllTypes.NestedEnum').name) |
||||
self.assertEquals( |
||||
'google/protobuf/unittest.proto', |
||||
self._Database().pool.FindFileContainingSymbol( |
||||
'protobuf_unittest.TestAllTypes').name) |
||||
|
||||
def testFindFileByName(self): |
||||
self.assertEquals( |
||||
'google/protobuf/unittest.proto', |
||||
self._Database().pool.FindFileByName( |
||||
'google/protobuf/unittest.proto').name) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
basetest.main() |
@ -0,0 +1,68 @@ |
||||
#! /usr/bin/python |
||||
# |
||||
# 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. |
||||
|
||||
"""Tests for google.protobuf.text_encoding.""" |
||||
|
||||
from google.apputils import basetest |
||||
from google.protobuf import text_encoding |
||||
|
||||
TEST_VALUES = [ |
||||
("foo\\rbar\\nbaz\\t", |
||||
"foo\\rbar\\nbaz\\t", |
||||
b"foo\rbar\nbaz\t"), |
||||
("\\'full of \\\"sound\\\" and \\\"fury\\\"\\'", |
||||
"\\'full of \\\"sound\\\" and \\\"fury\\\"\\'", |
||||
b"'full of \"sound\" and \"fury\"'"), |
||||
("signi\\\\fying\\\\ nothing\\\\", |
||||
"signi\\\\fying\\\\ nothing\\\\", |
||||
b"signi\\fying\\ nothing\\"), |
||||
("\\010\\t\\n\\013\\014\\r", |
||||
"\x08\\t\\n\x0b\x0c\\r", |
||||
b"\010\011\012\013\014\015")] |
||||
|
||||
|
||||
class TextEncodingTestCase(basetest.TestCase): |
||||
def testCEscape(self): |
||||
for escaped, escaped_utf8, unescaped in TEST_VALUES: |
||||
self.assertEquals(escaped, |
||||
text_encoding.CEscape(unescaped, as_utf8=False)) |
||||
self.assertEquals(escaped_utf8, |
||||
text_encoding.CEscape(unescaped, as_utf8=True)) |
||||
|
||||
def testCUnescape(self): |
||||
for escaped, escaped_utf8, unescaped in TEST_VALUES: |
||||
self.assertEquals(unescaped, text_encoding.CUnescape(escaped)) |
||||
self.assertEquals(unescaped, text_encoding.CUnescape(escaped_utf8)) |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
basetest.main() |
@ -0,0 +1,6 @@ |
||||
This is the 'v2' C++ implementation for python proto2. |
||||
|
||||
It is active when: |
||||
|
||||
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp |
||||
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2 |
@ -0,0 +1,61 @@ |
||||
# 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. |
||||
|
||||
"""Protocol message implementation hooks for C++ implementation. |
||||
|
||||
Contains helper functions used to create protocol message classes from |
||||
Descriptor objects at runtime backed by the protocol buffer C++ API. |
||||
""" |
||||
|
||||
__author__ = 'tibell@google.com (Johan Tibell)' |
||||
|
||||
from google.protobuf.pyext import _message |
||||
from google.protobuf import message |
||||
|
||||
|
||||
def NewMessage(bases, message_descriptor, dictionary): |
||||
"""Creates a new protocol message *class*.""" |
||||
new_bases = [] |
||||
for base in bases: |
||||
if base is message.Message: |
||||
# _message.Message must come before message.Message as it |
||||
# overrides methods in that class. |
||||
new_bases.append(_message.Message) |
||||
new_bases.append(base) |
||||
return tuple(new_bases) |
||||
|
||||
|
||||
def InitMessage(message_descriptor, cls): |
||||
"""Constructs a new message instance (called before instance's __init__).""" |
||||
|
||||
def SubInit(self, **kwargs): |
||||
super(cls, self).__init__(message_descriptor, **kwargs) |
||||
cls.__init__ = SubInit |
||||
cls.AddDescriptors(message_descriptor) |
@ -0,0 +1,357 @@ |
||||
// 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: petar@google.com (Petar Petrov)
|
||||
|
||||
#include <Python.h> |
||||
#include <string> |
||||
|
||||
#include <google/protobuf/descriptor.pb.h> |
||||
#include <google/protobuf/pyext/descriptor.h> |
||||
#include <google/protobuf/pyext/scoped_pyobject_ptr.h> |
||||
|
||||
#define C(str) const_cast<char*>(str) |
||||
|
||||
#if PY_MAJOR_VERSION >= 3 |
||||
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize |
||||
#define PyInt_FromLong PyLong_FromLong |
||||
#if PY_VERSION_HEX < 0x03030000 |
||||
#error "Python 3.0 - 3.2 are not supported." |
||||
#else |
||||
#define PyString_AsString(ob) \ |
||||
(PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AS_STRING(ob)) |
||||
#endif |
||||
#endif |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace python { |
||||
|
||||
|
||||
#ifndef PyVarObject_HEAD_INIT |
||||
#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, |
||||
#endif |
||||
#ifndef Py_TYPE |
||||
#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) |
||||
#endif |
||||
|
||||
|
||||
static google::protobuf::DescriptorPool* g_descriptor_pool = NULL; |
||||
|
||||
namespace cfield_descriptor { |
||||
|
||||
static void Dealloc(CFieldDescriptor* self) { |
||||
Py_CLEAR(self->descriptor_field); |
||||
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); |
||||
} |
||||
|
||||
static PyObject* GetFullName(CFieldDescriptor* self, void *closure) { |
||||
return PyString_FromStringAndSize( |
||||
self->descriptor->full_name().c_str(), |
||||
self->descriptor->full_name().size()); |
||||
} |
||||
|
||||
static PyObject* GetName(CFieldDescriptor *self, void *closure) { |
||||
return PyString_FromStringAndSize( |
||||
self->descriptor->name().c_str(), |
||||
self->descriptor->name().size()); |
||||
} |
||||
|
||||
static PyObject* GetCppType(CFieldDescriptor *self, void *closure) { |
||||
return PyInt_FromLong(self->descriptor->cpp_type()); |
||||
} |
||||
|
||||
static PyObject* GetLabel(CFieldDescriptor *self, void *closure) { |
||||
return PyInt_FromLong(self->descriptor->label()); |
||||
} |
||||
|
||||
static PyObject* GetID(CFieldDescriptor *self, void *closure) { |
||||
return PyLong_FromVoidPtr(self); |
||||
} |
||||
|
||||
static PyGetSetDef Getters[] = { |
||||
{ C("full_name"), (getter)GetFullName, NULL, "Full name", NULL}, |
||||
{ C("name"), (getter)GetName, NULL, "last name", NULL}, |
||||
{ C("cpp_type"), (getter)GetCppType, NULL, "C++ Type", NULL}, |
||||
{ C("label"), (getter)GetLabel, NULL, "Label", NULL}, |
||||
{ C("id"), (getter)GetID, NULL, "ID", NULL}, |
||||
{NULL} |
||||
}; |
||||
|
||||
} // namespace cfield_descriptor
|
||||
|
||||
PyTypeObject CFieldDescriptor_Type = { |
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0) |
||||
C("google.protobuf.internal." |
||||
"_net_proto2___python." |
||||
"CFieldDescriptor"), // tp_name
|
||||
sizeof(CFieldDescriptor), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor)cfield_descriptor::Dealloc, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
C("A Field Descriptor"), // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
0, // tp_methods
|
||||
0, // tp_members
|
||||
cfield_descriptor::Getters, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
PyType_GenericAlloc, // tp_alloc
|
||||
PyType_GenericNew, // tp_new
|
||||
PyObject_Del, // tp_free
|
||||
}; |
||||
|
||||
namespace cdescriptor_pool { |
||||
|
||||
static void Dealloc(CDescriptorPool* self) { |
||||
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); |
||||
} |
||||
|
||||
static PyObject* NewCDescriptor( |
||||
const google::protobuf::FieldDescriptor* field_descriptor) { |
||||
CFieldDescriptor* cfield_descriptor = PyObject_New( |
||||
CFieldDescriptor, &CFieldDescriptor_Type); |
||||
if (cfield_descriptor == NULL) { |
||||
return NULL; |
||||
} |
||||
cfield_descriptor->descriptor = field_descriptor; |
||||
cfield_descriptor->descriptor_field = NULL; |
||||
|
||||
return reinterpret_cast<PyObject*>(cfield_descriptor); |
||||
} |
||||
|
||||
PyObject* FindFieldByName(CDescriptorPool* self, PyObject* name) { |
||||
const char* full_field_name = PyString_AsString(name); |
||||
if (full_field_name == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
const google::protobuf::FieldDescriptor* field_descriptor = NULL; |
||||
|
||||
field_descriptor = self->pool->FindFieldByName(full_field_name); |
||||
|
||||
if (field_descriptor == NULL) { |
||||
PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s", |
||||
full_field_name); |
||||
return NULL; |
||||
} |
||||
|
||||
return NewCDescriptor(field_descriptor); |
||||
} |
||||
|
||||
PyObject* FindExtensionByName(CDescriptorPool* self, PyObject* arg) { |
||||
const char* full_field_name = PyString_AsString(arg); |
||||
if (full_field_name == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
const google::protobuf::FieldDescriptor* field_descriptor = |
||||
self->pool->FindExtensionByName(full_field_name); |
||||
if (field_descriptor == NULL) { |
||||
PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s", |
||||
full_field_name); |
||||
return NULL; |
||||
} |
||||
|
||||
return NewCDescriptor(field_descriptor); |
||||
} |
||||
|
||||
static PyMethodDef Methods[] = { |
||||
{ C("FindFieldByName"), |
||||
(PyCFunction)FindFieldByName, |
||||
METH_O, |
||||
C("Searches for a field descriptor by full name.") }, |
||||
{ C("FindExtensionByName"), |
||||
(PyCFunction)FindExtensionByName, |
||||
METH_O, |
||||
C("Searches for extension descriptor by full name.") }, |
||||
{NULL} |
||||
}; |
||||
|
||||
} // namespace cdescriptor_pool
|
||||
|
||||
PyTypeObject CDescriptorPool_Type = { |
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0) |
||||
C("google.protobuf.internal." |
||||
"_net_proto2___python." |
||||
"CFieldDescriptor"), // tp_name
|
||||
sizeof(CDescriptorPool), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor)cdescriptor_pool::Dealloc, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
C("A Descriptor Pool"), // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
cdescriptor_pool::Methods, // tp_methods
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
PyType_GenericAlloc, // tp_alloc
|
||||
PyType_GenericNew, // tp_new
|
||||
PyObject_Del, // tp_free
|
||||
}; |
||||
|
||||
google::protobuf::DescriptorPool* GetDescriptorPool() { |
||||
if (g_descriptor_pool == NULL) { |
||||
g_descriptor_pool = new google::protobuf::DescriptorPool( |
||||
google::protobuf::DescriptorPool::generated_pool()); |
||||
} |
||||
return g_descriptor_pool; |
||||
} |
||||
|
||||
PyObject* Python_NewCDescriptorPool(PyObject* ignored, PyObject* args) { |
||||
CDescriptorPool* cdescriptor_pool = PyObject_New( |
||||
CDescriptorPool, &CDescriptorPool_Type); |
||||
if (cdescriptor_pool == NULL) { |
||||
return NULL; |
||||
} |
||||
cdescriptor_pool->pool = GetDescriptorPool(); |
||||
return reinterpret_cast<PyObject*>(cdescriptor_pool); |
||||
} |
||||
|
||||
|
||||
// Collects errors that occur during proto file building to allow them to be
|
||||
// propagated in the python exception instead of only living in ERROR logs.
|
||||
class BuildFileErrorCollector : public google::protobuf::DescriptorPool::ErrorCollector { |
||||
public: |
||||
BuildFileErrorCollector() : error_message(""), had_errors(false) {} |
||||
|
||||
void AddError(const string& filename, const string& element_name, |
||||
const Message* descriptor, ErrorLocation location, |
||||
const string& message) { |
||||
// Replicates the logging behavior that happens in the C++ implementation
|
||||
// when an error collector is not passed in.
|
||||
if (!had_errors) { |
||||
error_message += |
||||
("Invalid proto descriptor for file \"" + filename + "\":\n"); |
||||
} |
||||
// As this only happens on failure and will result in the program not
|
||||
// running at all, no effort is made to optimize this string manipulation.
|
||||
error_message += (" " + element_name + ": " + message + "\n"); |
||||
} |
||||
|
||||
string error_message; |
||||
bool had_errors; |
||||
}; |
||||
|
||||
PyObject* Python_BuildFile(PyObject* ignored, PyObject* arg) { |
||||
char* message_type; |
||||
Py_ssize_t message_len; |
||||
|
||||
if (PyBytes_AsStringAndSize(arg, &message_type, &message_len) < 0) { |
||||
return NULL; |
||||
} |
||||
|
||||
google::protobuf::FileDescriptorProto file_proto; |
||||
if (!file_proto.ParseFromArray(message_type, message_len)) { |
||||
PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!"); |
||||
return NULL; |
||||
} |
||||
|
||||
if (google::protobuf::DescriptorPool::generated_pool()->FindFileByName( |
||||
file_proto.name()) != NULL) { |
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
BuildFileErrorCollector error_collector; |
||||
const google::protobuf::FileDescriptor* descriptor = |
||||
GetDescriptorPool()->BuildFileCollectingErrors(file_proto, |
||||
&error_collector); |
||||
if (descriptor == NULL) { |
||||
PyErr_Format(PyExc_TypeError, |
||||
"Couldn't build proto file into descriptor pool!\n%s", |
||||
error_collector.error_message.c_str()); |
||||
return NULL; |
||||
} |
||||
|
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
bool InitDescriptor() { |
||||
CFieldDescriptor_Type.tp_new = PyType_GenericNew; |
||||
if (PyType_Ready(&CFieldDescriptor_Type) < 0) |
||||
return false; |
||||
|
||||
CDescriptorPool_Type.tp_new = PyType_GenericNew; |
||||
if (PyType_Ready(&CDescriptorPool_Type) < 0) |
||||
return false; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -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: petar@google.com (Petar Petrov)
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__ |
||||
#define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__ |
||||
|
||||
#include <Python.h> |
||||
#include <structmember.h> |
||||
|
||||
#include <google/protobuf/descriptor.h> |
||||
|
||||
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) |
||||
typedef int Py_ssize_t; |
||||
#define PY_SSIZE_T_MAX INT_MAX |
||||
#define PY_SSIZE_T_MIN INT_MIN |
||||
#endif |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace python { |
||||
|
||||
typedef struct CFieldDescriptor { |
||||
PyObject_HEAD |
||||
|
||||
// The proto2 descriptor that this object represents.
|
||||
const google::protobuf::FieldDescriptor* descriptor; |
||||
|
||||
// Reference to the original field object in the Python DESCRIPTOR.
|
||||
PyObject* descriptor_field; |
||||
} CFieldDescriptor; |
||||
|
||||
typedef struct { |
||||
PyObject_HEAD |
||||
|
||||
const google::protobuf::DescriptorPool* pool; |
||||
} CDescriptorPool; |
||||
|
||||
extern PyTypeObject CFieldDescriptor_Type; |
||||
|
||||
extern PyTypeObject CDescriptorPool_Type; |
||||
|
||||
namespace cdescriptor_pool { |
||||
|
||||
// Looks up a field by name. Returns a CDescriptor corresponding to
|
||||
// the field on success, or NULL on failure.
|
||||
//
|
||||
// Returns a new reference.
|
||||
PyObject* FindFieldByName(CDescriptorPool* self, PyObject* name); |
||||
|
||||
// Looks up an extension by name. Returns a CDescriptor corresponding
|
||||
// to the field on success, or NULL on failure.
|
||||
//
|
||||
// Returns a new reference.
|
||||
PyObject* FindExtensionByName(CDescriptorPool* self, PyObject* arg); |
||||
|
||||
} // namespace cdescriptor_pool
|
||||
|
||||
PyObject* Python_NewCDescriptorPool(PyObject* ignored, PyObject* args); |
||||
PyObject* Python_BuildFile(PyObject* ignored, PyObject* args); |
||||
bool InitDescriptor(); |
||||
google::protobuf::DescriptorPool* GetDescriptorPool(); |
||||
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__
|
@ -0,0 +1,338 @@ |
||||
// 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: anuraag@google.com (Anuraag Agrawal)
|
||||
// Author: tibell@google.com (Johan Tibell)
|
||||
|
||||
#include <google/protobuf/pyext/extension_dict.h> |
||||
|
||||
#include <google/protobuf/stubs/common.h> |
||||
#include <google/protobuf/descriptor.h> |
||||
#include <google/protobuf/dynamic_message.h> |
||||
#include <google/protobuf/message.h> |
||||
#include <google/protobuf/pyext/descriptor.h> |
||||
#include <google/protobuf/pyext/message.h> |
||||
#include <google/protobuf/pyext/repeated_composite_container.h> |
||||
#include <google/protobuf/pyext/repeated_scalar_container.h> |
||||
#include <google/protobuf/pyext/scoped_pyobject_ptr.h> |
||||
#include <google/protobuf/stubs/shared_ptr.h> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace python { |
||||
|
||||
extern google::protobuf::DynamicMessageFactory* global_message_factory; |
||||
|
||||
namespace extension_dict { |
||||
|
||||
// TODO(tibell): Always use self->message for clarity, just like in
|
||||
// RepeatedCompositeContainer.
|
||||
static google::protobuf::Message* GetMessage(ExtensionDict* self) { |
||||
if (self->parent != NULL) { |
||||
return self->parent->message; |
||||
} else { |
||||
return self->message; |
||||
} |
||||
} |
||||
|
||||
CFieldDescriptor* InternalGetCDescriptorFromExtension(PyObject* extension) { |
||||
PyObject* cdescriptor = PyObject_GetAttrString(extension, "_cdescriptor"); |
||||
if (cdescriptor == NULL) { |
||||
PyErr_SetString(PyExc_KeyError, "Unregistered extension."); |
||||
return NULL; |
||||
} |
||||
if (!PyObject_TypeCheck(cdescriptor, &CFieldDescriptor_Type)) { |
||||
PyErr_SetString(PyExc_TypeError, "Not a CFieldDescriptor"); |
||||
Py_DECREF(cdescriptor); |
||||
return NULL; |
||||
} |
||||
CFieldDescriptor* descriptor = |
||||
reinterpret_cast<CFieldDescriptor*>(cdescriptor); |
||||
return descriptor; |
||||
} |
||||
|
||||
PyObject* len(ExtensionDict* self) { |
||||
#if PY_MAJOR_VERSION >= 3 |
||||
return PyLong_FromLong(PyDict_Size(self->values)); |
||||
#else |
||||
return PyInt_FromLong(PyDict_Size(self->values)); |
||||
#endif |
||||
} |
||||
|
||||
// TODO(tibell): Use VisitCompositeField.
|
||||
int ReleaseExtension(ExtensionDict* self, |
||||
PyObject* extension, |
||||
const google::protobuf::FieldDescriptor* descriptor) { |
||||
if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { |
||||
if (descriptor->cpp_type() == |
||||
google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { |
||||
if (repeated_composite_container::Release( |
||||
reinterpret_cast<RepeatedCompositeContainer*>( |
||||
extension)) < 0) { |
||||
return -1; |
||||
} |
||||
} else { |
||||
if (repeated_scalar_container::Release( |
||||
reinterpret_cast<RepeatedScalarContainer*>( |
||||
extension)) < 0) { |
||||
return -1; |
||||
} |
||||
} |
||||
} else if (descriptor->cpp_type() == |
||||
google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { |
||||
if (cmessage::ReleaseSubMessage( |
||||
GetMessage(self), descriptor, |
||||
reinterpret_cast<CMessage*>(extension)) < 0) { |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
PyObject* subscript(ExtensionDict* self, PyObject* key) { |
||||
CFieldDescriptor* cdescriptor = InternalGetCDescriptorFromExtension( |
||||
key); |
||||
if (cdescriptor == NULL) { |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr py_cdescriptor(reinterpret_cast<PyObject*>(cdescriptor)); |
||||
const google::protobuf::FieldDescriptor* descriptor = cdescriptor->descriptor; |
||||
if (descriptor == NULL) { |
||||
return NULL; |
||||
} |
||||
if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && |
||||
descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { |
||||
return cmessage::InternalGetScalar(self->parent, descriptor); |
||||
} |
||||
|
||||
PyObject* value = PyDict_GetItem(self->values, key); |
||||
if (value != NULL) { |
||||
Py_INCREF(value); |
||||
return value; |
||||
} |
||||
|
||||
if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && |
||||
descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
||||
PyObject* sub_message = cmessage::InternalGetSubMessage( |
||||
self->parent, cdescriptor); |
||||
if (sub_message == NULL) { |
||||
return NULL; |
||||
} |
||||
PyDict_SetItem(self->values, key, sub_message); |
||||
return sub_message; |
||||
} |
||||
|
||||
if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { |
||||
if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
||||
// COPIED
|
||||
PyObject* py_container = PyObject_CallObject( |
||||
reinterpret_cast<PyObject*>(&RepeatedCompositeContainer_Type), |
||||
NULL); |
||||
if (py_container == NULL) { |
||||
return NULL; |
||||
} |
||||
RepeatedCompositeContainer* container = |
||||
reinterpret_cast<RepeatedCompositeContainer*>(py_container); |
||||
PyObject* field = cdescriptor->descriptor_field; |
||||
PyObject* message_type = PyObject_GetAttrString(field, "message_type"); |
||||
PyObject* concrete_class = PyObject_GetAttrString(message_type, |
||||
"_concrete_class"); |
||||
container->owner = self->owner; |
||||
container->parent = self->parent; |
||||
container->message = self->parent->message; |
||||
container->parent_field = cdescriptor; |
||||
container->subclass_init = concrete_class; |
||||
Py_DECREF(message_type); |
||||
PyDict_SetItem(self->values, key, py_container); |
||||
return py_container; |
||||
} else { |
||||
// COPIED
|
||||
ScopedPyObjectPtr init_args(PyTuple_Pack(2, self->parent, cdescriptor)); |
||||
PyObject* py_container = PyObject_CallObject( |
||||
reinterpret_cast<PyObject*>(&RepeatedScalarContainer_Type), |
||||
init_args); |
||||
if (py_container == NULL) { |
||||
return NULL; |
||||
} |
||||
PyDict_SetItem(self->values, key, py_container); |
||||
return py_container; |
||||
} |
||||
} |
||||
PyErr_SetString(PyExc_ValueError, "control reached unexpected line"); |
||||
return NULL; |
||||
} |
||||
|
||||
int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) { |
||||
CFieldDescriptor* cdescriptor = InternalGetCDescriptorFromExtension( |
||||
key); |
||||
if (cdescriptor == NULL) { |
||||
return -1; |
||||
} |
||||
ScopedPyObjectPtr py_cdescriptor(reinterpret_cast<PyObject*>(cdescriptor)); |
||||
const google::protobuf::FieldDescriptor* descriptor = cdescriptor->descriptor; |
||||
if (descriptor->label() != FieldDescriptor::LABEL_OPTIONAL || |
||||
descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
||||
PyErr_SetString(PyExc_TypeError, "Extension is repeated and/or composite " |
||||
"type"); |
||||
return -1; |
||||
} |
||||
cmessage::AssureWritable(self->parent); |
||||
if (cmessage::InternalSetScalar(self->parent, descriptor, value) < 0) { |
||||
return -1; |
||||
} |
||||
// TODO(tibell): We shouldn't write scalars to the cache.
|
||||
PyDict_SetItem(self->values, key, value); |
||||
return 0; |
||||
} |
||||
|
||||
PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) { |
||||
CFieldDescriptor* cdescriptor = InternalGetCDescriptorFromExtension( |
||||
extension); |
||||
if (cdescriptor == NULL) { |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr py_cdescriptor(reinterpret_cast<PyObject*>(cdescriptor)); |
||||
PyObject* value = PyDict_GetItem(self->values, extension); |
||||
if (value != NULL) { |
||||
if (ReleaseExtension(self, value, cdescriptor->descriptor) < 0) { |
||||
return NULL; |
||||
} |
||||
} |
||||
if (cmessage::ClearFieldByDescriptor(self->parent, |
||||
cdescriptor->descriptor) == NULL) { |
||||
return NULL; |
||||
} |
||||
if (PyDict_DelItem(self->values, extension) < 0) { |
||||
PyErr_Clear(); |
||||
} |
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
PyObject* HasExtension(ExtensionDict* self, PyObject* extension) { |
||||
CFieldDescriptor* cdescriptor = InternalGetCDescriptorFromExtension( |
||||
extension); |
||||
if (cdescriptor == NULL) { |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr py_cdescriptor(reinterpret_cast<PyObject*>(cdescriptor)); |
||||
PyObject* result = cmessage::HasFieldByDescriptor( |
||||
self->parent, cdescriptor->descriptor); |
||||
return result; |
||||
} |
||||
|
||||
PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* name) { |
||||
ScopedPyObjectPtr extensions_by_name(PyObject_GetAttrString( |
||||
reinterpret_cast<PyObject*>(self->parent), "_extensions_by_name")); |
||||
if (extensions_by_name == NULL) { |
||||
return NULL; |
||||
} |
||||
PyObject* result = PyDict_GetItem(extensions_by_name, name); |
||||
if (result == NULL) { |
||||
Py_RETURN_NONE; |
||||
} else { |
||||
Py_INCREF(result); |
||||
return result; |
||||
} |
||||
} |
||||
|
||||
int init(ExtensionDict* self, PyObject* args, PyObject* kwargs) { |
||||
self->parent = NULL; |
||||
self->message = NULL; |
||||
self->values = PyDict_New(); |
||||
return 0; |
||||
} |
||||
|
||||
void dealloc(ExtensionDict* self) { |
||||
Py_CLEAR(self->values); |
||||
self->owner.reset(); |
||||
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); |
||||
} |
||||
|
||||
static PyMappingMethods MpMethods = { |
||||
(lenfunc)len, /* mp_length */ |
||||
(binaryfunc)subscript, /* mp_subscript */ |
||||
(objobjargproc)ass_subscript,/* mp_ass_subscript */ |
||||
}; |
||||
|
||||
#define EDMETHOD(name, args, doc) { #name, (PyCFunction)name, args, doc } |
||||
static PyMethodDef Methods[] = { |
||||
EDMETHOD(ClearExtension, METH_O, "Clears an extension from the object."), |
||||
EDMETHOD(HasExtension, METH_O, "Checks if the object has an extension."), |
||||
EDMETHOD(_FindExtensionByName, METH_O, |
||||
"Finds an extension by name."), |
||||
{ NULL, NULL } |
||||
}; |
||||
|
||||
} // namespace extension_dict
|
||||
|
||||
PyTypeObject ExtensionDict_Type = { |
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0) |
||||
"google.protobuf.internal." |
||||
"cpp._message.ExtensionDict", // tp_name
|
||||
sizeof(ExtensionDict), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor)extension_dict::dealloc, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
&extension_dict::MpMethods, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
"An extension dict", // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
extension_dict::Methods, // tp_methods
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
(initproc)extension_dict::init, // tp_init
|
||||
}; |
||||
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,123 @@ |
||||
// 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: anuraag@google.com (Anuraag Agrawal)
|
||||
// Author: tibell@google.com (Johan Tibell)
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_EXTENSION_DICT_H__ |
||||
#define GOOGLE_PROTOBUF_PYTHON_CPP_EXTENSION_DICT_H__ |
||||
|
||||
#include <Python.h> |
||||
|
||||
#include <memory> |
||||
#ifndef _SHARED_PTR_H |
||||
#include <google/protobuf/stubs/shared_ptr.h> |
||||
#endif |
||||
|
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
|
||||
class Message; |
||||
class FieldDescriptor; |
||||
|
||||
using internal::shared_ptr; |
||||
|
||||
namespace python { |
||||
|
||||
struct CMessage; |
||||
struct CFieldDescriptor; |
||||
|
||||
typedef struct ExtensionDict { |
||||
PyObject_HEAD; |
||||
shared_ptr<Message> owner; |
||||
CMessage* parent; |
||||
Message* message; |
||||
PyObject* values; |
||||
} ExtensionDict; |
||||
|
||||
extern PyTypeObject ExtensionDict_Type; |
||||
|
||||
namespace extension_dict { |
||||
|
||||
// Gets the _cdescriptor reference to a CFieldDescriptor object given a
|
||||
// python descriptor object.
|
||||
//
|
||||
// Returns a new reference.
|
||||
CFieldDescriptor* InternalGetCDescriptorFromExtension(PyObject* extension); |
||||
|
||||
// Gets the number of extension values in this ExtensionDict as a python object.
|
||||
//
|
||||
// Returns a new reference.
|
||||
PyObject* len(ExtensionDict* self); |
||||
|
||||
// Releases extensions referenced outside this dictionary to keep outside
|
||||
// references alive.
|
||||
//
|
||||
// Returns 0 on success, -1 on failure.
|
||||
int ReleaseExtension(ExtensionDict* self, |
||||
PyObject* extension, |
||||
const google::protobuf::FieldDescriptor* descriptor); |
||||
|
||||
// Gets an extension from the dict for the given extension descriptor.
|
||||
//
|
||||
// Returns a new reference.
|
||||
PyObject* subscript(ExtensionDict* self, PyObject* key); |
||||
|
||||
// Assigns a value to an extension in the dict. Can only be used for singular
|
||||
// simple types.
|
||||
//
|
||||
// Returns 0 on success, -1 on failure.
|
||||
int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value); |
||||
|
||||
// Clears an extension from the dict. Will release the extension if there
|
||||
// is still an external reference left to it.
|
||||
//
|
||||
// Returns None on success.
|
||||
PyObject* ClearExtension(ExtensionDict* self, |
||||
PyObject* extension); |
||||
|
||||
// Checks if the dict has an extension.
|
||||
//
|
||||
// Returns a new python boolean reference.
|
||||
PyObject* HasExtension(ExtensionDict* self, PyObject* extension); |
||||
|
||||
// Gets an extension from the dict given the extension name as opposed to
|
||||
// descriptor.
|
||||
//
|
||||
// Returns a new reference.
|
||||
PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* name); |
||||
|
||||
} // namespace extension_dict
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_PYTHON_CPP_EXTENSION_DICT_H__
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,305 @@ |
||||
// 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: anuraag@google.com (Anuraag Agrawal)
|
||||
// Author: tibell@google.com (Johan Tibell)
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__ |
||||
#define GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__ |
||||
|
||||
#include <Python.h> |
||||
|
||||
#include <memory> |
||||
#ifndef _SHARED_PTR_H |
||||
#include <google/protobuf/stubs/shared_ptr.h> |
||||
#endif |
||||
#include <string> |
||||
|
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
|
||||
class Message; |
||||
class Reflection; |
||||
class FieldDescriptor; |
||||
|
||||
using internal::shared_ptr; |
||||
|
||||
namespace python { |
||||
|
||||
struct CFieldDescriptor; |
||||
struct ExtensionDict; |
||||
|
||||
typedef struct CMessage { |
||||
PyObject_HEAD; |
||||
|
||||
// This is the top-level C++ Message object that owns the whole
|
||||
// proto tree. Every Python CMessage holds a reference to it in
|
||||
// order to keep it alive as long as there's a Python object that
|
||||
// references any part of the tree.
|
||||
shared_ptr<Message> owner; |
||||
|
||||
// Weak reference to a parent CMessage object. This is NULL for any top-level
|
||||
// message and is set for any child message (i.e. a child submessage or a
|
||||
// part of a repeated composite field).
|
||||
//
|
||||
// Used to make sure all ancestors are also mutable when first modifying
|
||||
// a child submessage (in other words, turning a default message instance
|
||||
// into a mutable one).
|
||||
//
|
||||
// If a submessage is released (becomes a new top-level message), this field
|
||||
// MUST be set to NULL. The parent may get deallocated and further attempts
|
||||
// to use this pointer will result in a crash.
|
||||
struct CMessage* parent; |
||||
|
||||
// Weak reference to the parent's descriptor that describes this submessage.
|
||||
// Used together with the parent's message when making a default message
|
||||
// instance mutable.
|
||||
// TODO(anuraag): With a bit of work on the Python/C++ layer, it should be
|
||||
// possible to make this a direct pointer to a C++ FieldDescriptor, this would
|
||||
// be easier if this implementation replaces upstream.
|
||||
CFieldDescriptor* parent_field; |
||||
|
||||
// Pointer to the C++ Message object for this CMessage. The
|
||||
// CMessage does not own this pointer.
|
||||
Message* message; |
||||
|
||||
// Indicates this submessage is pointing to a default instance of a message.
|
||||
// Submessages are always first created as read only messages and are then
|
||||
// made writable, at which point this field is set to false.
|
||||
bool read_only; |
||||
|
||||
// A reference to a Python dictionary containing CMessage,
|
||||
// RepeatedCompositeContainer, and RepeatedScalarContainer
|
||||
// objects. Used as a cache to make sure we don't have to make a
|
||||
// Python wrapper for the C++ Message objects on every access, or
|
||||
// deal with the synchronization nightmare that could create.
|
||||
PyObject* composite_fields; |
||||
|
||||
// A reference to the dictionary containing the message's extensions.
|
||||
// Similar to composite_fields, acting as a cache, but also contains the
|
||||
// required extension dict logic.
|
||||
ExtensionDict* extensions; |
||||
} CMessage; |
||||
|
||||
extern PyTypeObject CMessage_Type; |
||||
|
||||
namespace cmessage { |
||||
|
||||
// Create a new empty message that can be populated by the parent.
|
||||
PyObject* NewEmpty(PyObject* type); |
||||
|
||||
// Release a submessage from its proto tree, making it a new top-level messgae.
|
||||
// A new message will be created if this is a read-only default instance.
|
||||
//
|
||||
// Corresponds to reflection api method ReleaseMessage.
|
||||
int ReleaseSubMessage(google::protobuf::Message* message, |
||||
const google::protobuf::FieldDescriptor* field_descriptor, |
||||
CMessage* child_cmessage); |
||||
|
||||
// Initializes a new CMessage instance for a submessage. Only called once per
|
||||
// submessage as the result is cached in composite_fields.
|
||||
//
|
||||
// Corresponds to reflection api method GetMessage.
|
||||
PyObject* InternalGetSubMessage(CMessage* self, |
||||
CFieldDescriptor* cfield_descriptor); |
||||
|
||||
// Deletes a range of C++ submessages in a repeated field (following a
|
||||
// removal in a RepeatedCompositeContainer).
|
||||
//
|
||||
// Releases messages to the provided cmessage_list if it is not NULL rather
|
||||
// than just removing them from the underlying proto. This cmessage_list must
|
||||
// have a CMessage for each underlying submessage. The CMessages refered to
|
||||
// by slice will be removed from cmessage_list by this function.
|
||||
//
|
||||
// Corresponds to reflection api method RemoveLast.
|
||||
int InternalDeleteRepeatedField(google::protobuf::Message* message, |
||||
const google::protobuf::FieldDescriptor* field_descriptor, |
||||
PyObject* slice, PyObject* cmessage_list); |
||||
|
||||
// Sets the specified scalar value to the message.
|
||||
int InternalSetScalar(CMessage* self, |
||||
const google::protobuf::FieldDescriptor* field_descriptor, |
||||
PyObject* value); |
||||
|
||||
// Retrieves the specified scalar value from the message.
|
||||
//
|
||||
// Returns a new python reference.
|
||||
PyObject* InternalGetScalar(CMessage* self, |
||||
const google::protobuf::FieldDescriptor* field_descriptor); |
||||
|
||||
// Clears the message, removing all contained data. Extension dictionary and
|
||||
// submessages are released first if there are remaining external references.
|
||||
//
|
||||
// Corresponds to message api method Clear.
|
||||
PyObject* Clear(CMessage* self); |
||||
|
||||
// Clears the data described by the given descriptor. Used to clear extensions
|
||||
// (which don't have names). Extension release is handled by ExtensionDict
|
||||
// class, not this function.
|
||||
// TODO(anuraag): Try to make this discrepancy in release semantics with
|
||||
// ClearField less confusing.
|
||||
//
|
||||
// Corresponds to reflection api method ClearField.
|
||||
PyObject* ClearFieldByDescriptor( |
||||
CMessage* self, |
||||
const google::protobuf::FieldDescriptor* descriptor); |
||||
|
||||
// Clears the data for the given field name. The message is released if there
|
||||
// are any external references.
|
||||
//
|
||||
// Corresponds to reflection api method ClearField.
|
||||
PyObject* ClearField(CMessage* self, PyObject* arg); |
||||
|
||||
// Checks if the message has the field described by the descriptor. Used for
|
||||
// extensions (which have no name).
|
||||
//
|
||||
// Corresponds to reflection api method HasField
|
||||
PyObject* HasFieldByDescriptor( |
||||
CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor); |
||||
|
||||
// Checks if the message has the named field.
|
||||
//
|
||||
// Corresponds to reflection api method HasField.
|
||||
PyObject* HasField(CMessage* self, PyObject* arg); |
||||
|
||||
// Initializes constants/enum values on a message. This is called by
|
||||
// RepeatedCompositeContainer and ExtensionDict after calling the constructor.
|
||||
// TODO(anuraag): Make it always called from within the constructor since it can
|
||||
int InitAttributes(CMessage* self, PyObject* descriptor, PyObject* kwargs); |
||||
|
||||
PyObject* MergeFrom(CMessage* self, PyObject* arg); |
||||
|
||||
// Retrieves an attribute named 'name' from CMessage 'self'. Returns
|
||||
// the attribute value on success, or NULL on failure.
|
||||
//
|
||||
// Returns a new reference.
|
||||
PyObject* GetAttr(CMessage* self, PyObject* name); |
||||
|
||||
// Set the value of the attribute named 'name', for CMessage 'self',
|
||||
// to the value 'value'. Returns -1 on failure.
|
||||
int SetAttr(CMessage* self, PyObject* name, PyObject* value); |
||||
|
||||
PyObject* FindInitializationErrors(CMessage* self); |
||||
|
||||
// Set the owner field of self and any children of self, recursively.
|
||||
// Used when self is being released and thus has a new owner (the
|
||||
// released Message.)
|
||||
int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner); |
||||
|
||||
int AssureWritable(CMessage* self); |
||||
|
||||
} // namespace cmessage
|
||||
|
||||
/* Is 64bit */ |
||||
#define IS_64BIT (SIZEOF_LONG == 8) |
||||
|
||||
#define FIELD_BELONGS_TO_MESSAGE(field_descriptor, message) \ |
||||
((message)->GetDescriptor() == (field_descriptor)->containing_type()) |
||||
|
||||
#define FIELD_IS_REPEATED(field_descriptor) \ |
||||
((field_descriptor)->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) |
||||
|
||||
#define GOOGLE_CHECK_GET_INT32(arg, value, err) \ |
||||
int32 value; \
|
||||
if (!CheckAndGetInteger(arg, &value, kint32min_py, kint32max_py)) { \
|
||||
return err; \
|
||||
} |
||||
|
||||
#define GOOGLE_CHECK_GET_INT64(arg, value, err) \ |
||||
int64 value; \
|
||||
if (!CheckAndGetInteger(arg, &value, kint64min_py, kint64max_py)) { \
|
||||
return err; \
|
||||
} |
||||
|
||||
#define GOOGLE_CHECK_GET_UINT32(arg, value, err) \ |
||||
uint32 value; \
|
||||
if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint32max_py)) { \
|
||||
return err; \
|
||||
} |
||||
|
||||
#define GOOGLE_CHECK_GET_UINT64(arg, value, err) \ |
||||
uint64 value; \
|
||||
if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint64max_py)) { \
|
||||
return err; \
|
||||
} |
||||
|
||||
#define GOOGLE_CHECK_GET_FLOAT(arg, value, err) \ |
||||
float value; \
|
||||
if (!CheckAndGetFloat(arg, &value)) { \
|
||||
return err; \
|
||||
} \
|
||||
|
||||
#define GOOGLE_CHECK_GET_DOUBLE(arg, value, err) \ |
||||
double value; \
|
||||
if (!CheckAndGetDouble(arg, &value)) { \
|
||||
return err; \
|
||||
} |
||||
|
||||
#define GOOGLE_CHECK_GET_BOOL(arg, value, err) \ |
||||
bool value; \
|
||||
if (!CheckAndGetBool(arg, &value)) { \
|
||||
return err; \
|
||||
} |
||||
|
||||
|
||||
extern PyObject* kPythonZero; |
||||
extern PyObject* kint32min_py; |
||||
extern PyObject* kint32max_py; |
||||
extern PyObject* kuint32max_py; |
||||
extern PyObject* kint64min_py; |
||||
extern PyObject* kint64max_py; |
||||
extern PyObject* kuint64max_py; |
||||
|
||||
#define C(str) const_cast<char*>(str) |
||||
|
||||
void FormatTypeError(PyObject* arg, char* expected_types); |
||||
template<class T> |
||||
bool CheckAndGetInteger( |
||||
PyObject* arg, T* value, PyObject* min, PyObject* max); |
||||
bool CheckAndGetDouble(PyObject* arg, double* value); |
||||
bool CheckAndGetFloat(PyObject* arg, float* value); |
||||
bool CheckAndGetBool(PyObject* arg, bool* value); |
||||
bool CheckAndSetString( |
||||
PyObject* arg, google::protobuf::Message* message, |
||||
const google::protobuf::FieldDescriptor* descriptor, |
||||
const google::protobuf::Reflection* reflection, |
||||
bool append, |
||||
int index); |
||||
PyObject* ToStringObject( |
||||
const google::protobuf::FieldDescriptor* descriptor, string value); |
||||
|
||||
extern PyObject* PickleError_class; |
||||
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__
|
@ -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. |
||||
|
||||
import "google/protobuf/internal/cpp/proto1_api_test.proto"; |
||||
|
||||
package google.protobuf.python.internal; |
||||
|
||||
message TestNestedProto1APIMessage { |
||||
optional int32 a = 1; |
||||
optional TestMessage.NestedMessage b = 2; |
||||
} |
@ -0,0 +1,66 @@ |
||||
// 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: tibell@google.com (Johan Tibell) |
||||
// |
||||
// These message definitions are used to exercises known corner cases |
||||
// in the C++ implementation of the Python API. |
||||
|
||||
|
||||
package google.protobuf.python.internal; |
||||
|
||||
// Protos optimized for SPEED use a strict superset of the generated code |
||||
// of equivalent ones optimized for CODE_SIZE, so we should optimize all our |
||||
// tests for speed unless explicitly testing code size optimization. |
||||
option optimize_for = SPEED; |
||||
|
||||
message TestAllTypes { |
||||
message NestedMessage { |
||||
optional int32 bb = 1; |
||||
optional ForeignMessage cc = 2; |
||||
} |
||||
|
||||
repeated NestedMessage repeated_nested_message = 1; |
||||
optional NestedMessage optional_nested_message = 2; |
||||
optional int32 optional_int32 = 3; |
||||
} |
||||
|
||||
message ForeignMessage { |
||||
optional int32 c = 1; |
||||
repeated int32 d = 2; |
||||
} |
||||
|
||||
message TestAllExtensions { |
||||
extensions 1 to max; |
||||
} |
||||
|
||||
extend TestAllExtensions { |
||||
optional TestAllTypes.NestedMessage optional_nested_message_extension = 1; |
||||
} |
@ -0,0 +1,57 @@ |
||||
// 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: qrczak@google.com (Marcin Kowalczyk)
|
||||
//
|
||||
// This module exposes the C proto inside the given Python proto, in
|
||||
// case the Python proto is implemented with a C proto.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__ |
||||
#define GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__ |
||||
|
||||
#include <Python.h> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
|
||||
class Message; |
||||
|
||||
namespace python { |
||||
|
||||
// Return the pointer to the C proto inside the given Python proto,
|
||||
// or NULL when this is not a Python proto implemented with a C proto.
|
||||
const Message* GetCProtoInsidePyProto(PyObject* msg); |
||||
Message* MutableCProtoInsidePyProto(PyObject* msg); |
||||
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
|
@ -0,0 +1,763 @@ |
||||
// 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: anuraag@google.com (Anuraag Agrawal)
|
||||
// Author: tibell@google.com (Johan Tibell)
|
||||
|
||||
#include <google/protobuf/pyext/repeated_composite_container.h> |
||||
|
||||
#include <memory> |
||||
#ifndef _SHARED_PTR_H |
||||
#include <google/protobuf/stubs/shared_ptr.h> |
||||
#endif |
||||
|
||||
#include <google/protobuf/stubs/common.h> |
||||
#include <google/protobuf/descriptor.h> |
||||
#include <google/protobuf/dynamic_message.h> |
||||
#include <google/protobuf/message.h> |
||||
#include <google/protobuf/pyext/descriptor.h> |
||||
#include <google/protobuf/pyext/message.h> |
||||
#include <google/protobuf/pyext/scoped_pyobject_ptr.h> |
||||
|
||||
#if PY_MAJOR_VERSION >= 3 |
||||
#define PyInt_Check PyLong_Check |
||||
#define PyInt_AsLong PyLong_AsLong |
||||
#define PyInt_FromLong PyLong_FromLong |
||||
#endif |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace python { |
||||
|
||||
extern google::protobuf::DynamicMessageFactory* global_message_factory; |
||||
|
||||
namespace repeated_composite_container { |
||||
|
||||
// TODO(tibell): We might also want to check:
|
||||
// GOOGLE_CHECK_NOTNULL((self)->owner.get());
|
||||
#define GOOGLE_CHECK_ATTACHED(self) \ |
||||
do { \
|
||||
GOOGLE_CHECK_NOTNULL((self)->message); \
|
||||
GOOGLE_CHECK_NOTNULL((self)->parent_field); \
|
||||
} while (0); |
||||
|
||||
#define GOOGLE_CHECK_RELEASED(self) \ |
||||
do { \
|
||||
GOOGLE_CHECK((self)->owner.get() == NULL); \
|
||||
GOOGLE_CHECK((self)->message == NULL); \
|
||||
GOOGLE_CHECK((self)->parent_field == NULL); \
|
||||
GOOGLE_CHECK((self)->parent == NULL); \
|
||||
} while (0); |
||||
|
||||
// Returns a new reference.
|
||||
static PyObject* GetKey(PyObject* x) { |
||||
// Just the identity function.
|
||||
Py_INCREF(x); |
||||
return x; |
||||
} |
||||
|
||||
#define GET_KEY(keyfunc, value) \ |
||||
((keyfunc) == NULL ? \
|
||||
GetKey((value)) : \
|
||||
PyObject_CallFunctionObjArgs((keyfunc), (value), NULL)) |
||||
|
||||
// Converts a comparison function that returns -1, 0, or 1 into a
|
||||
// less-than predicate.
|
||||
//
|
||||
// Returns -1 on error, 1 if x < y, 0 if x >= y.
|
||||
static int islt(PyObject *x, PyObject *y, PyObject *compare) { |
||||
if (compare == NULL) |
||||
return PyObject_RichCompareBool(x, y, Py_LT); |
||||
|
||||
ScopedPyObjectPtr res(PyObject_CallFunctionObjArgs(compare, x, y, NULL)); |
||||
if (res == NULL) |
||||
return -1; |
||||
if (!PyInt_Check(res)) { |
||||
PyErr_Format(PyExc_TypeError, |
||||
"comparison function must return int, not %.200s", |
||||
Py_TYPE(res)->tp_name); |
||||
return -1; |
||||
} |
||||
return PyInt_AsLong(res) < 0; |
||||
} |
||||
|
||||
// Copied from uarrsort.c but swaps memcpy swaps with protobuf/python swaps
|
||||
// TODO(anuraag): Is there a better way to do this then reinventing the wheel?
|
||||
static int InternalQuickSort(RepeatedCompositeContainer* self, |
||||
Py_ssize_t start, |
||||
Py_ssize_t limit, |
||||
PyObject* cmp, |
||||
PyObject* keyfunc) { |
||||
if (limit - start <= 1) |
||||
return 0; // Nothing to sort.
|
||||
|
||||
GOOGLE_CHECK_ATTACHED(self); |
||||
|
||||
google::protobuf::Message* message = self->message; |
||||
const google::protobuf::Reflection* reflection = message->GetReflection(); |
||||
const google::protobuf::FieldDescriptor* descriptor = self->parent_field->descriptor; |
||||
Py_ssize_t left; |
||||
Py_ssize_t right; |
||||
|
||||
PyObject* children = self->child_messages; |
||||
|
||||
do { |
||||
left = start; |
||||
right = limit; |
||||
ScopedPyObjectPtr mid( |
||||
GET_KEY(keyfunc, PyList_GET_ITEM(children, (start + limit) / 2))); |
||||
do { |
||||
ScopedPyObjectPtr key(GET_KEY(keyfunc, PyList_GET_ITEM(children, left))); |
||||
int is_lt = islt(key, mid, cmp); |
||||
if (is_lt == -1) |
||||
return -1; |
||||
/* array[left]<x */ |
||||
while (is_lt) { |
||||
++left; |
||||
ScopedPyObjectPtr key(GET_KEY(keyfunc, |
||||
PyList_GET_ITEM(children, left))); |
||||
is_lt = islt(key, mid, cmp); |
||||
if (is_lt == -1) |
||||
return -1; |
||||
} |
||||
key.reset(GET_KEY(keyfunc, PyList_GET_ITEM(children, right - 1))); |
||||
is_lt = islt(mid, key, cmp); |
||||
if (is_lt == -1) |
||||
return -1; |
||||
while (is_lt) { |
||||
--right; |
||||
ScopedPyObjectPtr key(GET_KEY(keyfunc, |
||||
PyList_GET_ITEM(children, right - 1))); |
||||
is_lt = islt(mid, key, cmp); |
||||
if (is_lt == -1) |
||||
return -1; |
||||
} |
||||
if (left < right) { |
||||
--right; |
||||
if (left < right) { |
||||
reflection->SwapElements(message, descriptor, left, right); |
||||
PyObject* tmp = PyList_GET_ITEM(children, left); |
||||
PyList_SET_ITEM(children, left, PyList_GET_ITEM(children, right)); |
||||
PyList_SET_ITEM(children, right, tmp); |
||||
} |
||||
++left; |
||||
} |
||||
} while (left < right); |
||||
|
||||
if ((right - start) < (limit - left)) { |
||||
/* sort [start..right[ */ |
||||
if (start < (right - 1)) { |
||||
InternalQuickSort(self, start, right, cmp, keyfunc); |
||||
} |
||||
|
||||
/* sort [left..limit[ */ |
||||
start = left; |
||||
} else { |
||||
/* sort [left..limit[ */ |
||||
if (left < (limit - 1)) { |
||||
InternalQuickSort(self, left, limit, cmp, keyfunc); |
||||
} |
||||
|
||||
/* sort [start..right[ */ |
||||
limit = right; |
||||
} |
||||
} while (start < (limit - 1)); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
#undef GET_KEY |
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// len()
|
||||
|
||||
static Py_ssize_t Length(RepeatedCompositeContainer* self) { |
||||
google::protobuf::Message* message = self->message; |
||||
if (message != NULL) { |
||||
return message->GetReflection()->FieldSize(*message, |
||||
self->parent_field->descriptor); |
||||
} else { |
||||
// The container has been released (i.e. by a call to Clear() or
|
||||
// ClearField() on the parent) and thus there's no message.
|
||||
return PyList_GET_SIZE(self->child_messages); |
||||
} |
||||
} |
||||
|
||||
// Returns 0 if successful; returns -1 and sets an exception if
|
||||
// unsuccessful.
|
||||
static int UpdateChildMessages(RepeatedCompositeContainer* self) { |
||||
if (self->message == NULL) |
||||
return 0; |
||||
|
||||
// A MergeFrom on a parent message could have caused extra messages to be
|
||||
// added in the underlying protobuf so add them to our list. They can never
|
||||
// be removed in such a way so there's no need to worry about that.
|
||||
Py_ssize_t message_length = Length(self); |
||||
Py_ssize_t child_length = PyList_GET_SIZE(self->child_messages); |
||||
google::protobuf::Message* message = self->message; |
||||
const google::protobuf::Reflection* reflection = message->GetReflection(); |
||||
for (Py_ssize_t i = child_length; i < message_length; ++i) { |
||||
const Message& sub_message = reflection->GetRepeatedMessage( |
||||
*(self->message), self->parent_field->descriptor, i); |
||||
ScopedPyObjectPtr py_cmsg(cmessage::NewEmpty(self->subclass_init)); |
||||
if (py_cmsg == NULL) { |
||||
return -1; |
||||
} |
||||
CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg.get()); |
||||
cmsg->owner = self->owner; |
||||
cmsg->message = const_cast<google::protobuf::Message*>(&sub_message); |
||||
cmsg->parent = self->parent; |
||||
if (cmessage::InitAttributes(cmsg, NULL, NULL) < 0) { |
||||
return -1; |
||||
} |
||||
PyList_Append(self->child_messages, py_cmsg); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// add()
|
||||
|
||||
static PyObject* AddToAttached(RepeatedCompositeContainer* self, |
||||
PyObject* args, |
||||
PyObject* kwargs) { |
||||
GOOGLE_CHECK_ATTACHED(self); |
||||
|
||||
if (UpdateChildMessages(self) < 0) { |
||||
return NULL; |
||||
} |
||||
if (cmessage::AssureWritable(self->parent) == -1) |
||||
return NULL; |
||||
google::protobuf::Message* message = self->message; |
||||
google::protobuf::Message* sub_message = |
||||
message->GetReflection()->AddMessage(message, |
||||
self->parent_field->descriptor); |
||||
PyObject* py_cmsg = cmessage::NewEmpty(self->subclass_init); |
||||
if (py_cmsg == NULL) { |
||||
return NULL; |
||||
} |
||||
CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg); |
||||
|
||||
cmsg->owner = self->owner; |
||||
cmsg->message = sub_message; |
||||
cmsg->parent = self->parent; |
||||
// cmessage::InitAttributes must be called after cmsg->message has
|
||||
// been set.
|
||||
if (cmessage::InitAttributes(cmsg, NULL, kwargs) < 0) { |
||||
Py_DECREF(py_cmsg); |
||||
return NULL; |
||||
} |
||||
PyList_Append(self->child_messages, py_cmsg); |
||||
return py_cmsg; |
||||
} |
||||
|
||||
static PyObject* AddToReleased(RepeatedCompositeContainer* self, |
||||
PyObject* args, |
||||
PyObject* kwargs) { |
||||
GOOGLE_CHECK_RELEASED(self); |
||||
|
||||
// Create the CMessage
|
||||
PyObject* py_cmsg = PyObject_CallObject(self->subclass_init, NULL); |
||||
if (py_cmsg == NULL) |
||||
return NULL; |
||||
CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg); |
||||
if (cmessage::InitAttributes(cmsg, NULL, kwargs) < 0) { |
||||
Py_DECREF(py_cmsg); |
||||
return NULL; |
||||
} |
||||
|
||||
// The Message got created by the call to subclass_init above and
|
||||
// it set self->owner to the newly allocated message.
|
||||
|
||||
PyList_Append(self->child_messages, py_cmsg); |
||||
return py_cmsg; |
||||
} |
||||
|
||||
PyObject* Add(RepeatedCompositeContainer* self, |
||||
PyObject* args, |
||||
PyObject* kwargs) { |
||||
if (self->message == NULL) |
||||
return AddToReleased(self, args, kwargs); |
||||
else |
||||
return AddToAttached(self, args, kwargs); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// extend()
|
||||
|
||||
PyObject* Extend(RepeatedCompositeContainer* self, PyObject* value) { |
||||
cmessage::AssureWritable(self->parent); |
||||
if (UpdateChildMessages(self) < 0) { |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr iter(PyObject_GetIter(value)); |
||||
if (iter == NULL) { |
||||
PyErr_SetString(PyExc_TypeError, "Value must be iterable"); |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr next; |
||||
while ((next.reset(PyIter_Next(iter))) != NULL) { |
||||
if (!PyObject_TypeCheck(next, &CMessage_Type)) { |
||||
PyErr_SetString(PyExc_TypeError, "Not a cmessage"); |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr new_message(Add(self, NULL, NULL)); |
||||
if (new_message == NULL) { |
||||
return NULL; |
||||
} |
||||
CMessage* new_cmessage = reinterpret_cast<CMessage*>(new_message.get()); |
||||
if (cmessage::MergeFrom(new_cmessage, next) == NULL) { |
||||
return NULL; |
||||
} |
||||
} |
||||
if (PyErr_Occurred()) { |
||||
return NULL; |
||||
} |
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
PyObject* MergeFrom(RepeatedCompositeContainer* self, PyObject* other) { |
||||
if (UpdateChildMessages(self) < 0) { |
||||
return NULL; |
||||
} |
||||
return Extend(self, other); |
||||
} |
||||
|
||||
PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice) { |
||||
if (UpdateChildMessages(self) < 0) { |
||||
return NULL; |
||||
} |
||||
Py_ssize_t from; |
||||
Py_ssize_t to; |
||||
Py_ssize_t step; |
||||
Py_ssize_t length = Length(self); |
||||
Py_ssize_t slicelength; |
||||
if (PySlice_Check(slice)) { |
||||
#if PY_MAJOR_VERSION >= 3 |
||||
if (PySlice_GetIndicesEx(slice, |
||||
#else |
||||
if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), |
||||
#endif |
||||
length, &from, &to, &step, &slicelength) == -1) { |
||||
return NULL; |
||||
} |
||||
return PyList_GetSlice(self->child_messages, from, to); |
||||
} else if (PyInt_Check(slice) || PyLong_Check(slice)) { |
||||
from = to = PyLong_AsLong(slice); |
||||
if (from < 0) { |
||||
from = to = length + from; |
||||
} |
||||
PyObject* result = PyList_GetItem(self->child_messages, from); |
||||
if (result == NULL) { |
||||
return NULL; |
||||
} |
||||
Py_INCREF(result); |
||||
return result; |
||||
} |
||||
PyErr_SetString(PyExc_TypeError, "index must be an integer or slice"); |
||||
return NULL; |
||||
} |
||||
|
||||
int AssignSubscript(RepeatedCompositeContainer* self, |
||||
PyObject* slice, |
||||
PyObject* value) { |
||||
if (UpdateChildMessages(self) < 0) { |
||||
return -1; |
||||
} |
||||
if (value != NULL) { |
||||
PyErr_SetString(PyExc_TypeError, "does not support assignment"); |
||||
return -1; |
||||
} |
||||
|
||||
// Delete from the underlying Message, if any.
|
||||
if (self->message != NULL) { |
||||
if (cmessage::InternalDeleteRepeatedField(self->message, |
||||
self->parent_field->descriptor, |
||||
slice, |
||||
self->child_messages) < 0) { |
||||
return -1; |
||||
} |
||||
} else { |
||||
Py_ssize_t from; |
||||
Py_ssize_t to; |
||||
Py_ssize_t step; |
||||
Py_ssize_t length = Length(self); |
||||
Py_ssize_t slicelength; |
||||
if (PySlice_Check(slice)) { |
||||
#if PY_MAJOR_VERSION >= 3 |
||||
if (PySlice_GetIndicesEx(slice, |
||||
#else |
||||
if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), |
||||
#endif |
||||
length, &from, &to, &step, &slicelength) == -1) { |
||||
return -1; |
||||
} |
||||
return PySequence_DelSlice(self->child_messages, from, to); |
||||
} else if (PyInt_Check(slice) || PyLong_Check(slice)) { |
||||
from = to = PyLong_AsLong(slice); |
||||
if (from < 0) { |
||||
from = to = length + from; |
||||
} |
||||
return PySequence_DelItem(self->child_messages, from); |
||||
} |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static PyObject* Remove(RepeatedCompositeContainer* self, PyObject* value) { |
||||
if (UpdateChildMessages(self) < 0) { |
||||
return NULL; |
||||
} |
||||
Py_ssize_t index = PySequence_Index(self->child_messages, value); |
||||
if (index == -1) { |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr py_index(PyLong_FromLong(index)); |
||||
if (AssignSubscript(self, py_index, NULL) < 0) { |
||||
return NULL; |
||||
} |
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
static PyObject* RichCompare(RepeatedCompositeContainer* self, |
||||
PyObject* other, |
||||
int opid) { |
||||
if (UpdateChildMessages(self) < 0) { |
||||
return NULL; |
||||
} |
||||
if (!PyObject_TypeCheck(other, &RepeatedCompositeContainer_Type)) { |
||||
PyErr_SetString(PyExc_TypeError, |
||||
"Can only compare repeated composite fields " |
||||
"against other repeated composite fields."); |
||||
return NULL; |
||||
} |
||||
if (opid == Py_EQ || opid == Py_NE) { |
||||
// TODO(anuraag): Don't make new lists just for this...
|
||||
ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); |
||||
if (full_slice == NULL) { |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr list(Subscript(self, full_slice)); |
||||
if (list == NULL) { |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr other_list( |
||||
Subscript( |
||||
reinterpret_cast<RepeatedCompositeContainer*>(other), full_slice)); |
||||
if (other_list == NULL) { |
||||
return NULL; |
||||
} |
||||
return PyObject_RichCompare(list, other_list, opid); |
||||
} else { |
||||
Py_INCREF(Py_NotImplemented); |
||||
return Py_NotImplemented; |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// sort()
|
||||
|
||||
static PyObject* SortAttached(RepeatedCompositeContainer* self, |
||||
PyObject* args, |
||||
PyObject* kwds) { |
||||
// Sort the underlying Message array.
|
||||
PyObject *compare = NULL; |
||||
int reverse = 0; |
||||
PyObject *keyfunc = NULL; |
||||
static char *kwlist[] = {"cmp", "key", "reverse", 0}; |
||||
|
||||
if (args != NULL) { |
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi:sort", |
||||
kwlist, &compare, &keyfunc, &reverse)) |
||||
return NULL; |
||||
} |
||||
if (compare == Py_None) |
||||
compare = NULL; |
||||
if (keyfunc == Py_None) |
||||
keyfunc = NULL; |
||||
|
||||
const Py_ssize_t length = Length(self); |
||||
if (InternalQuickSort(self, 0, length, compare, keyfunc) < 0) |
||||
return NULL; |
||||
|
||||
// Finally reverse the result if requested.
|
||||
if (reverse) { |
||||
google::protobuf::Message* message = self->message; |
||||
const google::protobuf::Reflection* reflection = message->GetReflection(); |
||||
const google::protobuf::FieldDescriptor* descriptor = self->parent_field->descriptor; |
||||
|
||||
// Reverse the Message array.
|
||||
for (int i = 0; i < length / 2; ++i) |
||||
reflection->SwapElements(message, descriptor, i, length - i - 1); |
||||
|
||||
// Reverse the Python list.
|
||||
ScopedPyObjectPtr res(PyObject_CallMethod(self->child_messages, |
||||
"reverse", NULL)); |
||||
if (res == NULL) |
||||
return NULL; |
||||
} |
||||
|
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
static PyObject* SortReleased(RepeatedCompositeContainer* self, |
||||
PyObject* args, |
||||
PyObject* kwds) { |
||||
ScopedPyObjectPtr m(PyObject_GetAttrString(self->child_messages, "sort")); |
||||
if (m == NULL) |
||||
return NULL; |
||||
if (PyObject_Call(m, args, kwds) == NULL) |
||||
return NULL; |
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
static PyObject* Sort(RepeatedCompositeContainer* self, |
||||
PyObject* args, |
||||
PyObject* kwds) { |
||||
// Support the old sort_function argument for backwards
|
||||
// compatibility.
|
||||
if (kwds != NULL) { |
||||
PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function"); |
||||
if (sort_func != NULL) { |
||||
// Must set before deleting as sort_func is a borrowed reference
|
||||
// and kwds might be the only thing keeping it alive.
|
||||
PyDict_SetItemString(kwds, "cmp", sort_func); |
||||
PyDict_DelItemString(kwds, "sort_function"); |
||||
} |
||||
} |
||||
|
||||
if (UpdateChildMessages(self) < 0) |
||||
return NULL; |
||||
if (self->message == NULL) { |
||||
return SortReleased(self, args, kwds); |
||||
} else { |
||||
return SortAttached(self, args, kwds); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
static PyObject* Item(RepeatedCompositeContainer* self, Py_ssize_t index) { |
||||
if (UpdateChildMessages(self) < 0) { |
||||
return NULL; |
||||
} |
||||
Py_ssize_t length = Length(self); |
||||
if (index < 0) { |
||||
index = length + index; |
||||
} |
||||
PyObject* item = PyList_GetItem(self->child_messages, index); |
||||
if (item == NULL) { |
||||
return NULL; |
||||
} |
||||
Py_INCREF(item); |
||||
return item; |
||||
} |
||||
|
||||
// The caller takes ownership of the returned Message.
|
||||
Message* ReleaseLast(const FieldDescriptor* field, |
||||
const Descriptor* type, |
||||
Message* message) { |
||||
GOOGLE_CHECK_NOTNULL(field); |
||||
GOOGLE_CHECK_NOTNULL(type); |
||||
GOOGLE_CHECK_NOTNULL(message); |
||||
|
||||
Message* released_message = message->GetReflection()->ReleaseLast( |
||||
message, field); |
||||
// TODO(tibell): Deal with proto1.
|
||||
|
||||
// ReleaseMessage will return NULL which differs from
|
||||
// child_cmessage->message, if the field does not exist. In this case,
|
||||
// the latter points to the default instance via a const_cast<>, so we
|
||||
// have to reset it to a new mutable object since we are taking ownership.
|
||||
if (released_message == NULL) { |
||||
const Message* prototype = global_message_factory->GetPrototype(type); |
||||
GOOGLE_CHECK_NOTNULL(prototype); |
||||
return prototype->New(); |
||||
} else { |
||||
return released_message; |
||||
} |
||||
} |
||||
|
||||
// Release field of message and transfer the ownership to cmessage.
|
||||
void ReleaseLastTo(const FieldDescriptor* field, |
||||
Message* message, |
||||
CMessage* cmessage) { |
||||
GOOGLE_CHECK_NOTNULL(field); |
||||
GOOGLE_CHECK_NOTNULL(message); |
||||
GOOGLE_CHECK_NOTNULL(cmessage); |
||||
|
||||
shared_ptr<Message> released_message( |
||||
ReleaseLast(field, cmessage->message->GetDescriptor(), message)); |
||||
cmessage->parent = NULL; |
||||
cmessage->parent_field = NULL; |
||||
cmessage->message = released_message.get(); |
||||
cmessage->read_only = false; |
||||
cmessage::SetOwner(cmessage, released_message); |
||||
} |
||||
|
||||
// Called to release a container using
|
||||
// ClearField('container_field_name') on the parent.
|
||||
int Release(RepeatedCompositeContainer* self) { |
||||
if (UpdateChildMessages(self) < 0) { |
||||
PyErr_WriteUnraisable(PyBytes_FromString("Failed to update released " |
||||
"messages")); |
||||
return -1; |
||||
} |
||||
|
||||
Message* message = self->message; |
||||
const FieldDescriptor* field = self->parent_field->descriptor; |
||||
|
||||
// The reflection API only lets us release the last message in a
|
||||
// repeated field. Therefore we iterate through the children
|
||||
// starting with the last one.
|
||||
const Py_ssize_t size = PyList_GET_SIZE(self->child_messages); |
||||
GOOGLE_DCHECK_EQ(size, message->GetReflection()->FieldSize(*message, field)); |
||||
for (Py_ssize_t i = size - 1; i >= 0; --i) { |
||||
CMessage* child_cmessage = reinterpret_cast<CMessage*>( |
||||
PyList_GET_ITEM(self->child_messages, i)); |
||||
ReleaseLastTo(field, message, child_cmessage); |
||||
} |
||||
|
||||
// Detach from containing message.
|
||||
self->parent = NULL; |
||||
self->parent_field = NULL; |
||||
self->message = NULL; |
||||
self->owner.reset(); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int SetOwner(RepeatedCompositeContainer* self, |
||||
const shared_ptr<Message>& new_owner) { |
||||
GOOGLE_CHECK_ATTACHED(self); |
||||
|
||||
self->owner = new_owner; |
||||
const Py_ssize_t n = PyList_GET_SIZE(self->child_messages); |
||||
for (Py_ssize_t i = 0; i < n; ++i) { |
||||
PyObject* msg = PyList_GET_ITEM(self->child_messages, i); |
||||
if (cmessage::SetOwner(reinterpret_cast<CMessage*>(msg), new_owner) == -1) { |
||||
return -1; |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static int Init(RepeatedCompositeContainer* self, |
||||
PyObject* args, |
||||
PyObject* kwargs) { |
||||
self->message = NULL; |
||||
self->parent = NULL; |
||||
self->parent_field = NULL; |
||||
self->subclass_init = NULL; |
||||
self->child_messages = PyList_New(0); |
||||
return 0; |
||||
} |
||||
|
||||
static void Dealloc(RepeatedCompositeContainer* self) { |
||||
Py_CLEAR(self->child_messages); |
||||
// TODO(tibell): Do we need to call delete on these objects to make
|
||||
// sure their destructors are called?
|
||||
self->owner.reset(); |
||||
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); |
||||
} |
||||
|
||||
static PySequenceMethods SqMethods = { |
||||
(lenfunc)Length, /* sq_length */ |
||||
0, /* sq_concat */ |
||||
0, /* sq_repeat */ |
||||
(ssizeargfunc)Item /* sq_item */ |
||||
}; |
||||
|
||||
static PyMappingMethods MpMethods = { |
||||
(lenfunc)Length, /* mp_length */ |
||||
(binaryfunc)Subscript, /* mp_subscript */ |
||||
(objobjargproc)AssignSubscript,/* mp_ass_subscript */ |
||||
}; |
||||
|
||||
static PyMethodDef Methods[] = { |
||||
{ "add", (PyCFunction) Add, METH_VARARGS | METH_KEYWORDS, |
||||
"Adds an object to the repeated container." }, |
||||
{ "extend", (PyCFunction) Extend, METH_O, |
||||
"Adds objects to the repeated container." }, |
||||
{ "remove", (PyCFunction) Remove, METH_O, |
||||
"Removes an object from the repeated container." }, |
||||
{ "sort", (PyCFunction) Sort, METH_VARARGS | METH_KEYWORDS, |
||||
"Sorts the repeated container." }, |
||||
{ "MergeFrom", (PyCFunction) MergeFrom, METH_O, |
||||
"Adds objects to the repeated container." }, |
||||
{ NULL, NULL } |
||||
}; |
||||
|
||||
} // namespace repeated_composite_container
|
||||
|
||||
PyTypeObject RepeatedCompositeContainer_Type = { |
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0) |
||||
"google.protobuf.internal." |
||||
"cpp._message.RepeatedCompositeContainer", // tp_name
|
||||
sizeof(RepeatedCompositeContainer), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor)repeated_composite_container::Dealloc, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
&repeated_composite_container::SqMethods, // tp_as_sequence
|
||||
&repeated_composite_container::MpMethods, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
"A Repeated scalar container", // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
(richcmpfunc)repeated_composite_container::RichCompare, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
repeated_composite_container::Methods, // tp_methods
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
(initproc)repeated_composite_container::Init, // tp_init
|
||||
}; |
||||
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,172 @@ |
||||
// 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: anuraag@google.com (Anuraag Agrawal)
|
||||
// Author: tibell@google.com (Johan Tibell)
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_COMPOSITE_CONTAINER_H__ |
||||
#define GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_COMPOSITE_CONTAINER_H__ |
||||
|
||||
#include <Python.h> |
||||
|
||||
#include <memory> |
||||
#ifndef _SHARED_PTR_H |
||||
#include <google/protobuf/stubs/shared_ptr.h> |
||||
#endif |
||||
#include <string> |
||||
#include <vector> |
||||
|
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
|
||||
class FieldDescriptor; |
||||
class Message; |
||||
|
||||
using internal::shared_ptr; |
||||
|
||||
namespace python { |
||||
|
||||
struct CMessage; |
||||
struct CFieldDescriptor; |
||||
|
||||
// A RepeatedCompositeContainer can be in one of two states: attached
|
||||
// or released.
|
||||
//
|
||||
// When in the attached state all modifications to the container are
|
||||
// done both on the 'message' and on the 'child_messages'
|
||||
// list. In this state all Messages refered to by the children in
|
||||
// 'child_messages' are owner by the 'owner'.
|
||||
//
|
||||
// When in the released state 'message', 'owner', 'parent', and
|
||||
// 'parent_field' are NULL.
|
||||
typedef struct RepeatedCompositeContainer { |
||||
PyObject_HEAD; |
||||
|
||||
// This is the top-level C++ Message object that owns the whole
|
||||
// proto tree. Every Python RepeatedCompositeContainer holds a
|
||||
// reference to it in order to keep it alive as long as there's a
|
||||
// Python object that references any part of the tree.
|
||||
shared_ptr<Message> owner; |
||||
|
||||
// Weak reference to parent object. May be NULL. Used to make sure
|
||||
// the parent is writable before modifying the
|
||||
// RepeatedCompositeContainer.
|
||||
CMessage* parent; |
||||
|
||||
// A descriptor used to modify the underlying 'message'.
|
||||
CFieldDescriptor* parent_field; |
||||
|
||||
// Pointer to the C++ Message that contains this container. The
|
||||
// RepeatedCompositeContainer does not own this pointer.
|
||||
//
|
||||
// If NULL, this message has been released from its parent (by
|
||||
// calling Clear() or ClearField() on the parent.
|
||||
Message* message; |
||||
|
||||
// A callable that is used to create new child messages.
|
||||
PyObject* subclass_init; |
||||
|
||||
// A list of child messages.
|
||||
PyObject* child_messages; |
||||
} RepeatedCompositeContainer; |
||||
|
||||
extern PyTypeObject RepeatedCompositeContainer_Type; |
||||
|
||||
namespace repeated_composite_container { |
||||
|
||||
// Returns the number of items in this repeated composite container.
|
||||
static Py_ssize_t Length(RepeatedCompositeContainer* self); |
||||
|
||||
// Appends a new CMessage to the container and returns it. The
|
||||
// CMessage is initialized using the content of kwargs.
|
||||
//
|
||||
// Returns a new reference if successful; returns NULL and sets an
|
||||
// exception if unsuccessful.
|
||||
PyObject* Add(RepeatedCompositeContainer* self, |
||||
PyObject* args, |
||||
PyObject* kwargs); |
||||
|
||||
// Appends all the CMessages in the input iterator to the container.
|
||||
//
|
||||
// Returns None if successful; returns NULL and sets an exception if
|
||||
// unsuccessful.
|
||||
PyObject* Extend(RepeatedCompositeContainer* self, PyObject* value); |
||||
|
||||
// Appends a new message to the container for each message in the
|
||||
// input iterator, merging each data element in. Equivalent to extend.
|
||||
//
|
||||
// Returns None if successful; returns NULL and sets an exception if
|
||||
// unsuccessful.
|
||||
PyObject* MergeFrom(RepeatedCompositeContainer* self, PyObject* other); |
||||
|
||||
// Accesses messages in the container.
|
||||
//
|
||||
// Returns a new reference to the message for an integer parameter.
|
||||
// Returns a new reference to a list of messages for a slice.
|
||||
PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice); |
||||
|
||||
// Deletes items from the container (cannot be used for assignment).
|
||||
//
|
||||
// Returns 0 on success, -1 on failure.
|
||||
int AssignSubscript(RepeatedCompositeContainer* self, |
||||
PyObject* slice, |
||||
PyObject* value); |
||||
|
||||
// Releases the messages in the container to the given message.
|
||||
//
|
||||
// Returns 0 on success, -1 on failure.
|
||||
int ReleaseToMessage(RepeatedCompositeContainer* self, |
||||
google::protobuf::Message* new_message); |
||||
|
||||
// Releases the messages in the container to a new message.
|
||||
//
|
||||
// Returns 0 on success, -1 on failure.
|
||||
int Release(RepeatedCompositeContainer* self); |
||||
|
||||
// Returns 0 on success, -1 on failure.
|
||||
int SetOwner(RepeatedCompositeContainer* self, |
||||
const shared_ptr<Message>& new_owner); |
||||
|
||||
// Removes the last element of the repeated message field 'field' on
|
||||
// the Message 'message', and transfers the ownership of the released
|
||||
// Message to 'cmessage'.
|
||||
//
|
||||
// Corresponds to reflection api method ReleaseMessage.
|
||||
void ReleaseLastTo(const FieldDescriptor* field, |
||||
Message* message, |
||||
CMessage* cmessage); |
||||
|
||||
} // namespace repeated_composite_container
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_COMPOSITE_CONTAINER_H__
|
@ -0,0 +1,825 @@ |
||||
// 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: anuraag@google.com (Anuraag Agrawal)
|
||||
// Author: tibell@google.com (Johan Tibell)
|
||||
|
||||
#include <google/protobuf/pyext/repeated_scalar_container.h> |
||||
|
||||
#include <memory> |
||||
#ifndef _SHARED_PTR_H |
||||
#include <google/protobuf/stubs/shared_ptr.h> |
||||
#endif |
||||
|
||||
#include <google/protobuf/stubs/common.h> |
||||
#include <google/protobuf/descriptor.h> |
||||
#include <google/protobuf/dynamic_message.h> |
||||
#include <google/protobuf/message.h> |
||||
#include <google/protobuf/pyext/descriptor.h> |
||||
#include <google/protobuf/pyext/message.h> |
||||
#include <google/protobuf/pyext/scoped_pyobject_ptr.h> |
||||
|
||||
#if PY_MAJOR_VERSION >= 3 |
||||
#define PyInt_FromLong PyLong_FromLong |
||||
#if PY_VERSION_HEX < 0x03030000 |
||||
#error "Python 3.0 - 3.2 are not supported." |
||||
#else |
||||
#define PyString_AsString(ob) \ |
||||
(PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AS_STRING(ob)) |
||||
#endif |
||||
#endif |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace python { |
||||
|
||||
extern google::protobuf::DynamicMessageFactory* global_message_factory; |
||||
|
||||
namespace repeated_scalar_container { |
||||
|
||||
static int InternalAssignRepeatedField( |
||||
RepeatedScalarContainer* self, PyObject* list) { |
||||
self->message->GetReflection()->ClearField(self->message, |
||||
self->parent_field->descriptor); |
||||
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) { |
||||
PyObject* value = PyList_GET_ITEM(list, i); |
||||
if (Append(self, value) == NULL) { |
||||
return -1; |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static Py_ssize_t Len(RepeatedScalarContainer* self) { |
||||
google::protobuf::Message* message = self->message; |
||||
return message->GetReflection()->FieldSize(*message, |
||||
self->parent_field->descriptor); |
||||
} |
||||
|
||||
static int AssignItem(RepeatedScalarContainer* self, |
||||
Py_ssize_t index, |
||||
PyObject* arg) { |
||||
cmessage::AssureWritable(self->parent); |
||||
google::protobuf::Message* message = self->message; |
||||
const google::protobuf::FieldDescriptor* field_descriptor = |
||||
self->parent_field->descriptor; |
||||
if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) { |
||||
PyErr_SetString( |
||||
PyExc_KeyError, "Field does not belong to message!"); |
||||
return -1; |
||||
} |
||||
|
||||
const google::protobuf::Reflection* reflection = message->GetReflection(); |
||||
int field_size = reflection->FieldSize(*message, field_descriptor); |
||||
if (index < 0) { |
||||
index = field_size + index; |
||||
} |
||||
if (index < 0 || index >= field_size) { |
||||
PyErr_Format(PyExc_IndexError, |
||||
"list assignment index (%d) out of range", |
||||
static_cast<int>(index)); |
||||
return -1; |
||||
} |
||||
|
||||
if (arg == NULL) { |
||||
ScopedPyObjectPtr py_index(PyLong_FromLong(index)); |
||||
return cmessage::InternalDeleteRepeatedField(message, field_descriptor, |
||||
py_index, NULL); |
||||
} |
||||
|
||||
if (PySequence_Check(arg) && !(PyBytes_Check(arg) || PyUnicode_Check(arg))) { |
||||
PyErr_SetString(PyExc_TypeError, "Value must be scalar"); |
||||
return -1; |
||||
} |
||||
|
||||
switch (field_descriptor->cpp_type()) { |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { |
||||
GOOGLE_CHECK_GET_INT32(arg, value, -1); |
||||
reflection->SetRepeatedInt32(message, field_descriptor, index, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { |
||||
GOOGLE_CHECK_GET_INT64(arg, value, -1); |
||||
reflection->SetRepeatedInt64(message, field_descriptor, index, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { |
||||
GOOGLE_CHECK_GET_UINT32(arg, value, -1); |
||||
reflection->SetRepeatedUInt32(message, field_descriptor, index, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { |
||||
GOOGLE_CHECK_GET_UINT64(arg, value, -1); |
||||
reflection->SetRepeatedUInt64(message, field_descriptor, index, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { |
||||
GOOGLE_CHECK_GET_FLOAT(arg, value, -1); |
||||
reflection->SetRepeatedFloat(message, field_descriptor, index, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { |
||||
GOOGLE_CHECK_GET_DOUBLE(arg, value, -1); |
||||
reflection->SetRepeatedDouble(message, field_descriptor, index, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { |
||||
GOOGLE_CHECK_GET_BOOL(arg, value, -1); |
||||
reflection->SetRepeatedBool(message, field_descriptor, index, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { |
||||
if (!CheckAndSetString( |
||||
arg, message, field_descriptor, reflection, false, index)) { |
||||
return -1; |
||||
} |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { |
||||
GOOGLE_CHECK_GET_INT32(arg, value, -1); |
||||
const google::protobuf::EnumDescriptor* enum_descriptor = |
||||
field_descriptor->enum_type(); |
||||
const google::protobuf::EnumValueDescriptor* enum_value = |
||||
enum_descriptor->FindValueByNumber(value); |
||||
if (enum_value != NULL) { |
||||
reflection->SetRepeatedEnum(message, field_descriptor, index, |
||||
enum_value); |
||||
} else { |
||||
ScopedPyObjectPtr s(PyObject_Str(arg)); |
||||
if (s != NULL) { |
||||
PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", |
||||
PyString_AsString(s.get())); |
||||
} |
||||
return -1; |
||||
} |
||||
break; |
||||
} |
||||
default: |
||||
PyErr_Format( |
||||
PyExc_SystemError, "Adding value to a field of unknown type %d", |
||||
field_descriptor->cpp_type()); |
||||
return -1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) { |
||||
google::protobuf::Message* message = self->message; |
||||
const google::protobuf::FieldDescriptor* field_descriptor = |
||||
self->parent_field->descriptor; |
||||
const google::protobuf::Reflection* reflection = message->GetReflection(); |
||||
|
||||
int field_size = reflection->FieldSize(*message, field_descriptor); |
||||
if (index < 0) { |
||||
index = field_size + index; |
||||
} |
||||
if (index < 0 || index >= field_size) { |
||||
PyErr_Format(PyExc_IndexError, |
||||
"list assignment index (%d) out of range", |
||||
static_cast<int>(index)); |
||||
return NULL; |
||||
} |
||||
|
||||
PyObject* result = NULL; |
||||
switch (field_descriptor->cpp_type()) { |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { |
||||
int32 value = reflection->GetRepeatedInt32( |
||||
*message, field_descriptor, index); |
||||
result = PyInt_FromLong(value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { |
||||
int64 value = reflection->GetRepeatedInt64( |
||||
*message, field_descriptor, index); |
||||
result = PyLong_FromLongLong(value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { |
||||
uint32 value = reflection->GetRepeatedUInt32( |
||||
*message, field_descriptor, index); |
||||
result = PyLong_FromLongLong(value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { |
||||
uint64 value = reflection->GetRepeatedUInt64( |
||||
*message, field_descriptor, index); |
||||
result = PyLong_FromUnsignedLongLong(value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { |
||||
float value = reflection->GetRepeatedFloat( |
||||
*message, field_descriptor, index); |
||||
result = PyFloat_FromDouble(value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { |
||||
double value = reflection->GetRepeatedDouble( |
||||
*message, field_descriptor, index); |
||||
result = PyFloat_FromDouble(value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { |
||||
bool value = reflection->GetRepeatedBool( |
||||
*message, field_descriptor, index); |
||||
result = PyBool_FromLong(value ? 1 : 0); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { |
||||
const google::protobuf::EnumValueDescriptor* enum_value = |
||||
message->GetReflection()->GetRepeatedEnum( |
||||
*message, field_descriptor, index); |
||||
result = PyInt_FromLong(enum_value->number()); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { |
||||
string value = reflection->GetRepeatedString( |
||||
*message, field_descriptor, index); |
||||
result = ToStringObject(field_descriptor, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { |
||||
PyObject* py_cmsg = PyObject_CallObject(reinterpret_cast<PyObject*>( |
||||
&CMessage_Type), NULL); |
||||
if (py_cmsg == NULL) { |
||||
return NULL; |
||||
} |
||||
CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg); |
||||
const google::protobuf::Message& msg = reflection->GetRepeatedMessage( |
||||
*message, field_descriptor, index); |
||||
cmsg->owner = self->owner; |
||||
cmsg->parent = self->parent; |
||||
cmsg->message = const_cast<google::protobuf::Message*>(&msg); |
||||
cmsg->read_only = false; |
||||
result = reinterpret_cast<PyObject*>(py_cmsg); |
||||
break; |
||||
} |
||||
default: |
||||
PyErr_Format( |
||||
PyExc_SystemError, |
||||
"Getting value from a repeated field of unknown type %d", |
||||
field_descriptor->cpp_type()); |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { |
||||
Py_ssize_t from; |
||||
Py_ssize_t to; |
||||
Py_ssize_t step; |
||||
Py_ssize_t length; |
||||
Py_ssize_t slicelength; |
||||
bool return_list = false; |
||||
#if PY_MAJOR_VERSION < 3 |
||||
if (PyInt_Check(slice)) { |
||||
from = to = PyInt_AsLong(slice); |
||||
} else // NOLINT
|
||||
#endif |
||||
if (PyLong_Check(slice)) { |
||||
from = to = PyLong_AsLong(slice); |
||||
} else if (PySlice_Check(slice)) { |
||||
length = Len(self); |
||||
#if PY_MAJOR_VERSION >= 3 |
||||
if (PySlice_GetIndicesEx(slice, |
||||
#else |
||||
if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), |
||||
#endif |
||||
length, &from, &to, &step, &slicelength) == -1) { |
||||
return NULL; |
||||
} |
||||
return_list = true; |
||||
} else { |
||||
PyErr_SetString(PyExc_TypeError, "list indices must be integers"); |
||||
return NULL; |
||||
} |
||||
|
||||
if (!return_list) { |
||||
return Item(self, from); |
||||
} |
||||
|
||||
PyObject* list = PyList_New(0); |
||||
if (list == NULL) { |
||||
return NULL; |
||||
} |
||||
if (from <= to) { |
||||
if (step < 0) { |
||||
return list; |
||||
} |
||||
for (Py_ssize_t index = from; index < to; index += step) { |
||||
if (index < 0 || index >= length) { |
||||
break; |
||||
} |
||||
ScopedPyObjectPtr s(Item(self, index)); |
||||
PyList_Append(list, s); |
||||
} |
||||
} else { |
||||
if (step > 0) { |
||||
return list; |
||||
} |
||||
for (Py_ssize_t index = from; index > to; index += step) { |
||||
if (index < 0 || index >= length) { |
||||
break; |
||||
} |
||||
ScopedPyObjectPtr s(Item(self, index)); |
||||
PyList_Append(list, s); |
||||
} |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
PyObject* Append(RepeatedScalarContainer* self, PyObject* item) { |
||||
cmessage::AssureWritable(self->parent); |
||||
google::protobuf::Message* message = self->message; |
||||
const google::protobuf::FieldDescriptor* field_descriptor = |
||||
self->parent_field->descriptor; |
||||
|
||||
if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) { |
||||
PyErr_SetString( |
||||
PyExc_KeyError, "Field does not belong to message!"); |
||||
return NULL; |
||||
} |
||||
|
||||
const google::protobuf::Reflection* reflection = message->GetReflection(); |
||||
switch (field_descriptor->cpp_type()) { |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { |
||||
GOOGLE_CHECK_GET_INT32(item, value, NULL); |
||||
reflection->AddInt32(message, field_descriptor, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { |
||||
GOOGLE_CHECK_GET_INT64(item, value, NULL); |
||||
reflection->AddInt64(message, field_descriptor, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { |
||||
GOOGLE_CHECK_GET_UINT32(item, value, NULL); |
||||
reflection->AddUInt32(message, field_descriptor, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { |
||||
GOOGLE_CHECK_GET_UINT64(item, value, NULL); |
||||
reflection->AddUInt64(message, field_descriptor, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { |
||||
GOOGLE_CHECK_GET_FLOAT(item, value, NULL); |
||||
reflection->AddFloat(message, field_descriptor, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { |
||||
GOOGLE_CHECK_GET_DOUBLE(item, value, NULL); |
||||
reflection->AddDouble(message, field_descriptor, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { |
||||
GOOGLE_CHECK_GET_BOOL(item, value, NULL); |
||||
reflection->AddBool(message, field_descriptor, value); |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { |
||||
if (!CheckAndSetString( |
||||
item, message, field_descriptor, reflection, true, -1)) { |
||||
return NULL; |
||||
} |
||||
break; |
||||
} |
||||
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { |
||||
GOOGLE_CHECK_GET_INT32(item, value, NULL); |
||||
const google::protobuf::EnumDescriptor* enum_descriptor = |
||||
field_descriptor->enum_type(); |
||||
const google::protobuf::EnumValueDescriptor* enum_value = |
||||
enum_descriptor->FindValueByNumber(value); |
||||
if (enum_value != NULL) { |
||||
reflection->AddEnum(message, field_descriptor, enum_value); |
||||
} else { |
||||
ScopedPyObjectPtr s(PyObject_Str(item)); |
||||
if (s != NULL) { |
||||
PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", |
||||
PyString_AsString(s.get())); |
||||
} |
||||
return NULL; |
||||
} |
||||
break; |
||||
} |
||||
default: |
||||
PyErr_Format( |
||||
PyExc_SystemError, "Adding value to a field of unknown type %d", |
||||
field_descriptor->cpp_type()); |
||||
return NULL; |
||||
} |
||||
|
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
static int AssSubscript(RepeatedScalarContainer* self, |
||||
PyObject* slice, |
||||
PyObject* value) { |
||||
Py_ssize_t from; |
||||
Py_ssize_t to; |
||||
Py_ssize_t step; |
||||
Py_ssize_t length; |
||||
Py_ssize_t slicelength; |
||||
bool create_list = false; |
||||
|
||||
cmessage::AssureWritable(self->parent); |
||||
google::protobuf::Message* message = self->message; |
||||
const google::protobuf::FieldDescriptor* field_descriptor = |
||||
self->parent_field->descriptor; |
||||
|
||||
#if PY_MAJOR_VERSION < 3 |
||||
if (PyInt_Check(slice)) { |
||||
from = to = PyInt_AsLong(slice); |
||||
} else |
||||
#endif |
||||
if (PyLong_Check(slice)) { |
||||
from = to = PyLong_AsLong(slice); |
||||
} else if (PySlice_Check(slice)) { |
||||
const google::protobuf::Reflection* reflection = message->GetReflection(); |
||||
length = reflection->FieldSize(*message, field_descriptor); |
||||
#if PY_MAJOR_VERSION >= 3 |
||||
if (PySlice_GetIndicesEx(slice, |
||||
#else |
||||
if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), |
||||
#endif |
||||
length, &from, &to, &step, &slicelength) == -1) { |
||||
return -1; |
||||
} |
||||
create_list = true; |
||||
} else { |
||||
PyErr_SetString(PyExc_TypeError, "list indices must be integers"); |
||||
return -1; |
||||
} |
||||
|
||||
if (value == NULL) { |
||||
return cmessage::InternalDeleteRepeatedField( |
||||
message, field_descriptor, slice, NULL); |
||||
} |
||||
|
||||
if (!create_list) { |
||||
return AssignItem(self, from, value); |
||||
} |
||||
|
||||
ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); |
||||
if (full_slice == NULL) { |
||||
return -1; |
||||
} |
||||
ScopedPyObjectPtr new_list(Subscript(self, full_slice)); |
||||
if (new_list == NULL) { |
||||
return -1; |
||||
} |
||||
if (PySequence_SetSlice(new_list, from, to, value) < 0) { |
||||
return -1; |
||||
} |
||||
|
||||
return InternalAssignRepeatedField(self, new_list); |
||||
} |
||||
|
||||
PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) { |
||||
cmessage::AssureWritable(self->parent); |
||||
if (PyObject_Not(value)) { |
||||
Py_RETURN_NONE; |
||||
} |
||||
ScopedPyObjectPtr iter(PyObject_GetIter(value)); |
||||
if (iter == NULL) { |
||||
PyErr_SetString(PyExc_TypeError, "Value must be iterable"); |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr next; |
||||
while ((next.reset(PyIter_Next(iter))) != NULL) { |
||||
if (Append(self, next) == NULL) { |
||||
return NULL; |
||||
} |
||||
} |
||||
if (PyErr_Occurred()) { |
||||
return NULL; |
||||
} |
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
static PyObject* Insert(RepeatedScalarContainer* self, PyObject* args) { |
||||
Py_ssize_t index; |
||||
PyObject* value; |
||||
if (!PyArg_ParseTuple(args, "lO", &index, &value)) { |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); |
||||
ScopedPyObjectPtr new_list(Subscript(self, full_slice)); |
||||
if (PyList_Insert(new_list, index, value) < 0) { |
||||
return NULL; |
||||
} |
||||
int ret = InternalAssignRepeatedField(self, new_list); |
||||
if (ret < 0) { |
||||
return NULL; |
||||
} |
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
static PyObject* Remove(RepeatedScalarContainer* self, PyObject* value) { |
||||
Py_ssize_t match_index = -1; |
||||
for (Py_ssize_t i = 0; i < Len(self); ++i) { |
||||
ScopedPyObjectPtr elem(Item(self, i)); |
||||
if (PyObject_RichCompareBool(elem, value, Py_EQ)) { |
||||
match_index = i; |
||||
break; |
||||
} |
||||
} |
||||
if (match_index == -1) { |
||||
PyErr_SetString(PyExc_ValueError, "remove(x): x not in container"); |
||||
return NULL; |
||||
} |
||||
if (AssignItem(self, match_index, NULL) < 0) { |
||||
return NULL; |
||||
} |
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
static PyObject* RichCompare(RepeatedScalarContainer* self, |
||||
PyObject* other, |
||||
int opid) { |
||||
if (opid != Py_EQ && opid != Py_NE) { |
||||
Py_INCREF(Py_NotImplemented); |
||||
return Py_NotImplemented; |
||||
} |
||||
|
||||
// Copy the contents of this repeated scalar container, and other if it is
|
||||
// also a repeated scalar container, into Python lists so we can delegate
|
||||
// to the list's compare method.
|
||||
|
||||
ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); |
||||
if (full_slice == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
ScopedPyObjectPtr other_list_deleter; |
||||
if (PyObject_TypeCheck(other, &RepeatedScalarContainer_Type)) { |
||||
other_list_deleter.reset(Subscript( |
||||
reinterpret_cast<RepeatedScalarContainer*>(other), full_slice)); |
||||
other = other_list_deleter.get(); |
||||
} |
||||
|
||||
ScopedPyObjectPtr list(Subscript(self, full_slice)); |
||||
if (list == NULL) { |
||||
return NULL; |
||||
} |
||||
return PyObject_RichCompare(list, other, opid); |
||||
} |
||||
|
||||
PyObject* Reduce(RepeatedScalarContainer* unused_self) { |
||||
PyErr_Format( |
||||
PickleError_class, |
||||
"can't pickle repeated message fields, convert to list first"); |
||||
return NULL; |
||||
} |
||||
|
||||
static PyObject* Sort(RepeatedScalarContainer* self, |
||||
PyObject* args, |
||||
PyObject* kwds) { |
||||
// Support the old sort_function argument for backwards
|
||||
// compatibility.
|
||||
if (kwds != NULL) { |
||||
PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function"); |
||||
if (sort_func != NULL) { |
||||
// Must set before deleting as sort_func is a borrowed reference
|
||||
// and kwds might be the only thing keeping it alive.
|
||||
if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1) |
||||
return NULL; |
||||
if (PyDict_DelItemString(kwds, "sort_function") == -1) |
||||
return NULL; |
||||
} |
||||
} |
||||
|
||||
ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); |
||||
if (full_slice == NULL) { |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr list(Subscript(self, full_slice)); |
||||
if (list == NULL) { |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr m(PyObject_GetAttrString(list, "sort")); |
||||
if (m == NULL) { |
||||
return NULL; |
||||
} |
||||
ScopedPyObjectPtr res(PyObject_Call(m, args, kwds)); |
||||
if (res == NULL) { |
||||
return NULL; |
||||
} |
||||
int ret = InternalAssignRepeatedField(self, list); |
||||
if (ret < 0) { |
||||
return NULL; |
||||
} |
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
static int Init(RepeatedScalarContainer* self, |
||||
PyObject* args, |
||||
PyObject* kwargs) { |
||||
PyObject* py_parent; |
||||
PyObject* py_parent_field; |
||||
if (!PyArg_UnpackTuple(args, "__init__()", 2, 2, &py_parent, |
||||
&py_parent_field)) { |
||||
return -1; |
||||
} |
||||
|
||||
if (!PyObject_TypeCheck(py_parent, &CMessage_Type)) { |
||||
PyErr_Format(PyExc_TypeError, |
||||
"expect %s, but got %s", |
||||
CMessage_Type.tp_name, |
||||
Py_TYPE(py_parent)->tp_name); |
||||
return -1; |
||||
} |
||||
|
||||
if (!PyObject_TypeCheck(py_parent_field, &CFieldDescriptor_Type)) { |
||||
PyErr_Format(PyExc_TypeError, |
||||
"expect %s, but got %s", |
||||
CFieldDescriptor_Type.tp_name, |
||||
Py_TYPE(py_parent_field)->tp_name); |
||||
return -1; |
||||
} |
||||
|
||||
CMessage* cmessage = reinterpret_cast<CMessage*>(py_parent); |
||||
CFieldDescriptor* cdescriptor = reinterpret_cast<CFieldDescriptor*>( |
||||
py_parent_field); |
||||
|
||||
if (!FIELD_BELONGS_TO_MESSAGE(cdescriptor->descriptor, cmessage->message)) { |
||||
PyErr_SetString( |
||||
PyExc_KeyError, "Field does not belong to message!"); |
||||
return -1; |
||||
} |
||||
|
||||
self->message = cmessage->message; |
||||
self->parent = cmessage; |
||||
self->parent_field = cdescriptor; |
||||
self->owner = cmessage->owner; |
||||
return 0; |
||||
} |
||||
|
||||
// Initializes the underlying Message object of "to" so it becomes a new parent
|
||||
// repeated scalar, and copies all the values from "from" to it. A child scalar
|
||||
// container can be released by passing it as both from and to (e.g. making it
|
||||
// the recipient of the new parent message and copying the values from itself).
|
||||
static int InitializeAndCopyToParentContainer( |
||||
RepeatedScalarContainer* from, |
||||
RepeatedScalarContainer* to) { |
||||
ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); |
||||
if (full_slice == NULL) { |
||||
return -1; |
||||
} |
||||
ScopedPyObjectPtr values(Subscript(from, full_slice)); |
||||
if (values == NULL) { |
||||
return -1; |
||||
} |
||||
google::protobuf::Message* new_message = global_message_factory->GetPrototype( |
||||
from->message->GetDescriptor())->New(); |
||||
to->parent = NULL; |
||||
// TODO(anuraag): Document why it's OK to hang on to parent_field,
|
||||
// even though it's a weak reference. It ought to be enough to
|
||||
// hold on to the FieldDescriptor only.
|
||||
to->parent_field = from->parent_field; |
||||
to->message = new_message; |
||||
to->owner.reset(new_message); |
||||
if (InternalAssignRepeatedField(to, values) < 0) { |
||||
return -1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int Release(RepeatedScalarContainer* self) { |
||||
return InitializeAndCopyToParentContainer(self, self); |
||||
} |
||||
|
||||
PyObject* DeepCopy(RepeatedScalarContainer* self, PyObject* arg) { |
||||
ScopedPyObjectPtr init_args( |
||||
PyTuple_Pack(2, self->parent, self->parent_field)); |
||||
PyObject* clone = PyObject_CallObject( |
||||
reinterpret_cast<PyObject*>(&RepeatedScalarContainer_Type), init_args); |
||||
if (clone == NULL) { |
||||
return NULL; |
||||
} |
||||
if (!PyObject_TypeCheck(clone, &RepeatedScalarContainer_Type)) { |
||||
Py_DECREF(clone); |
||||
return NULL; |
||||
} |
||||
if (InitializeAndCopyToParentContainer( |
||||
self, reinterpret_cast<RepeatedScalarContainer*>(clone)) < 0) { |
||||
Py_DECREF(clone); |
||||
return NULL; |
||||
} |
||||
return clone; |
||||
} |
||||
|
||||
static void Dealloc(RepeatedScalarContainer* self) { |
||||
self->owner.reset(); |
||||
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); |
||||
} |
||||
|
||||
void SetOwner(RepeatedScalarContainer* self, |
||||
const shared_ptr<Message>& new_owner) { |
||||
self->owner = new_owner; |
||||
} |
||||
|
||||
static PySequenceMethods SqMethods = { |
||||
(lenfunc)Len, /* sq_length */ |
||||
0, /* sq_concat */ |
||||
0, /* sq_repeat */ |
||||
(ssizeargfunc)Item, /* sq_item */ |
||||
0, /* sq_slice */ |
||||
(ssizeobjargproc)AssignItem /* sq_ass_item */ |
||||
}; |
||||
|
||||
static PyMappingMethods MpMethods = { |
||||
(lenfunc)Len, /* mp_length */ |
||||
(binaryfunc)Subscript, /* mp_subscript */ |
||||
(objobjargproc)AssSubscript, /* mp_ass_subscript */ |
||||
}; |
||||
|
||||
static PyMethodDef Methods[] = { |
||||
{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, |
||||
"Makes a deep copy of the class." }, |
||||
{ "__reduce__", (PyCFunction)Reduce, METH_NOARGS, |
||||
"Outputs picklable representation of the repeated field." }, |
||||
{ "append", (PyCFunction)Append, METH_O, |
||||
"Appends an object to the repeated container." }, |
||||
{ "extend", (PyCFunction)Extend, METH_O, |
||||
"Appends objects to the repeated container." }, |
||||
{ "insert", (PyCFunction)Insert, METH_VARARGS, |
||||
"Appends objects to the repeated container." }, |
||||
{ "remove", (PyCFunction)Remove, METH_O, |
||||
"Removes an object from the repeated container." }, |
||||
{ "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS, |
||||
"Sorts the repeated container."}, |
||||
{ NULL, NULL } |
||||
}; |
||||
|
||||
} // namespace repeated_scalar_container
|
||||
|
||||
PyTypeObject RepeatedScalarContainer_Type = { |
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0) |
||||
"google.protobuf.internal." |
||||
"cpp._message.RepeatedScalarContainer", // tp_name
|
||||
sizeof(RepeatedScalarContainer), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor)repeated_scalar_container::Dealloc, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
&repeated_scalar_container::SqMethods, // tp_as_sequence
|
||||
&repeated_scalar_container::MpMethods, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
"A Repeated scalar container", // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
(richcmpfunc)repeated_scalar_container::RichCompare, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
repeated_scalar_container::Methods, // tp_methods
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
(initproc)repeated_scalar_container::Init, // tp_init
|
||||
}; |
||||
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,112 @@ |
||||
// 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: anuraag@google.com (Anuraag Agrawal)
|
||||
// Author: tibell@google.com (Johan Tibell)
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_SCALAR_CONTAINER_H__ |
||||
#define GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_SCALAR_CONTAINER_H__ |
||||
|
||||
#include <Python.h> |
||||
|
||||
#include <memory> |
||||
#ifndef _SHARED_PTR_H |
||||
#include <google/protobuf/stubs/shared_ptr.h> |
||||
#endif |
||||
|
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
|
||||
class Message; |
||||
|
||||
using internal::shared_ptr; |
||||
|
||||
namespace python { |
||||
|
||||
struct CFieldDescriptor; |
||||
struct CMessage; |
||||
|
||||
typedef struct RepeatedScalarContainer { |
||||
PyObject_HEAD; |
||||
|
||||
// This is the top-level C++ Message object that owns the whole
|
||||
// proto tree. Every Python RepeatedScalarContainer holds a
|
||||
// reference to it in order to keep it alive as long as there's a
|
||||
// Python object that references any part of the tree.
|
||||
shared_ptr<Message> owner; |
||||
|
||||
// Pointer to the C++ Message that contains this container. The
|
||||
// RepeatedScalarContainer does not own this pointer.
|
||||
Message* message; |
||||
|
||||
// Weak reference to a parent CMessage object (i.e. may be NULL.)
|
||||
//
|
||||
// Used to make sure all ancestors are also mutable when first
|
||||
// modifying the container.
|
||||
CMessage* parent; |
||||
|
||||
// Weak reference to the parent's descriptor that describes this
|
||||
// field. Used together with the parent's message when making a
|
||||
// default message instance mutable.
|
||||
CFieldDescriptor* parent_field; |
||||
} RepeatedScalarContainer; |
||||
|
||||
extern PyTypeObject RepeatedScalarContainer_Type; |
||||
|
||||
namespace repeated_scalar_container { |
||||
|
||||
// Appends the scalar 'item' to the end of the container 'self'.
|
||||
//
|
||||
// Returns None if successful; returns NULL and sets an exception if
|
||||
// unsuccessful.
|
||||
PyObject* Append(RepeatedScalarContainer* self, PyObject* item); |
||||
|
||||
// Releases the messages in the container to a new message.
|
||||
//
|
||||
// Returns 0 on success, -1 on failure.
|
||||
int Release(RepeatedScalarContainer* self); |
||||
|
||||
// Appends all the elements in the input iterator to the container.
|
||||
//
|
||||
// Returns None if successful; returns NULL and sets an exception if
|
||||
// unsuccessful.
|
||||
PyObject* Extend(RepeatedScalarContainer* self, PyObject* value); |
||||
|
||||
// Set the owner field of self and any children of self.
|
||||
void SetOwner(RepeatedScalarContainer* self, |
||||
const shared_ptr<Message>& new_owner); |
||||
|
||||
} // namespace repeated_scalar_container
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_SCALAR_CONTAINER_H__
|
@ -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: tibell@google.com (Johan Tibell)
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__ |
||||
#define GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__ |
||||
|
||||
#include <Python.h> |
||||
|
||||
namespace google { |
||||
class ScopedPyObjectPtr { |
||||
public: |
||||
// Constructor. Defaults to intializing with NULL.
|
||||
// There is no way to create an uninitialized ScopedPyObjectPtr.
|
||||
explicit ScopedPyObjectPtr(PyObject* p = NULL) : ptr_(p) { } |
||||
|
||||
// Destructor. If there is a PyObject object, delete it.
|
||||
~ScopedPyObjectPtr() { |
||||
Py_XDECREF(ptr_); |
||||
} |
||||
|
||||
// Reset. Deletes the current owned object, if any.
|
||||
// Then takes ownership of a new object, if given.
|
||||
// this->reset(this->get()) works.
|
||||
PyObject* reset(PyObject* p = NULL) { |
||||
if (p != ptr_) { |
||||
Py_XDECREF(ptr_); |
||||
ptr_ = p; |
||||
} |
||||
return ptr_; |
||||
} |
||||
|
||||
// Releases ownership of the object.
|
||||
PyObject* release() { |
||||
PyObject* p = ptr_; |
||||
ptr_ = NULL; |
||||
return p; |
||||
} |
||||
|
||||
operator PyObject*() { return ptr_; } |
||||
|
||||
PyObject* operator->() const { |
||||
assert(ptr_ != NULL); |
||||
return ptr_; |
||||
} |
||||
|
||||
PyObject* get() const { return ptr_; } |
||||
|
||||
Py_ssize_t refcnt() const { return Py_REFCNT(ptr_); } |
||||
|
||||
void inc() const { Py_INCREF(ptr_); } |
||||
|
||||
// Comparison operators.
|
||||
// These return whether a ScopedPyObjectPtr and a raw pointer
|
||||
// refer to the same object, not just to two different but equal
|
||||
// objects.
|
||||
bool operator==(const PyObject* p) const { return ptr_ == p; } |
||||
bool operator!=(const PyObject* p) const { return ptr_ != p; } |
||||
|
||||
private: |
||||
PyObject* ptr_; |
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ScopedPyObjectPtr); |
||||
}; |
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__
|
@ -0,0 +1,185 @@ |
||||
# 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. |
||||
|
||||
"""A database of Python protocol buffer generated symbols. |
||||
|
||||
SymbolDatabase makes it easy to create new instances of a registered type, given |
||||
only the type's protocol buffer symbol name. Once all symbols are registered, |
||||
they can be accessed using either the MessageFactory interface which |
||||
SymbolDatabase exposes, or the DescriptorPool interface of the underlying |
||||
pool. |
||||
|
||||
Example usage: |
||||
|
||||
db = symbol_database.SymbolDatabase() |
||||
|
||||
# Register symbols of interest, from one or multiple files. |
||||
db.RegisterFileDescriptor(my_proto_pb2.DESCRIPTOR) |
||||
db.RegisterMessage(my_proto_pb2.MyMessage) |
||||
db.RegisterEnumDescriptor(my_proto_pb2.MyEnum.DESCRIPTOR) |
||||
|
||||
# The database can be used as a MessageFactory, to generate types based on |
||||
# their name: |
||||
types = db.GetMessages(['my_proto.proto']) |
||||
my_message_instance = types['MyMessage']() |
||||
|
||||
# The database's underlying descriptor pool can be queried, so it's not |
||||
# necessary to know a type's filename to be able to generate it: |
||||
filename = db.pool.FindFileContainingSymbol('MyMessage') |
||||
my_message_instance = db.GetMessages([filename])['MyMessage']() |
||||
|
||||
# This functionality is also provided directly via a convenience method: |
||||
my_message_instance = db.GetSymbol('MyMessage')() |
||||
""" |
||||
|
||||
|
||||
from google.protobuf import descriptor_pool |
||||
|
||||
|
||||
class SymbolDatabase(object): |
||||
"""A database of Python generated symbols. |
||||
|
||||
SymbolDatabase also models message_factory.MessageFactory. |
||||
|
||||
The symbol database can be used to keep a global registry of all protocol |
||||
buffer types used within a program. |
||||
""" |
||||
|
||||
def __init__(self): |
||||
"""Constructor.""" |
||||
|
||||
self._symbols = {} |
||||
self._symbols_by_file = {} |
||||
self.pool = descriptor_pool.DescriptorPool() |
||||
|
||||
def RegisterMessage(self, message): |
||||
"""Registers the given message type in the local database. |
||||
|
||||
Args: |
||||
message: a message.Message, to be registered. |
||||
|
||||
Returns: |
||||
The provided message. |
||||
""" |
||||
|
||||
desc = message.DESCRIPTOR |
||||
self._symbols[desc.full_name] = message |
||||
if desc.file.name not in self._symbols_by_file: |
||||
self._symbols_by_file[desc.file.name] = {} |
||||
self._symbols_by_file[desc.file.name][desc.full_name] = message |
||||
self.pool.AddDescriptor(desc) |
||||
return message |
||||
|
||||
def RegisterEnumDescriptor(self, enum_descriptor): |
||||
"""Registers the given enum descriptor in the local database. |
||||
|
||||
Args: |
||||
enum_descriptor: a descriptor.EnumDescriptor. |
||||
|
||||
Returns: |
||||
The provided descriptor. |
||||
""" |
||||
self.pool.AddEnumDescriptor(enum_descriptor) |
||||
return enum_descriptor |
||||
|
||||
def RegisterFileDescriptor(self, file_descriptor): |
||||
"""Registers the given file descriptor in the local database. |
||||
|
||||
Args: |
||||
file_descriptor: a descriptor.FileDescriptor. |
||||
|
||||
Returns: |
||||
The provided descriptor. |
||||
""" |
||||
self.pool.AddFileDescriptor(file_descriptor) |
||||
|
||||
def GetSymbol(self, symbol): |
||||
"""Tries to find a symbol in the local database. |
||||
|
||||
Currently, this method only returns message.Message instances, however, if |
||||
may be extended in future to support other symbol types. |
||||
|
||||
Args: |
||||
symbol: A str, a protocol buffer symbol. |
||||
|
||||
Returns: |
||||
A Python class corresponding to the symbol. |
||||
|
||||
Raises: |
||||
KeyError: if the symbol could not be found. |
||||
""" |
||||
|
||||
return self._symbols[symbol] |
||||
|
||||
def GetPrototype(self, descriptor): |
||||
"""Builds a proto2 message class based on the passed in descriptor. |
||||
|
||||
Passing a descriptor with a fully qualified name matching a previous |
||||
invocation will cause the same class to be returned. |
||||
|
||||
Args: |
||||
descriptor: The descriptor to build from. |
||||
|
||||
Returns: |
||||
A class describing the passed in descriptor. |
||||
""" |
||||
|
||||
return self.GetSymbol(descriptor.full_name) |
||||
|
||||
def GetMessages(self, files): |
||||
"""Gets all the messages from a specified file. |
||||
|
||||
This will find and resolve dependencies, failing if they are not registered |
||||
in the symbol database. |
||||
|
||||
|
||||
Args: |
||||
files: The file names to extract messages from. |
||||
|
||||
Returns: |
||||
A dictionary mapping proto names to the message classes. This will include |
||||
any dependent messages as well as any messages defined in the same file as |
||||
a specified message. |
||||
|
||||
Raises: |
||||
KeyError: if a file could not be found. |
||||
""" |
||||
|
||||
result = {} |
||||
for f in files: |
||||
result.update(self._symbols_by_file[f]) |
||||
return result |
||||
|
||||
_DEFAULT = SymbolDatabase() |
||||
|
||||
|
||||
def Default(): |
||||
"""Returns the default SymbolDatabase.""" |
||||
return _DEFAULT |
@ -0,0 +1,110 @@ |
||||
# 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. |
||||
|
||||
#PY25 compatible for GAE. |
||||
# |
||||
"""Encoding related utilities.""" |
||||
|
||||
import re |
||||
import sys ##PY25 |
||||
|
||||
# Lookup table for utf8 |
||||
_cescape_utf8_to_str = [chr(i) for i in xrange(0, 256)] |
||||
_cescape_utf8_to_str[9] = r'\t' # optional escape |
||||
_cescape_utf8_to_str[10] = r'\n' # optional escape |
||||
_cescape_utf8_to_str[13] = r'\r' # optional escape |
||||
_cescape_utf8_to_str[39] = r"\'" # optional escape |
||||
|
||||
_cescape_utf8_to_str[34] = r'\"' # necessary escape |
||||
_cescape_utf8_to_str[92] = r'\\' # necessary escape |
||||
|
||||
# Lookup table for non-utf8, with necessary escapes at (o >= 127 or o < 32) |
||||
_cescape_byte_to_str = ([r'\%03o' % i for i in xrange(0, 32)] + |
||||
[chr(i) for i in xrange(32, 127)] + |
||||
[r'\%03o' % i for i in xrange(127, 256)]) |
||||
_cescape_byte_to_str[9] = r'\t' # optional escape |
||||
_cescape_byte_to_str[10] = r'\n' # optional escape |
||||
_cescape_byte_to_str[13] = r'\r' # optional escape |
||||
_cescape_byte_to_str[39] = r"\'" # optional escape |
||||
|
||||
_cescape_byte_to_str[34] = r'\"' # necessary escape |
||||
_cescape_byte_to_str[92] = r'\\' # necessary escape |
||||
|
||||
|
||||
def CEscape(text, as_utf8): |
||||
"""Escape a bytes string for use in an ascii protocol buffer. |
||||
|
||||
text.encode('string_escape') does not seem to satisfy our needs as it |
||||
encodes unprintable characters using two-digit hex escapes whereas our |
||||
C++ unescaping function allows hex escapes to be any length. So, |
||||
"\0011".encode('string_escape') ends up being "\\x011", which will be |
||||
decoded in C++ as a single-character string with char code 0x11. |
||||
|
||||
Args: |
||||
text: A byte string to be escaped |
||||
as_utf8: Specifies if result should be returned in UTF-8 encoding |
||||
Returns: |
||||
Escaped string |
||||
""" |
||||
# PY3 hack: make Ord work for str and bytes: |
||||
# //platforms/networking/data uses unicode here, hence basestring. |
||||
Ord = ord if isinstance(text, basestring) else lambda x: x |
||||
if as_utf8: |
||||
return ''.join(_cescape_utf8_to_str[Ord(c)] for c in text) |
||||
return ''.join(_cescape_byte_to_str[Ord(c)] for c in text) |
||||
|
||||
|
||||
_CUNESCAPE_HEX = re.compile(r'(\\+)x([0-9a-fA-F])(?![0-9a-fA-F])') |
||||
_cescape_highbit_to_str = ([chr(i) for i in range(0, 127)] + |
||||
[r'\%03o' % i for i in range(127, 256)]) |
||||
|
||||
|
||||
def CUnescape(text): |
||||
"""Unescape a text string with C-style escape sequences to UTF-8 bytes.""" |
||||
|
||||
def ReplaceHex(m): |
||||
# Only replace the match if the number of leading back slashes is odd. i.e. |
||||
# the slash itself is not escaped. |
||||
if len(m.group(1)) & 1: |
||||
return m.group(1) + 'x0' + m.group(2) |
||||
return m.group(0) |
||||
|
||||
# This is required because the 'string_escape' encoding doesn't |
||||
# allow single-digit hex escapes (like '\xf'). |
||||
result = _CUNESCAPE_HEX.sub(ReplaceHex, text) |
||||
|
||||
if sys.version_info[0] < 3: ##PY25 |
||||
##!PY25 if str is bytes: # PY2 |
||||
return result.decode('string_escape') |
||||
result = ''.join(_cescape_highbit_to_str[ord(c)] for c in result) |
||||
return (result.encode('ascii') # Make it bytes to allow decode. |
||||
.decode('unicode_escape') |
||||
# Make it bytes again to return the proper type. |
||||
.encode('raw_unicode_escape')) |
@ -0,0 +1,129 @@ |
||||
optional_int32: 101 |
||||
optional_int64: 102 |
||||
optional_uint32: 103 |
||||
optional_uint64: 104 |
||||
optional_sint32: 105 |
||||
optional_sint64: 106 |
||||
optional_fixed32: 107 |
||||
optional_fixed64: 108 |
||||
optional_sfixed32: 109 |
||||
optional_sfixed64: 110 |
||||
optional_float: 111 |
||||
optional_double: 112 |
||||
optional_bool: true |
||||
optional_string: "115" |
||||
optional_bytes: "116" |
||||
OptionalGroup < |
||||
a: 117 |
||||
> |
||||
optional_nested_message < |
||||
bb: 118 |
||||
> |
||||
optional_foreign_message < |
||||
c: 119 |
||||
> |
||||
optional_import_message < |
||||
d: 120 |
||||
> |
||||
optional_nested_enum: BAZ |
||||
optional_foreign_enum: FOREIGN_BAZ |
||||
optional_import_enum: IMPORT_BAZ |
||||
optional_string_piece: "124" |
||||
optional_cord: "125" |
||||
optional_public_import_message < |
||||
e: 126 |
||||
> |
||||
optional_lazy_message < |
||||
bb: 127 |
||||
> |
||||
repeated_int32: 201 |
||||
repeated_int32: 301 |
||||
repeated_int64: 202 |
||||
repeated_int64: 302 |
||||
repeated_uint32: 203 |
||||
repeated_uint32: 303 |
||||
repeated_uint64: 204 |
||||
repeated_uint64: 304 |
||||
repeated_sint32: 205 |
||||
repeated_sint32: 305 |
||||
repeated_sint64: 206 |
||||
repeated_sint64: 306 |
||||
repeated_fixed32: 207 |
||||
repeated_fixed32: 307 |
||||
repeated_fixed64: 208 |
||||
repeated_fixed64: 308 |
||||
repeated_sfixed32: 209 |
||||
repeated_sfixed32: 309 |
||||
repeated_sfixed64: 210 |
||||
repeated_sfixed64: 310 |
||||
repeated_float: 211 |
||||
repeated_float: 311 |
||||
repeated_double: 212 |
||||
repeated_double: 312 |
||||
repeated_bool: true |
||||
repeated_bool: false |
||||
repeated_string: "215" |
||||
repeated_string: "315" |
||||
repeated_bytes: "216" |
||||
repeated_bytes: "316" |
||||
RepeatedGroup < |
||||
a: 217 |
||||
> |
||||
RepeatedGroup < |
||||
a: 317 |
||||
> |
||||
repeated_nested_message < |
||||
bb: 218 |
||||
> |
||||
repeated_nested_message < |
||||
bb: 318 |
||||
> |
||||
repeated_foreign_message < |
||||
c: 219 |
||||
> |
||||
repeated_foreign_message < |
||||
c: 319 |
||||
> |
||||
repeated_import_message < |
||||
d: 220 |
||||
> |
||||
repeated_import_message < |
||||
d: 320 |
||||
> |
||||
repeated_nested_enum: BAR |
||||
repeated_nested_enum: BAZ |
||||
repeated_foreign_enum: FOREIGN_BAR |
||||
repeated_foreign_enum: FOREIGN_BAZ |
||||
repeated_import_enum: IMPORT_BAR |
||||
repeated_import_enum: IMPORT_BAZ |
||||
repeated_string_piece: "224" |
||||
repeated_string_piece: "324" |
||||
repeated_cord: "225" |
||||
repeated_cord: "325" |
||||
repeated_lazy_message < |
||||
bb: 227 |
||||
> |
||||
repeated_lazy_message < |
||||
bb: 327 |
||||
> |
||||
default_int32: 401 |
||||
default_int64: 402 |
||||
default_uint32: 403 |
||||
default_uint64: 404 |
||||
default_sint32: 405 |
||||
default_sint64: 406 |
||||
default_fixed32: 407 |
||||
default_fixed64: 408 |
||||
default_sfixed32: 409 |
||||
default_sfixed64: 410 |
||||
default_float: 411 |
||||
default_double: 412 |
||||
default_bool: false |
||||
default_string: "415" |
||||
default_bytes: "416" |
||||
default_nested_enum: FOO |
||||
default_foreign_enum: FOREIGN_FOO |
||||
default_import_enum: IMPORT_FOO |
||||
default_string_piece: "424" |
||||
default_cord: "425" |
||||
oneof_bytes: "604" |
Loading…
Reference in new issue