Merge branch 'fflexo-javalist'

* fflexo-javalist:
  Java std::vector minor improvement
  Fix Java container tests for change in vector constructor declaration
  Add in missing Java std::list listIterator index range checking
  Minor correction in C# std::list doNextIndex
  Add missing typedefs to Java std::vector
  Consistent destructor declarations
  Remove Java std::list::max_size
  Java std::list std::vector - test addAll and subList
  Handle length_error exceptions in Java std::vector::reserve
  Remove Java std::list::assign
  Additional add/remove methods added to Java std::list wrappers
  More efficient add implementation for Java std::list
  Java std::vector std::list: add missing exception handling
  Java std::vector std::list enhancements
  Modify std::list declarations to match the C++ standard
  Fix removing elements from std::list Java wrapper
  Improve Java std::list std::vector runtime tests and wrap std::list::clear
  Wrap std::list::empty as isEmpty in Java
  javabase typemap improvement for std::list
  Java std::list - fully qualifiy Java class name to avoid potential name ambiguity
  cosmetics
  Remove redundant code
  Java std::list rework to be consistent with std::vector wrappers
  li_std_list testcase not working for most languages
  re-enabled li_std_list test
  Switched from autobox to jboxtype per #842
  Document autobox.i
  Made the conversion from long->int for size_type mapping onto Java interfaces cleaner.
  Be consistent in semantics of %extend on std::list::iterator
  Comment on consideration of making iterator non-static.
  Java style fix: iterator->Iterator
  Moving iterator functionality into nested Java class now.
  Removed typedef from li_std_list test as it's not expected to work properly in templated code
  Added a best case workaround for std::list::size_type vs jint problem. There's a bit of commentry added around it too for clarity.
  Drop non-const reference from autobox typemap macro to be consistent.
  just use a forward declaration for C++ iterator types to fix enum errors
  Added enum to li_std_list tests
  Added li_std_list to the Java test-suit makefile
  added more comments in a few places
  Base _runme.java for li_std_list off li_std_vector_runme.java
  Expose more types from li_std_list.i
  Don't expose sort() to avoid adding dependencies on all std::list users
  Target each method specificly for setting modifiers
  Don't expose remove() method from std::list to avoid confusing it with Java's remove() in List
  - added std_list.i implemenatation that extends Java's AbstractSequentialList base class - added autobox.i that provides supporting typemaps for generics in containers
This commit is contained in:
William S Fulton 2017-07-17 07:35:13 +01:00
commit df899cfef1
9 changed files with 525 additions and 36 deletions

217
Lib/java/std_list.i Normal file
View file

@ -0,0 +1,217 @@
%include <std_common.i>
%{
#include <list>
#include <stdexcept>
%}
%fragment("SWIG_ListSize", "header", fragment="SWIG_JavaIntFromSize_t") {
SWIGINTERN jint SWIG_ListSize(size_t size) {
jint sz = SWIG_JavaIntFromSize_t(size);
if (sz == -1)
throw std::out_of_range("list size is too large to fit into a Java int");
return sz;
}
}
%javamethodmodifiers std::list::begin "private";
%javamethodmodifiers std::list::insert "private";
%javamethodmodifiers std::list::doSize "private";
%javamethodmodifiers std::list::doPreviousIndex "private";
%javamethodmodifiers std::list::doNextIndex "private";
%javamethodmodifiers std::list::doHasNext "private";
// Match Java style better:
%rename(Iterator) std::list::iterator;
%nodefaultctor std::list::iterator;
namespace std {
template <typename T> class list {
%typemap(javabase) std::list<T> "java.util.AbstractSequentialList<$typemap(jboxtype, T)>"
%proxycode %{
public $javaclassname(java.util.Collection c) {
this();
java.util.ListIterator<$typemap(jboxtype, T)> it = listIterator(0);
// Special case the "copy constructor" here to avoid lots of cross-language calls
for (Object o : c) {
it.add(($typemap(jboxtype, T))o);
}
}
public int size() {
return doSize();
}
public boolean add($typemap(jboxtype, T) value) {
addLast(value);
return true;
}
public java.util.ListIterator<$typemap(jboxtype, T)> listIterator(int index) {
return new java.util.ListIterator<$typemap(jboxtype, T)>() {
private Iterator pos;
private Iterator last;
private java.util.ListIterator<$typemap(jboxtype, T)> init(int index) {
if (index < 0 || index > $javaclassname.this.size())
throw new IndexOutOfBoundsException("Index: " + index);
pos = $javaclassname.this.begin();
pos = pos.advance_unchecked(index);
return this;
}
public void add($typemap(jboxtype, T) v) {
// Technically we can invalidate last here, but this makes more sense
last = $javaclassname.this.insert(pos, v);
}
public void set($typemap(jboxtype, T) v) {
if (null == last) {
throw new IllegalStateException();
}
last.set_unchecked(v);
}
public void remove() {
if (null == last) {
throw new IllegalStateException();
}
$javaclassname.this.remove(last);
last = null;
}
public int previousIndex() {
return $javaclassname.this.doPreviousIndex(pos);
}
public int nextIndex() {
return $javaclassname.this.doNextIndex(pos);
}
public $typemap(jboxtype, T) previous() {
if (previousIndex() < 0) {
throw new java.util.NoSuchElementException();
}
last = pos;
pos = pos.previous_unchecked();
return last.deref_unchecked();
}
public $typemap(jboxtype, T) next() {
if (!hasNext()) {
throw new java.util.NoSuchElementException();
}
last = pos;
pos = pos.next_unchecked();
return last.deref_unchecked();
}
public boolean hasPrevious() {
// This call to previousIndex() will be much slower than the hasNext() implementation, but it's simpler like this with C++ forward iterators
return previousIndex() != -1;
}
public boolean hasNext() {
return $javaclassname.this.doHasNext(pos);
}
}.init(index);
}
%}
public:
typedef size_t size_type;
typedef T value_type;
typedef T &reference;
/*
* We'd actually be better off having the nested class *not* be static in the wrapper
* output, but this doesn't actually remove the $static from the nested class still.
* (This would allow us to somewhat simplify the implementation of the ListIterator
* interface and give "natural" semantics to Java users of the C++ iterator)
*/
//%typemap(javaclassmodifiers) iterator "public class"
//%typemap(javainterfaces) iterator "java.util.ListIterator<$typemap(jboxtype, T)>"
struct iterator {
%extend {
void set_unchecked(const T &v) {
**$self = v;
}
iterator next_unchecked() const {
std::list<T>::iterator ret = *$self;
++ret;
return ret;
}
iterator previous_unchecked() const {
std::list<T>::iterator ret = *$self;
--ret;
return ret;
}
T deref_unchecked() const {
return **$self;
}
iterator advance_unchecked(size_type index) const {
std::list<T>::iterator ret = *$self;
std::advance(ret, index);
return ret;
}
}
};
list();
list(const list &other);
%rename(isEmpty) empty;
bool empty() const;
void clear();
%rename(remove) erase;
iterator erase(iterator pos);
%rename(removeLast) pop_back;
void pop_back();
%rename(removeFirst) pop_front;
void pop_front();
%rename(addLast) push_back;
void push_back(const T &value);
%rename(addFirst) push_front;
void push_front(const T &value);
iterator begin();
iterator end();
iterator insert(iterator pos, const T &value);
%extend {
%fragment("SWIG_ListSize");
list(jint count) throw (std::out_of_range) {
if (count < 0)
throw std::out_of_range("list count must be positive");
return new std::list<T>(static_cast<std::list<T>::size_type>(count));
}
list(jint count, const T &value) throw (std::out_of_range) {
if (count < 0)
throw std::out_of_range("list count must be positive");
return new std::list<T>(static_cast<std::list<T>::size_type>(count), value);
}
jint doSize() const throw (std::out_of_range) {
return SWIG_ListSize(self->size());
}
jint doPreviousIndex(const iterator &pos) const throw (std::out_of_range) {
return pos == self->begin() ? -1 : SWIG_ListSize(std::distance(self->begin(), static_cast<std::list<T>::const_iterator>(pos)));
}
jint doNextIndex(const iterator &pos) const throw (std::out_of_range) {
return pos == self->end() ? SWIG_ListSize(self->size()) : SWIG_ListSize(std::distance(self->begin(), static_cast<std::list<T>::const_iterator>(pos)));
}
bool doHasNext(const iterator &pos) const {
return pos != $self->end();
}
}
};
}

View file

@ -72,17 +72,34 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) {
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef CTYPE value_type;
typedef CTYPE &reference;
typedef CREF_TYPE const_reference;
typedef CTYPE *pointer;
typedef CTYPE const *const_pointer;
vector();
vector(size_type n);
vector(const vector &other);
size_type capacity() const;
void reserve(size_type n);
void reserve(size_type n) throw (std::length_error);
%rename(isEmpty) empty;
bool empty() const;
void clear();
%extend {
%fragment("SWIG_VectorSize");
vector(jint count) throw (std::out_of_range) {
if (count < 0)
throw std::out_of_range("vector count must be positive");
return new std::vector< CTYPE >(static_cast<std::vector< CTYPE >::size_type>(count));
}
vector(jint count, const CTYPE &value) throw (std::out_of_range) {
if (count < 0)
throw std::out_of_range("vector count must be positive");
return new std::vector< CTYPE >(static_cast<std::vector< CTYPE >::size_type>(count), value);
}
jint doSize() const throw (std::out_of_range) {
return SWIG_VectorSize(self->size());
}
@ -92,7 +109,7 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) {
}
void doAdd(jint index, const value_type& value) throw (std::out_of_range) {
const jint size = SWIG_VectorSize(self->size());
const jint size = static_cast<std::vector< CTYPE >::size_type>(self->size());
if (0 <= index && index <= size) {
self->insert(self->begin() + index, value);
} else {
@ -101,7 +118,7 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) {
}
value_type doRemove(jint index) throw (std::out_of_range) {
const jint size = SWIG_VectorSize(self->size());
const jint size = static_cast<std::vector< CTYPE >::size_type>(self->size());
if (0 <= index && index < size) {
CTYPE const old_value = (*self)[index];
self->erase(self->begin() + index);
@ -112,7 +129,7 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) {
}
CREF_TYPE doGet(jint index) throw (std::out_of_range) {
const jint size = SWIG_VectorSize(self->size());
const jint size = static_cast<std::vector< CTYPE >::size_type>(self->size());
if (index >= 0 && index < size)
return (*self)[index];
else
@ -120,7 +137,7 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) {
}
value_type doSet(jint index, const value_type& value) throw (std::out_of_range) {
const jint size = SWIG_VectorSize(self->size());
const jint size = static_cast<std::vector< CTYPE >::size_type>(self->size());
if (index >= 0 && index < size) {
CTYPE const old_value = (*self)[index];
(*self)[index] = value;
@ -131,7 +148,7 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) {
}
void doRemoveRange(jint fromIndex, jint toIndex) throw (std::out_of_range) {
const jint size = SWIG_VectorSize(self->size());
const jint size = static_cast<std::vector< CTYPE >::size_type>(self->size());
if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) {
self->erase(self->begin() + fromIndex, self->begin() + toIndex);
} else {