diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index 6c745aa23..fee33f8c2 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -7,6 +7,27 @@ %{ #include #include +#include + +// 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(INT_MAX)) { + throw std::out_of_range("vector size is too big to be representable as int"); + } + + return static_cast(sz); +} +} // anonymous namespace + %} %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CTYPE, CREF_TYPE) @@ -55,6 +76,10 @@ modCount++; doRemoveRange(fromIndex, toIndex); } + + public int size() { + return doSize(); + } %} public: @@ -63,21 +88,22 @@ typedef CREF_TYPE const_reference; vector(); vector(size_type n); - // Note that it returns int, and not size_type, for compatibility with - // the signature of size() in Java interface. - int size() const; size_type capacity() const; void reserve(size_type n); %rename(isEmpty) empty; bool empty() const; void clear(); %extend { + int doSize() const { + return size_as_int(self->size()); + } + void doAdd(const value_type& value) { self->push_back(value); } void doAdd(int index, const value_type& value) throw (std::out_of_range) { - const int size = int(self->size()); + const int size = size_as_int(self->size()); if (0 <= index && index <= size) { self->insert(self->begin() + index, value); } else { @@ -85,7 +111,7 @@ } } value_type doRemove(int index) throw (std::out_of_range) { - const int size = int(self->size()); + const int size = size_as_int(self->size()); if (0 <= index && index < size) { CTYPE const old_value = (*self)[index]; self->erase(self->begin() + index); @@ -95,14 +121,14 @@ } } CREF_TYPE doGet(int i) throw (std::out_of_range) { - int size = int(self->size()); + const int size = size_as_int(self->size()); if (i>=0 && isize()); + const int size = size_as_int(self->size()); if (i>=0 && isize()); + const int size = size_as_int(self->size()); if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) { self->erase(self->begin() + fromIndex, self->begin() + toIndex); } else {