Files
ortools-clone/ortools/util/python/vector.i

163 lines
5.5 KiB
OpenEdge ABL

// Copyright 2010-2018 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO(user): make this SWIG file comply with the SWIG style guide.
%include "ortools/base/base.i"
%import "ortools/base/integral_types.h"
// --------- std::vector<data> wrapping ----------
// We can't just reuse the google.i code (see LIST_OUTPUT_TYPEMAP in that
// file); for two reasons:
// 1) We want a few extra typemaps (ITI integers <-> int, for example), but
// can't invoke google.i's LIST_OUTPUT_TYPEMAP because it's only
// defined there. We may reuse base/swig/python-swig.cc though, since it's
// bundled with the google.i rule.
// 2) We use a lot of function overloading, so we must add extra typechecks.
//
// Note(user): for an unknown reason, using the (handy) method PyObjAs()
// defined in base/swig/python-swig.cc seems to cause issues, so we can't
// use a generic, templated type checker.
// Get const std::vector<std::string>& "in" typemap.
%define PY_LIST_OUTPUT_TYPEMAP(type, checker, py_converter)
%typecheck(SWIG_TYPECHECK_POINTER) const std::vector<type>&,
std::vector<type>,
const std::vector<type>* {
if (!PyTuple_Check($input) && !PyList_Check($input)) {
$1 = 0;
} else {
const bool is_tuple = PyTuple_Check($input);
const size_t size = is_tuple ? PyTuple_Size($input) : PyList_Size($input);
size_t i = 0;
while (i < size && checker(is_tuple ? PyTuple_GetItem($input, i)
: PyList_GetItem($input, i))) {
++i;
}
$1 = i == size;
}
}
%typemap(in) std::vector<type>(std::vector<type> temp) {
if (!vector_input_helper($input, &temp, PyObjAs<type>)) {
if (!PyErr_Occurred())
SWIG_Error(SWIG_TypeError, "sequence(type) expected");
return NULL;
}
$1 = temp;
}
%typemap(in) const std::vector<type>& (std::vector<type> temp),
const std::vector<type>* (std::vector<type> temp) {
if (!vector_input_helper($input, &temp, PyObjAs<type>)) {
if (!PyErr_Occurred())
SWIG_Error(SWIG_TypeError, "sequence(type) expected");
return NULL;
}
$1 = &temp;
}
%typemap(in,numinputs=0)
std::vector<type>* OUTPUT (std::vector<type> temp),
std::set<type>* OUTPUT (std::set<type> temp) {
$1 = &temp;
}
%typemap(argout)
std::vector<type>* OUTPUT,
std::set<type>* OUTPUT {
%append_output(list_output_helper($1, &py_converter));
}
%typemap(out) std::vector<type> {
$result = vector_output_helper(&$1, &py_converter);
}
%typemap(out) std::vector<type>*, const std::vector<type>& {
$result = vector_output_helper($1, &py_converter);
}
%enddef // PY_LIST_OUTPUT_TYPEMAP
PY_LIST_OUTPUT_TYPEMAP(int, PyInt_Check, PyInt_FromLong);
PY_LIST_OUTPUT_TYPEMAP(int64, SwigPyIntOrLong_Check, PyInt_FromLong);
PY_LIST_OUTPUT_TYPEMAP(double, PyFloat_Check, PyFloat_FromDouble);
// Add conversion list(tuple(int)) -> std::vector<std::vector>.
// TODO(user): see if we can also get rid of this and utilize already
// existing code.
%define PY_LIST_LIST_INPUT_TYPEMAP(type, checker)
%typemap(in) const std::vector<std::vector<type> >&
(std::vector<std::vector<type> > temp) {
if (!PyList_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Expecting a list of tuples");
SWIG_fail;
}
int len = PyList_Size($input);
int arity = -1;
if (len > 0) {
temp.resize(len);
for (size_t i = 0; i < len; ++i) {
PyObject *tuple = PyList_GetItem($input, i);
if (!PyTuple_Check(tuple) && !PyList_Check(tuple)) {
PyErr_SetString(PyExc_TypeError, "Expecting a sequence");
SWIG_fail;
}
bool is_tuple = PyTuple_Check(tuple);
int arity = is_tuple ? PyTuple_Size(tuple) : PyList_Size(tuple);
temp[i].resize(arity);
for (size_t j = 0; j < arity; ++j) {
bool success = PyObjAs<type>(is_tuple ?
PyTuple_GetItem(tuple, j) :
PyList_GetItem(tuple, j), &temp[i][j]);
if (!success) {
SWIG_fail;
}
}
}
}
$1 = &temp;
}
%typecheck(SWIG_TYPECHECK_POINTER) const std::vector<std::vector<type> >& {
if (!PyList_Check($input)) {
$1 = 0;
} else {
const int size = PyList_Size($input);
bool failed = false;
for (size_t i = 0; i < size; ++i) {
PyObject* const tuple = PyList_GetItem($input, i);
if (!PyTuple_Check(tuple) && !PyList_Check(tuple)) {
$1 = 0;
break;
} else {
const bool is_tuple = PyTuple_Check(tuple);
const int arity = is_tuple ? PyTuple_Size(tuple) : PyList_Size(tuple);
for (size_t j = 0; j < arity; ++j) {
PyObject* const entry =
is_tuple ? PyTuple_GetItem(tuple, j) : PyList_GetItem(tuple, j);
if (!checker(entry)) {
failed = true;
break;
}
}
}
if (failed) {
break;
}
}
$1 = failed ? 0 : 1;
}
}
%enddef // PY_LIST_LIST_INPUT_TYPEMAP
PY_LIST_LIST_INPUT_TYPEMAP(int, PyInt_Check);
PY_LIST_LIST_INPUT_TYPEMAP(int64, SwigPyIntOrLong_Check);
PY_LIST_LIST_INPUT_TYPEMAP(double, PyFloat_Check);