Add generic approach in fragments for converting size_t to Java int
This commit is contained in:
parent
be63f73e33
commit
5eb9f735da
2 changed files with 35 additions and 38 deletions
|
|
@ -54,6 +54,14 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%fragment("SWIG_JavaIntFromSize_t", "header") {
|
||||||
|
/* Check for overflow converting to Java int (always signed 32-bit) from (unsigned variable-bit) size_t */
|
||||||
|
SWIGINTERN jint SWIG_JavaIntFromSize_t(size_t size) {
|
||||||
|
static const jint JINT_MAX = 0x7FFFFFFF;
|
||||||
|
return (size > (size_t)JINT_MAX) ? -1 : (jint)size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Primitive types */
|
/* Primitive types */
|
||||||
%typemap(jni) bool, const bool & "jboolean"
|
%typemap(jni) bool, const bool & "jboolean"
|
||||||
%typemap(jni) char, const char & "jchar"
|
%typemap(jni) char, const char & "jchar"
|
||||||
|
|
|
||||||
|
|
@ -7,29 +7,17 @@
|
||||||
%{
|
%{
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
// C++ allows to have up to 2^64-1 items in a vector on 64 bit machines and
|
|
||||||
// 2^32-1 even on 32 bit ones, but in Java size() must return a value of type
|
|
||||||
// "int" which is limited to signed 32 bit values, i.e. 2^31-1, and there
|
|
||||||
// doesn't seem to be any way to represent bigger vectors there.
|
|
||||||
//
|
|
||||||
// The only thing we can do is to at least detect such situation and throw an
|
|
||||||
// exception instead of silently returning the wrong size in this case and we
|
|
||||||
// use this helper to convert size_t values to int, instead of just casting
|
|
||||||
// them, in order to achieve this.
|
|
||||||
namespace {
|
|
||||||
int size_as_int(std::size_t sz) {
|
|
||||||
if (sz > static_cast<std::size_t>(INT_MAX)) {
|
|
||||||
throw std::out_of_range("vector size is too big to be representable as int");
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<int>(sz);
|
|
||||||
}
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%fragment("SWIG_VectorSize", "header", fragment="SWIG_JavaIntFromSize_t") {
|
||||||
|
SWIGINTERN jint SWIG_VectorSize(size_t size) {
|
||||||
|
jint sz = SWIG_JavaIntFromSize_t(size);
|
||||||
|
if (sz == -1)
|
||||||
|
throw std::out_of_range("vector size is too large to fit into a Java int");
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
%define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CTYPE, CREF_TYPE)
|
%define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CTYPE, CREF_TYPE)
|
||||||
%typemap(javabase) std::vector< CTYPE > "java.util.AbstractList<$typemap(jboxtype, CTYPE)>"
|
%typemap(javabase) std::vector< CTYPE > "java.util.AbstractList<$typemap(jboxtype, CTYPE)>"
|
||||||
%typemap(javainterfaces) std::vector< CTYPE > "java.util.RandomAccess"
|
%typemap(javainterfaces) std::vector< CTYPE > "java.util.RandomAccess"
|
||||||
|
|
@ -94,16 +82,17 @@ int size_as_int(std::size_t sz) {
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
void clear();
|
void clear();
|
||||||
%extend {
|
%extend {
|
||||||
int doSize() const {
|
%fragment("SWIG_VectorSize");
|
||||||
return size_as_int(self->size());
|
jint doSize() const throw (std::out_of_range) {
|
||||||
|
return SWIG_VectorSize(self->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void doAdd(const value_type& value) {
|
void doAdd(const value_type& value) {
|
||||||
self->push_back(value);
|
self->push_back(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void doAdd(int index, const value_type& value) throw (std::out_of_range) {
|
void doAdd(jint index, const value_type& value) throw (std::out_of_range) {
|
||||||
const int size = size_as_int(self->size());
|
const jint size = SWIG_VectorSize(self->size());
|
||||||
if (0 <= index && index <= size) {
|
if (0 <= index && index <= size) {
|
||||||
self->insert(self->begin() + index, value);
|
self->insert(self->begin() + index, value);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -111,8 +100,8 @@ int size_as_int(std::size_t sz) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
value_type doRemove(int index) throw (std::out_of_range) {
|
value_type doRemove(jint index) throw (std::out_of_range) {
|
||||||
const int size = size_as_int(self->size());
|
const jint size = SWIG_VectorSize(self->size());
|
||||||
if (0 <= index && index < size) {
|
if (0 <= index && index < size) {
|
||||||
CTYPE const old_value = (*self)[index];
|
CTYPE const old_value = (*self)[index];
|
||||||
self->erase(self->begin() + index);
|
self->erase(self->begin() + index);
|
||||||
|
|
@ -122,27 +111,27 @@ int size_as_int(std::size_t sz) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CREF_TYPE doGet(int i) throw (std::out_of_range) {
|
CREF_TYPE doGet(jint index) throw (std::out_of_range) {
|
||||||
const int size = size_as_int(self->size());
|
const jint size = SWIG_VectorSize(self->size());
|
||||||
if (i>=0 && i<size)
|
if (index >= 0 && index < size)
|
||||||
return (*self)[i];
|
return (*self)[index];
|
||||||
else
|
else
|
||||||
throw std::out_of_range("vector index out of range");
|
throw std::out_of_range("vector index out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
value_type doSet(int i, const value_type& value) throw (std::out_of_range) {
|
value_type doSet(jint index, const value_type& value) throw (std::out_of_range) {
|
||||||
const int size = size_as_int(self->size());
|
const jint size = SWIG_VectorSize(self->size());
|
||||||
if (i>=0 && i<size) {
|
if (index >= 0 && index < size) {
|
||||||
CTYPE const old_value = (*self)[i];
|
CTYPE const old_value = (*self)[index];
|
||||||
(*self)[i] = value;
|
(*self)[index] = value;
|
||||||
return old_value;
|
return old_value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw std::out_of_range("vector index out of range");
|
throw std::out_of_range("vector index out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
void doRemoveRange(int fromIndex, int toIndex) throw (std::out_of_range) {
|
void doRemoveRange(jint fromIndex, jint toIndex) throw (std::out_of_range) {
|
||||||
const int size = size_as_int(self->size());
|
const jint size = SWIG_VectorSize(self->size());
|
||||||
if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) {
|
if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) {
|
||||||
self->erase(self->begin() + fromIndex, self->begin() + toIndex);
|
self->erase(self->begin() + fromIndex, self->begin() + toIndex);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue