SWIG+JAVA(範囲チェック付array_class)

carrays.iが、boundary checkをしていないので、boundary checkをつけたものを作成した。
ライセンスは、carrays.iに準拠(すなわちBSDライセンス)。
ただし、C++でしか使えない。

使い方は、

%bound_array_class(struct epoll_event, epoll_event_array, epoll_event);

と、第三引数に、第一引数のJavaでの名前を追加する。

epoll_event_array test = new epoll_event_array(3);

setitem,getitemの代わりに、set,getが使える。
length()で、長さを返す。
frompointerには、第二引数にlengthが必要。

//boundarray.i is made from carrays.i
/* -----------------------------------------------------------------------------
 * See the LICENSE file for information on copyright, usage and redistribution
 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
 *
 * carrays.i
 *
 * SWIG library file containing macros that can be used to manipulate simple
 * pointers as arrays.
 * ----------------------------------------------------------------------------- */


%define %bound_array_class(TYPE,NAME,JAVATYPE)
%{
typedef TYPE NAME;
%}

%typemap(javacode)  NAME %{
  protected int length = 0;

  public $javaclassname(int nelements) {
    length=nelements;
    $javaclassname array = __new_array(nelements);

    swigCPtr = array.swigCPtr;
    swigCMemOwn=true;
  }

  public JAVATYPE get(int i) {
  	 if(i<0 || i >= length) {
	      throw new java.lang.ArrayIndexOutOfBoundsException(i);
	 }
  	 return __getitem(i);     
  }
  public void set(int i, JAVATYPE v) {
  	 if(i<0 || i >= length) {
	      throw new java.lang.ArrayIndexOutOfBoundsException(i);
	 }
  	 __setitem(i,v);     
  }

  public int length() {
  	 return length;
  }

  public static $javaclassname frompointer(JAVATYPE t, int length) {
    long cPtr = JAVATYPE.getCPtr(t);

    if (cPtr == 0) { return null; }

    $javaclassname v = new $javaclassname(cPtr, false);

    v.length = length;

    return v ;
  }

%}

%javamethodmodifiers NAME(int nelements, int dummy) "protected";
%javamethodmodifiers __new_array(int nelements) "protected";
%javamethodmodifiers __getitem(int index) "protected";
%javamethodmodifiers __setitem(int index, TYPE value) "protected";


typedef struct NAME {
  /* Put language specific enhancements here */

} NAME;

%extend NAME {

#ifdef __cplusplus

NAME(int nelements, int dummy) {
  return new TYPE[nelements];
}


NAME* __new_array(int nelements) {
  return new TYPE[nelements];
}

~NAME() {
  delete [] self;
}
#else

NAME(int nelements) {
  return (TYPE *) calloc(nelements,sizeof(TYPE));
}

~NAME() {
  free(self);
}
#endif

TYPE __getitem(int index) {
  return self[index];
}

void __setitem(int index, TYPE value) {
  self[index] = value;
}
TYPE * cast() {
  return self;
}

};


%javamethodmodifiers NAME(int nelements, int dummy) "public";
%javamethodmodifiers __new_array(int nelements) "public";
%javamethodmodifiers __getitem(int index) "public";
%javamethodmodifiers __setitem(int index, TYPE value) "public";

%types(NAME = TYPE);

%enddef