#include<stdio.h>
#include<hdf5.h>
#include<HE5_HdfEosDef.h>
#include "ruby.h"
#include "narray.h"
#include<string.h>

/* for compatibility with ruby 1.6 */
#ifndef RARRAY_PTR
#define RARRAY_PTR(a) (RARRAY(a)->ptr)
#endif
#ifndef RARRAY_LEN
#define RARRAY_LEN(a) (RARRAY(a)->len)
#endif
#ifndef RSTRING_PTR
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
#endif
#ifndef SafeStringValue
#define SafeStringValue(s) Check_SafeStr(s)
#endif

extern int   check_numbertype(char *);
extern int   change_numbertype(char *);
extern int   change_entrycode(char *);
extern int   change_groupcode(char *);
extern int   change_subsetmode(char *);
extern int   change_compmethod(char *);
extern void  HE5Wrap_make_NArray1D_or_str(int, size_t, VALUE *, void **);
extern void  HE5Wrap_store_NArray1D_or_str(int, VALUE , void **);
extern void  change_chartype(hid_t, char *);
extern void  change_comptype(hid_t, char *);

extern int     *hdfeos5_obj2cintary(VALUE);
extern long    *hdfeos5_obj2clongary(VALUE);
extern float   *hdfeos5_obj2cfloatary(VALUE);
extern signed long long   *hdfeos5_obj2csint64ary(VALUE);
extern unsigned long long *hdfeos5_obj2cunsint64ary(VALUE);

extern VALUE hdfeos5_ccharary2obj(char *, int, int);
extern VALUE hdfeos5_cintary2obj(int *, int, int, int *);
extern VALUE hdfeos5_clongary2obj(long *, int, int, int *);
extern VALUE hdfeos5_cunsint64ary2obj(unsigned long long *, int, int, int *);

extern void hdfeos5_freecintary(int *);
extern void hdfeos5_freeclongary(long *);
extern void hdfeos5_freecfloatary(float *);
extern void hdfeos5_freecsint64ary(signed long long *);
extern void hdfeos5_freecunsint64ary(unsigned long long *);

VALUE hdfeos5_swwritefield_char(VALUE, VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_swwritefield_short(VALUE, VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_swwritefield_int(VALUE, VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_swwritefield_long(VALUE, VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_swwritefield_float(VALUE, VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_swwritefield_double(VALUE, VALUE, VALUE, VALUE, VALUE);

VALUE hdfeos5_swreadfield_char(VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_swreadfield_short(VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_swreadfield_int(VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_swreadfield_long(VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_swreadfield_float(VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_swreadfield_double(VALUE, VALUE, VALUE, VALUE);

#define Cbyte_to_NArray(v, rank, shape, up) \
{ \
    struct NARRAY *ary; \
    v = na_make_object(NA_BYTE, rank, shape, cNArray); \
    GetNArray(v,ary); \
    up = (unsigned char *)ary->ptr; \
}
#define Cshort_to_NArray(v, rank, shape, lp) \
{ \
    struct NARRAY *ary; \
    v = na_make_object(NA_SINT, rank, shape, cNArray); \
    GetNArray(v, ary); \
    lp = (short *)ary->ptr; \
}
#define Cint_to_NArray(v, rank, shape, lp) \
{ \
    struct NARRAY *ary; \
    v = na_make_object(NA_LINT, rank, shape, cNArray); \
    GetNArray(v, ary); \
    lp = (int *)ary->ptr; \
}
#define Clong_to_NArray(v, rank, shape, lp) \
{ \
    struct NARRAY *ary; \
    v = na_make_object(NA_LINT, rank, shape, cNArray); \
    GetNArray(v, ary); \
    lp = (long *)ary->ptr; \
}
#define Cfloat_to_NArray(v, rank, shape, fp) \
{ \
    struct NARRAY *ary; \
    v = na_make_object(NA_SFLOAT, rank, shape, cNArray); \
    GetNArray(v, ary); \
    fp = (float *)ary->ptr; \
}
#define Cdouble_to_NArray(v, rank, shape, dp); \
{ \
    struct NARRAY *ary; \
    v = na_make_object(NA_DFLOAT, rank, shape, cNArray); \
    GetNArray(v, ary); \
    dp = (double *)ary->ptr; \
}

/* Array or NArray to pointer and length (with no new allocation) */
#define Array_to_Cfloat_len_shape(obj, ptr, len, shape) \
{ \
    struct NARRAY *na; \
    obj = na_cast_object(obj, NA_SFLOAT); \
    GetNArray(obj, na); \
    ptr = (float *) NA_PTR(na,0); \
    len = na->total; \
    shape = na->shape; \
}
#define Array_to_Cdouble_len_shape(obj, ptr, len, shape) \
{ \
    struct NARRAY *na; \
    obj = na_cast_object(obj, NA_DFLOAT); \
    GetNArray(obj, na); \
    ptr = (double *) NA_PTR(na,0); \
    len = na->total; \
    shape = na->shape; \
}
#define Array_to_Cbyte_len_shape(obj, ptr, len, shape) \
{ \
    struct NARRAY *na; \
    obj = na_cast_object(obj, NA_BYTE); \
    GetNArray(obj, na); \
    ptr = (u_int8_t *) NA_PTR(na,0); \
    len = na->total; \
    shape = na->shape; \
}
#define Array_to_Cshort_len_shape(obj, ptr, len, shape) \
{ \
    struct NARRAY *na; \
    obj = na_cast_object(obj, NA_SINT); \
    GetNArray(obj, na); \
    ptr = (int16_t *) NA_PTR(na,0); \
    len = na->total; \
    shape = na->shape; \
}
#define Array_to_Cint_len_shape(obj, ptr, len, shape) \
{ \
    struct NARRAY *na; \
    obj = na_cast_object(obj, NA_LINT); \
    GetNArray(obj, na); \
    ptr = (int32_t *) NA_PTR(na,0); \
    len = na->total; \
    shape = na->shape; \
}
#define Array_to_Clong_len_shape(obj, ptr, len, shape) \
{ \
    struct NARRAY *na; \
    obj = na_cast_object(obj, NA_LINT); \
    GetNArray(obj, na); \
    ptr = (long *) NA_PTR(na,0); \
    len = na->total; \
    shape = na->shape; \
}

#define maxcharsize  3000

static VALUE rb_eHE5Error;
static VALUE mNumRu = 0;
static VALUE cHE5;
static VALUE cHE5Sw;
static VALUE cHE5SwField;

struct HE5{
  hid_t fid;
  char *name;
  int closed;
};

struct HE5Sw{
  hid_t swid;
  char *name;
  char *fname;
  hid_t fid;
  VALUE file;
};

struct HE5SwField{
  char *name;
  hid_t swid;
  VALUE swath;
};

static struct HE5Sw *
HE5Sw_init(hid_t swid, char *name, hid_t fid, VALUE file)
{
  struct HE5Sw *HE5Swath;
  HE5Swath=xmalloc(sizeof(struct HE5Sw));
  HE5Swath->swid=swid;
  HE5Swath->fid=fid;
  HE5Swath->name=xmalloc((strlen(name)+1)*sizeof(char));
  strcpy(HE5Swath->name,name);
  HE5Swath->file=file;
  return(HE5Swath);
}

static struct HE5SwField *
HE5SwField_init(char *name,hid_t swid,VALUE swath)
{
  struct HE5SwField *HE5Sw_Field;
  HE5Sw_Field=xmalloc(sizeof(struct HE5SwField));
  HE5Sw_Field->swid=swid;
  HE5Sw_Field->swath=swath;
  HE5Sw_Field->name=xmalloc((strlen(name)+1)*sizeof(char));
  strcpy(HE5Sw_Field->name,name);
  return(HE5Sw_Field);
}


void
HE5Sw_free(struct HE5Sw *HE5_Swath)
{
  free(HE5_Swath->name);
  free(HE5_Swath);
}

void
HE5SwField_free(struct HE5SwField *HE5Sw_Field)
{
  free(HE5Sw_Field->name);
  free(HE5Sw_Field);
}

static void
he5swfield_mark_obj(struct HE5SwField *he5fld)
{
    VALUE ptr;

    ptr = he5fld->swath;
    rb_gc_mark(ptr);
}

static void
he5sw_mark_obj(struct HE5Sw *he5sw)
{
    VALUE ptr;

    ptr = he5sw->file;
    rb_gc_mark(ptr);
}

VALUE
HE5Sw_clone(VALUE swath)
{
    VALUE clone;
    struct HE5Sw *he5sw1, *he5sw2;

    Data_Get_Struct(swath, struct HE5Sw, he5sw1);
    he5sw2 = HE5Sw_init(he5sw1->swid, he5sw1->name, he5sw1->fid, he5sw1->file);
    clone = Data_Wrap_Struct(cHE5Sw, he5sw_mark_obj, HE5Sw_free, he5sw2);
    CLONESETUP(clone, swath);
    return clone;
}

VALUE
HE5SwField_clone(VALUE field)
{
    VALUE clone;
    struct HE5SwField *he5fld1, *he5fld2;

    Data_Get_Struct(field, struct HE5SwField, he5fld1);
    he5fld2 = HE5SwField_init(he5fld1->name, he5fld1->swid, he5fld1->swath);
    clone = Data_Wrap_Struct(cHE5SwField, he5swfield_mark_obj, HE5SwField_free, he5fld2);
    CLONESETUP(clone, field);
    return clone;
}

long
swnentries_count(hid_t i_swathid, VALUE entrycode)
{
    char *c_entrycode;
    long o_strbufsize=FAIL;
    long o_count;

    Check_Type(entrycode,T_STRING);
    SafeStringValue(entrycode);
    c_entrycode = RSTRING_PTR(entrycode);

    o_count = HE5_SWnentries(i_swathid, change_entrycode(c_entrycode), &o_strbufsize);
    if (o_count < 0 ) return  Qfalse ;
    return(o_count);
}

long
swnentries_strbuf(hid_t i_swathid, VALUE entrycode)
{
    char *c_entrycode;
    long o_strbufsize=FAIL;
    long o_count;

    Check_Type(entrycode,T_STRING);
    SafeStringValue(entrycode);
    c_entrycode = RSTRING_PTR(entrycode);

    o_count = HE5_SWnentries(i_swathid, change_entrycode(c_entrycode), &o_strbufsize);
    if (o_count < 0 ) return  Qfalse ;
    return(o_strbufsize);
}

VALUE
hdfeos5_swcreate(VALUE mod, VALUE swathname)
{
    hid_t i_fid;
    hid_t swid;
    char* i_swathname;
    struct HE5 *he5file;
    struct HE5Sw *he5swath;
    char*  file;
    VALUE Swath;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5, he5file);
    i_fid=he5file->fid;
    file=he5file->name;

    Check_Type(swathname,T_STRING);
    SafeStringValue(swathname);
    i_swathname = RSTRING_PTR(swathname);

    swid = HE5_SWcreate(i_fid, i_swathname);
    if(swid == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    he5swath = HE5Sw_init(swid, i_swathname, i_fid, mod);
    Swath = Data_Wrap_Struct(cHE5Sw, he5sw_mark_obj, HE5Sw_free, he5swath);
    return(Swath);
}

VALUE
hdfeos5_swattach(VALUE mod, VALUE swathname)
{
    hid_t i_fid;
    hid_t swid;
    char *i_swathname, *i_fname;
    struct HE5 *he5file;
    struct HE5Sw *he5swath;
    VALUE Swath;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5, he5file);
    i_fid=he5file->fid;
    i_fname=he5file->name;

    Check_Type(swathname,T_STRING);
    SafeStringValue(swathname);
    i_swathname = RSTRING_PTR(swathname);

    swid = HE5_SWattach(i_fid, i_swathname);
    if(swid == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    he5swath = HE5Sw_init(swid, i_swathname, i_fid, mod);
    Swath = Data_Wrap_Struct(cHE5Sw, he5sw_mark_obj, HE5Sw_free, he5swath);
    return(Swath);
}

VALUE
hdfeos5_swdefdim(VALUE mod, VALUE dimname, VALUE dim)
{
    hid_t i_swathid;
    char *i_dimname;
    unsigned long long i_dim;
    herr_t o_rtn_val;
    VALUE rtn_val;
    struct HE5Sw *he5swath;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;
    Check_Type(dimname,T_STRING);
    SafeStringValue(dimname);
    Check_Type(dim,T_FIXNUM);
    i_dimname = RSTRING_PTR(dimname);
    i_dim = NUM2LONG(dim);
    o_rtn_val = HE5_SWdefdim(i_swathid, i_dimname, i_dim);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    return(dimname);
}

VALUE
hdfeos5_swdiminfo(VALUE mod, VALUE dimname)
{
    hid_t i_swathid;
    char *i_dimname;
    unsigned long long o_ndim;
    VALUE ndim;
    struct HE5Sw *he5swath;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(dimname,T_STRING);
    SafeStringValue(dimname);
    i_dimname = RSTRING_PTR(dimname);

    o_ndim = HE5_SWdiminfo(i_swathid, i_dimname);
    ndim = LONG2NUM(o_ndim);
    return(ndim);
}

VALUE
hdfeos5_swmapinfo(VALUE mod, VALUE geodim, VALUE datadim)
{
    hid_t i_swathid;
    char *i_geodim;
    char *i_datadim;
    long o_offset;
    long o_increment;
    herr_t o_rtn_val;
    VALUE offset;
    VALUE increment;
    struct HE5Sw *he5swath;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(geodim,T_STRING);
    SafeStringValue(geodim);
    Check_Type(datadim,T_STRING);
    SafeStringValue(datadim);

    i_geodim = RSTRING_PTR(geodim);
    i_datadim = RSTRING_PTR(datadim);

    o_rtn_val = HE5_SWmapinfo(i_swathid, i_geodim, i_datadim, &o_offset, &o_increment);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");

    offset = INT2NUM(o_offset);
    increment = INT2NUM(o_increment);

    return rb_ary_new3(2, offset, increment);
}

VALUE
hdfeos5_swidxmapinfo(VALUE mod, VALUE geodim, VALUE datadim)
{
    hid_t i_swathid;
    char *i_geodim;
    char *i_datadim;
    long *i_index;
    int size;
    unsigned long long o_gsize;
    VALUE gsize;
    VALUE index;
    VALUE dimsize;
    struct HE5Sw *he5swath;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(geodim,T_STRING);
    SafeStringValue(geodim);
    Check_Type(datadim,T_STRING);
    SafeStringValue(datadim);
    dimsize = hdfeos5_swdiminfo(mod, geodim);
    size    = NUM2INT(dimsize);

    i_geodim = RSTRING_PTR(geodim);
    i_datadim = RSTRING_PTR(datadim);
    i_index =  ALLOCA_N(long,(size+1));

    o_gsize = HE5_SWidxmapinfo(i_swathid, i_geodim, i_datadim, i_index);
    gsize = INT2NUM(o_gsize);
    index = hdfeos5_clongary2obj(i_index, size, 1, &size);

    return rb_ary_new3(2, gsize, index);
}

VALUE
hdfeos5_swcompinfo(VALUE mod)
{
    hid_t i_swathid;
    char *i_fldname;
    int o_compcode;
    int ncomplevel=32;  /* Set compression level: value 0,1,2,3,4,5,6,7,8,9,10,16, or 32 */
    void *o_compparm;
    herr_t o_rtn_val;
    char str[maxcharsize];
    VALUE rtn_val;
    VALUE compcode;
    VALUE compparm;
    struct HE5SwField *he5field;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    HE5Wrap_make_NArray1D_or_str(HE5T_NATIVE_INT, ncomplevel, &compparm, &o_compparm); 
    o_rtn_val = HE5_SWcompinfo(i_swathid, i_fldname, &o_compcode, o_compparm);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    change_comptype(o_compcode,str);
    compcode =rb_str_new(str,strlen(str));

    return rb_ary_new3(2, compcode, compparm);
}

VALUE
hdfeos5_swfieldinfo(VALUE mod)
{
    hid_t i_swathid;
    char *i_fldname;
    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[maxcharsize];
    char o_dimlist[maxcharsize];
    char str[maxcharsize];
    herr_t o_rtn_val;
    VALUE rank;
    VALUE dims;
    VALUE ntype;
    VALUE dimlist;
    struct HE5SwField *he5field;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    o_rtn_val = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, o_dimlist, NULL);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    rank = INT2NUM(i_rank);
    dims = hdfeos5_cunsint64ary2obj(hs_dims, i_rank, 1, &i_rank);
    change_chartype(i_ntype, str);
    ntype =rb_str_new(str,strlen(str));
    dimlist = rb_str_new(o_dimlist,strlen(o_dimlist));

    return rb_ary_new3(4, rank, dims, ntype, dimlist);
}

VALUE
hdfeos5_swchunkinfo(VALUE mod, VALUE fldname)
{
    hid_t i_swathid;
    char *i_fldname;
    int o_chunk_rank;
    unsigned long long *o_chunk_dim;
    herr_t o_rtn_val;
    VALUE chunk_rank;
    VALUE chunk_dims;
    struct HE5Sw *he5swath;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;
    Check_Type(fldname,T_STRING);
    SafeStringValue(fldname);
    i_fldname = RSTRING_PTR(fldname);

    o_rtn_val = HE5_SWchunkinfo(i_swathid, i_fldname, &o_chunk_rank, NULL);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    o_chunk_dim = ALLOCA_N(unsigned long long, (o_chunk_rank + 1));

    o_rtn_val = HE5_SWchunkinfo(i_swathid, i_fldname, &o_chunk_rank, o_chunk_dim);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    chunk_rank = INT2NUM(o_chunk_rank);
    chunk_dims = hdfeos5_cunsint64ary2obj(o_chunk_dim, o_chunk_rank, 1, &o_chunk_rank);

    return rb_ary_new3(2, chunk_rank, chunk_dims);
}

VALUE
hdfeos5_swdefdimmap(VALUE mod, VALUE geodim, VALUE datadim, VALUE offset, VALUE increment)
{
    hid_t i_swathid;
    char *i_geodim;
    char *i_datadim;
    unsigned long long i_offset;
    unsigned long long i_increment;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(geodim,T_STRING);
    SafeStringValue(geodim);
    Check_Type(datadim,T_STRING);
    SafeStringValue(datadim);
    Check_Type(offset,T_FIXNUM);
    Check_Type(increment,T_FIXNUM);

    i_geodim = RSTRING_PTR(geodim);
    i_datadim = RSTRING_PTR(datadim);
    i_offset = NUM2LONG(offset);
    i_increment = NUM2LONG(increment);

    o_rtn_val = HE5_SWdefdimmap(i_swathid, i_geodim, i_datadim, i_offset, i_increment);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    return(rtn_val);
}

VALUE
hdfeos5_swdefidxmap(VALUE mod, VALUE geodim, VALUE datadim, VALUE index)
{
    hid_t i_swathid;
    char *i_geodim;
    char *i_datadim;
    long *i_index;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(geodim,T_STRING);
    SafeStringValue(geodim);
    Check_Type(datadim,T_STRING);
    SafeStringValue(datadim);
    if ((TYPE(index) == T_BIGNUM) || (TYPE(index) == T_FIXNUM)) {
      index = rb_Array(index);
    }

    i_geodim = RSTRING_PTR(geodim);
    i_datadim = RSTRING_PTR(datadim);
    i_index =(long*)hdfeos5_obj2clongary(index);

    o_rtn_val = HE5_SWdefidxmap(i_swathid, i_geodim, i_datadim, i_index);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freeclongary(i_index);
    return(rtn_val);
}

VALUE
hdfeos5_swdefchunk(VALUE mod, VALUE rank, VALUE dim)
{
    hid_t i_swathid;
    int i_rank;
    unsigned long long *i_dim;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(rank,T_FIXNUM);
    i_rank = NUM2INT(rank);
    if ((TYPE(dim) == T_BIGNUM) || (TYPE(dim) == T_FIXNUM)) {
      dim = rb_Array(dim);
    }
    i_dim = hdfeos5_obj2cunsint64ary(dim);

    o_rtn_val = HE5_SWdefchunk(i_swathid, i_rank, i_dim);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecunsint64ary(i_dim);
    return(rtn_val);
}

VALUE
hdfeos5_swdefcomp(VALUE mod, VALUE compcode, VALUE compparm)
{
    hid_t i_swathid;
    int i_compcode;
    int *i_compparm;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(compcode,T_STRING);
    SafeStringValue(compcode);
    if ((TYPE(compparm) == T_BIGNUM) || (TYPE(compparm) == T_FIXNUM)) {
      compparm = rb_Array(compparm);
    }
    i_compcode = change_compmethod(RSTRING_PTR(compcode));
    i_compparm = hdfeos5_obj2cintary(compparm);

    o_rtn_val = HE5_SWdefcomp(i_swathid, i_compcode, i_compparm);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecintary(i_compparm);
    return(rtn_val);
}

VALUE
hdfeos5_swdefcomchunk(VALUE mod, VALUE compcode, VALUE compparm, VALUE rank, VALUE dim)
{
    hid_t i_swathid;
    int i_compcode;
    int *i_compparm;
    int i_rank;
    unsigned long long *i_dim;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(compcode,T_STRING);
    SafeStringValue(compcode);
    if ((TYPE(compparm) == T_BIGNUM) || (TYPE(compparm) == T_FIXNUM)) {
      compparm = rb_Array(compparm);
    }
    i_compcode = change_compmethod(RSTRING_PTR(compcode));
    i_compparm = hdfeos5_obj2cintary(compparm);

    Check_Type(rank,T_FIXNUM);
    i_rank = NUM2INT(rank);
    if ((TYPE(dim) == T_BIGNUM) || (TYPE(dim) == T_FIXNUM)) {
      dim = rb_Array(dim);
    }
    i_dim = hdfeos5_obj2cunsint64ary(dim);

    o_rtn_val = HE5_SWdefcomchunk(i_swathid, i_compcode, i_compparm, i_rank, i_dim);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecintary(i_compparm);
    hdfeos5_freecunsint64ary(i_dim);
    return(rtn_val);
}

VALUE
hdfeos5_swdefgeofield(VALUE file, VALUE fieldname, VALUE dimlist, VALUE maxdimlist, VALUE numbertype, VALUE merge)
{
    hid_t i_swathid;
    char *i_fieldname;
    char *i_dimlist;
    char *i_maxdimlist;
    hid_t i_numbertype;
    int i_merge;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5SwField *he5field;
    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(file, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fieldname,T_STRING);
    SafeStringValue(fieldname);
    Check_Type(dimlist,T_STRING);
    SafeStringValue(dimlist);
    Check_Type(maxdimlist,T_STRING);
    SafeStringValue(maxdimlist);
    Check_Type(numbertype,T_STRING);
    SafeStringValue(numbertype);
    Check_Type(merge,T_FIXNUM);

    i_fieldname = RSTRING_PTR(fieldname);
    i_dimlist = RSTRING_PTR(dimlist);
    i_maxdimlist = RSTRING_PTR(maxdimlist);
    i_numbertype = change_numbertype(RSTRING_PTR(numbertype));
    i_merge = NUM2INT(merge);

    if(strcmp(i_maxdimlist,"NULL")==0)  i_maxdimlist = NULL;
    o_rtn_val = HE5_SWdefgeofield(i_swathid, i_fieldname, i_dimlist, i_maxdimlist, i_numbertype, i_merge);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;

    he5field = HE5SwField_init(i_fieldname, i_swathid, file);
    return(Data_Wrap_Struct(cHE5SwField, he5swfield_mark_obj, HE5SwField_free, he5field));
}

VALUE
hdfeos5_swdefdatafield(VALUE file, VALUE fieldname, VALUE dimlist, VALUE maxdimlist, VALUE numbertype, VALUE merge)
{
    hid_t i_swathid;
    char *i_fieldname;
    char *i_dimlist;
    char *i_maxdimlist;
    hid_t i_numbertype;
    int i_merge;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5SwField *he5field;
    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(file, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fieldname,T_STRING);
    SafeStringValue(fieldname);
    Check_Type(dimlist,T_STRING);
    SafeStringValue(dimlist);
    Check_Type(maxdimlist,T_STRING);
    SafeStringValue(maxdimlist);
    Check_Type(numbertype,T_STRING);
    SafeStringValue(numbertype);
    Check_Type(merge,T_FIXNUM);

    i_fieldname = RSTRING_PTR(fieldname);
    i_dimlist = RSTRING_PTR(dimlist);
    i_maxdimlist = RSTRING_PTR(maxdimlist);
    i_numbertype = change_numbertype(RSTRING_PTR(numbertype));
    i_merge = NUM2INT(merge);

    if(strcmp(i_maxdimlist,"NULL")==0)  i_maxdimlist = NULL;
    o_rtn_val = HE5_SWdefdatafield(i_swathid, i_fieldname, i_dimlist, i_maxdimlist, i_numbertype, i_merge);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;

    he5field = HE5SwField_init(i_fieldname, i_swathid, file);
    return(Data_Wrap_Struct(cHE5SwField, he5swfield_mark_obj, HE5SwField_free, he5field));
}

VALUE
hdfeos5_swwritedatameta(VALUE mod, VALUE dimlist, VALUE mvalue)
{
    hid_t i_swathid;
    char *i_fieldname;
    char *i_dimlist;
    hid_t i_mvalue;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fieldname=he5field->name;
    i_swathid=he5field->swid;

    Check_Type(dimlist,T_STRING);
    SafeStringValue(dimlist);
    Check_Type(mvalue,T_FIXNUM);

    i_dimlist = RSTRING_PTR(dimlist);
    i_mvalue = NUM2INT(mvalue);

    o_rtn_val = HE5_SWwritedatameta(i_swathid, i_fieldname, i_dimlist, i_mvalue);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    return(rtn_val);

}

VALUE
hdfeos5_swwritegeometa(VALUE mod, VALUE dimlist, VALUE mvalue)
{
    hid_t i_swathid;
    char *i_fieldname;
    char *i_dimlist;
    hid_t i_mvalue;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fieldname=he5field->name;
    i_swathid=he5field->swid;

    Check_Type(dimlist,T_STRING);
    SafeStringValue(dimlist);
    Check_Type(mvalue,T_FIXNUM);

    i_dimlist = RSTRING_PTR(dimlist);
    i_mvalue = NUM2INT(mvalue);

    o_rtn_val = HE5_SWwritegeometa(i_swathid, i_fieldname, i_dimlist, i_mvalue);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    return(rtn_val);
}

VALUE
hdfeos5_swwriteattr(VALUE mod, VALUE attrname, VALUE numbertype, VALUE count, VALUE datbuf)
{
    hid_t i_swathid;
    char *i_attrname;
    hid_t i_numbertype;
    hid_t i_numbertypechk;
    unsigned long long *i_count;
    void *i_datbuf;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    Check_Type(numbertype,T_STRING);
    SafeStringValue(numbertype);
    count = rb_Array(count);

    i_attrname = RSTRING_PTR(attrname);
    i_numbertype    = change_numbertype(RSTRING_PTR(numbertype));
    i_numbertypechk = check_numbertype(RSTRING_PTR(numbertype));
    i_count = hdfeos5_obj2cunsint64ary(count);

    HE5Wrap_store_NArray1D_or_str(i_numbertypechk, datbuf, &i_datbuf); 
    o_rtn_val = HE5_SWwriteattr(i_swathid, i_attrname, i_numbertype, i_count, i_datbuf);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecunsint64ary(i_count);
    return(rtn_val);
}

VALUE
hdfeos5_sw_get_att(VALUE mod, VALUE attrname)
{
    VALUE result;
    hid_t i_swathid;
    char *i_attrname;
    hid_t o_ntype;
    void *o_datbuf;
    unsigned long long o_count;
    herr_t o_rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    i_attrname = RSTRING_PTR(attrname);

    o_rtn_val = HE5_SWattrinfo(i_swathid, i_attrname, &o_ntype, &o_count);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    HE5Wrap_make_NArray1D_or_str(o_ntype, o_count, &result, &o_datbuf); 
    o_rtn_val = HE5_SWreadattr(i_swathid, i_attrname, o_datbuf);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    return result;
}

VALUE
hdfeos5_swinqattrs(VALUE mod)
{
    hid_t i_swathid;
    char *o_attrnames;
    long  o_strbufsize;
    long  o_number;
    VALUE nattr;
    VALUE attrnames;
    VALUE strbufsize;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    o_number = HE5_SWinqattrs(i_swathid, NULL, &o_strbufsize);
    if(o_number < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    o_attrnames = ALLOCA_N(char, (o_strbufsize + 1));

    o_number = HE5_SWinqattrs(i_swathid, o_attrnames, &o_strbufsize);
    if(o_number < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    nattr = LONG2NUM(o_number);
    attrnames = rb_str_new(o_attrnames, o_strbufsize);
    strbufsize = INT2NUM(o_strbufsize);

    return rb_ary_new3(3, nattr, attrnames, strbufsize);
}

VALUE
hdfeos5_swinqdims(VALUE mod, VALUE entrycode)
{
    hid_t i_swathid;
    int i_count;
    long i_strbufsize;
    char *o_dimnames;
    unsigned long long *hs_dims;
    long o_ndims;
    VALUE ndims;
    VALUE dimnames;
    VALUE dims;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    i_count = swnentries_count(i_swathid, entrycode);
    i_strbufsize = swnentries_strbuf(i_swathid, entrycode);

    hs_dims = ALLOCA_N(unsigned long long,  i_count);
    o_dimnames = ALLOCA_N(char, (i_strbufsize + 1));
    
    o_ndims = HE5_SWinqdims(i_swathid, o_dimnames, hs_dims);
    if(o_ndims < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    ndims = LONG2NUM(o_ndims);
    dimnames = rb_str_new(o_dimnames,i_strbufsize);
    dims = hdfeos5_cunsint64ary2obj(hs_dims, i_count, 1, &i_count);

    return rb_ary_new3(3, ndims, dimnames, dims);
}

VALUE
hdfeos5_swinqmaps(VALUE mod, VALUE entrycode)
{
    hid_t i_swathid;
    char *o_dimmaps;
    long *o_offset;
    long *o_increment;
    long o_nmaps;
    int i_count;
    long i_strbufsize;
    VALUE nmaps;
    VALUE dimmaps;
    VALUE offset;
    VALUE increment;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    i_count = swnentries_count(i_swathid, entrycode);
    i_strbufsize = swnentries_strbuf(i_swathid, entrycode);

    o_offset = ALLOCA_N(long, i_count);
    o_increment = ALLOCA_N(long, i_count);
    o_dimmaps = ALLOCA_N(char, (i_strbufsize + 1));

    o_nmaps = HE5_SWinqmaps(i_swathid, o_dimmaps, o_offset, o_increment);
    if(o_nmaps < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    nmaps = LONG2NUM(o_nmaps);
    dimmaps = rb_str_new(o_dimmaps,i_strbufsize);
    offset = hdfeos5_clongary2obj(o_offset, i_count, 1, &i_count);
    increment = hdfeos5_clongary2obj(o_increment, i_count, 1, &i_count);

    return rb_ary_new3(4, nmaps, dimmaps, offset, increment);
}

VALUE
hdfeos5_swinqidxmaps(VALUE mod, VALUE entrycode)
{
    hid_t i_swathid;
    char *o_idxmaps;
    unsigned long long *hs_idxsizes;
    long o_nmap;
    int i_count;
    long i_strbufsize;
    VALUE nmap;
    VALUE idxmaps;
    VALUE idxsizes;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    i_count = swnentries_count(i_swathid, entrycode);
    i_strbufsize = swnentries_strbuf(i_swathid, entrycode);

    hs_idxsizes = ALLOCA_N(unsigned long long, i_count);
    o_idxmaps = ALLOCA_N(char, (i_strbufsize + 1));

    o_nmap = HE5_SWinqidxmaps(i_swathid, o_idxmaps, hs_idxsizes);
    if(o_nmap < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    nmap = LONG2NUM(o_nmap);
    idxmaps = rb_str_new(o_idxmaps,i_strbufsize);
    idxsizes = hdfeos5_cunsint64ary2obj(hs_idxsizes, i_count, 1, &i_count);

    return rb_ary_new3(3, nmap, idxmaps, idxsizes);
}

VALUE
hdfeos5_swinqdatafields(VALUE mod, VALUE entrycode)
{
    hid_t i_swathid;
    char  *o_fieldlist;
    int   *o_rank;
    hid_t *o_ntype;
    long   o_nflds;
    int  i_count;
    long i_strbufsize;
    VALUE nflds;
    VALUE fieldlist;
    VALUE rank;
    VALUE ntype;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    i_count = swnentries_count(i_swathid, entrycode);
    i_strbufsize = swnentries_strbuf(i_swathid, entrycode);

    o_rank = ALLOCA_N(int, i_count);
    o_fieldlist = ALLOCA_N(char, (i_strbufsize + 1));

    o_nflds = HE5_SWinqdatafields(i_swathid, o_fieldlist, NULL, NULL);
    if (o_nflds < 0 ) return  Qfalse ;

    o_ntype = ALLOCA_N(hid_t, (o_nflds + 1)); 
    o_nflds = HE5_SWinqdatafields(i_swathid, o_fieldlist, o_rank, o_ntype);
    if (o_nflds < 0 ) return  Qfalse ;
    else              nflds = LONG2NUM(o_nflds);
    fieldlist = rb_str_new(o_fieldlist,i_strbufsize);
 
    i_count = (int)o_nflds;
    rank = hdfeos5_cintary2obj(o_rank, i_count, 1, &i_count);
    ntype = hdfeos5_cintary2obj(o_ntype, i_count, 1, &i_count);

    return rb_ary_new3(4, nflds, fieldlist, rank, ntype);
}

VALUE
hdfeos5_swinqgeofields(VALUE mod, VALUE entrycode)
{
    hid_t i_swathid;
    char  *o_fieldlist;
    int   *o_rank;
    hid_t *o_ntype;
    long o_nflds;
    int  i_count;
    long i_strbufsize;
    VALUE nflds;
    VALUE fieldlist;
    VALUE rank;
    VALUE ntype;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    i_count = swnentries_count(i_swathid, entrycode);
    i_strbufsize = swnentries_strbuf(i_swathid, entrycode);

    o_rank = ALLOCA_N(int, i_count);
    o_fieldlist = ALLOCA_N(char, (i_strbufsize + 1));
    o_nflds = HE5_SWinqgeofields(i_swathid, o_fieldlist, o_rank, NULL);
    if (o_nflds < 0 ) return  Qfalse ;

    o_ntype = ALLOCA_N(hid_t, (o_nflds + 1));
    o_nflds = HE5_SWinqgeofields(i_swathid, o_fieldlist, o_rank, o_ntype);
    if (o_nflds < 0 ) return  Qfalse ;
    else              nflds = LONG2NUM(o_nflds);
    fieldlist = rb_str_new(o_fieldlist,i_strbufsize);

    i_count = (int)o_nflds;
    rank = hdfeos5_cintary2obj(o_rank, i_count, 1, &i_count);
    ntype = hdfeos5_cintary2obj(o_ntype, i_count, 1, &i_count);

    return rb_ary_new3(4, nflds, fieldlist, rank, ntype);
}

VALUE
hdfeos5_swinqdatatype(VALUE mod, VALUE fieldname, VALUE attrname, VALUE group)
{
    hid_t i_swathid;
    char *i_fieldname;
    char *i_attrname;
    int i_group;
    hid_t i_datatype = FAIL;
    H5T_class_t o_classid;
    H5T_order_t o_order;
    size_t o_size;
    herr_t o_rtn_val;
    VALUE classid;
    VALUE order;
    VALUE size;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fieldname,T_STRING);
    SafeStringValue(fieldname);
    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    Check_Type(group,T_STRING);
    SafeStringValue(group);

    i_fieldname = RSTRING_PTR(fieldname);
    i_attrname = RSTRING_PTR(attrname);
    i_group = change_groupcode(RSTRING_PTR(group));

    if(strcmp(i_attrname,"NULL")==0)  i_attrname = NULL;
    o_rtn_val = HE5_SWinqdatatype(i_swathid, i_fieldname, i_attrname, i_group, &i_datatype, &o_classid, &o_order, &o_size);
    if(o_rtn_val == FAIL) return Qfalse;
    classid = INT2NUM(o_classid);
    order = INT2NUM(o_order);
    size = INT2NUM(o_size);

    return rb_ary_new3(3, classid, order, size);
}

VALUE
hdfeos5_swnentries(VALUE mod, VALUE entrycode)
{
    hid_t i_swathid;
    int i_entrycode;
    long o_strbufsize;
    long o_count;
    VALUE count;
    VALUE strbufsize;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(entrycode,T_STRING);
    SafeStringValue(entrycode);
    i_entrycode = change_entrycode(RSTRING_PTR(entrycode));

    o_count = HE5_SWnentries(i_swathid, i_entrycode, &o_strbufsize);
    if (o_count < 0 ) return  Qfalse ;
    else              count = LONG2NUM(o_count);
    strbufsize = LONG2NUM(o_strbufsize);

    return rb_ary_new3(2, count, strbufsize);
}

VALUE
hdfeos5_swinqswath(VALUE mod)
{
    char *i_filename;
    char *o_swathlist;
    long o_strbufsize;
    long o_nSwath;
    VALUE nSwath;
    VALUE swathlist;
    VALUE strbufsize;

    struct HE5 *he5file;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5, he5file);
    i_filename=he5file->name;

    o_nSwath = HE5_SWinqswath(i_filename, NULL, &o_strbufsize);
    if (o_nSwath <= 0 ) return  Qfalse ;

    o_swathlist = ALLOCA_N(char, (o_strbufsize + 1));
    o_nSwath = HE5_SWinqswath(i_filename, o_swathlist, &o_strbufsize);
    if (o_nSwath <= 0 ) return  Qfalse ;
    else               nSwath = LONG2NUM(o_nSwath);
    swathlist = rb_str_new(o_swathlist, o_strbufsize);
    strbufsize = LONG2NUM(o_strbufsize);

    return rb_ary_new3(3, nSwath, swathlist, strbufsize);
}

VALUE
hdfeos5_swwritefield(VALUE mod, VALUE start, VALUE stride, VALUE edge, VALUE data, VALUE ntype)
{
    char *chk_ntype;
    Check_Type(ntype,T_STRING);
    SafeStringValue(ntype);
    chk_ntype = RSTRING_PTR(ntype);

    switch (check_numbertype(chk_ntype)){
    case  HE5T_NATIVE_CHAR:
    case  HE5T_NATIVE_SCHAR:
    case  HE5T_NATIVE_UCHAR:
    case  HE5T_CHARSTRING:
        return hdfeos5_swwritefield_char(mod,  start,  stride,  edge,  data);
	break;

    case  HE5T_NATIVE_INT8:
    case  HE5T_NATIVE_UINT8:
        return hdfeos5_swwritefield_char(mod,  start,  stride,  edge,  data);
	break;

    case  HE5T_NATIVE_SHORT:
    case  HE5T_NATIVE_USHORT:
    case  HE5T_NATIVE_INT16:
    case  HE5T_NATIVE_UINT16:
        return hdfeos5_swwritefield_short(mod,  start,  stride,  edge,  data);
	break;

    case  HE5T_NATIVE_INT:
    case  HE5T_NATIVE_UINT:
    case  HE5T_NATIVE_INT32:
    case  HE5T_NATIVE_UINT32:
        return hdfeos5_swwritefield_int(mod,  start,  stride,  edge,  data);
	break;

    case  HE5T_NATIVE_LONG:
        return hdfeos5_swwritefield_long(mod,  start,  stride,  edge,  data);
	break;

    case  HE5T_NATIVE_FLOAT:
        return hdfeos5_swwritefield_float(mod,  start,  stride,  edge,  data);
	break;

    case  HE5T_NATIVE_DOUBLE:
        return hdfeos5_swwritefield_double(mod,  start,  stride,  edge,  data);
	break;
    default:
	rb_raise(rb_eHE5Error, "not match data type [%s:%d]",__FILE__,__LINE__);
    }
}

VALUE
hdfeos5_swreadfield(VALUE mod, VALUE start, VALUE stride, VALUE edge, VALUE ntype)
{
    char *chk_ntype;
    Check_Type(ntype,T_STRING);
    SafeStringValue(ntype);
    chk_ntype = RSTRING_PTR(ntype);

    switch (check_numbertype(chk_ntype)){
    case  HE5T_NATIVE_CHAR:
    case  HE5T_NATIVE_SCHAR:
    case  HE5T_NATIVE_UCHAR:
    case  HE5T_CHARSTRING:
        return hdfeos5_swreadfield_char(mod,  start,  stride,  edge);
	break;

    case  HE5T_NATIVE_INT8:
    case  HE5T_NATIVE_UINT8:
        return hdfeos5_swreadfield_char(mod,  start,  stride,  edge);
	break;

    case  HE5T_NATIVE_SHORT:
    case  HE5T_NATIVE_USHORT:
    case  HE5T_NATIVE_INT16:
    case  HE5T_NATIVE_UINT16:
        return hdfeos5_swreadfield_short(mod,  start,  stride,  edge);
	break;

    case  HE5T_NATIVE_INT:
    case  HE5T_NATIVE_UINT:
    case  HE5T_NATIVE_INT32:
    case  HE5T_NATIVE_UINT32:
        return hdfeos5_swreadfield_int(mod,  start,  stride,  edge);
	break;

    case  HE5T_NATIVE_LONG:
        return hdfeos5_swreadfield_long(mod,  start,  stride,  edge);
	break;

    case  HE5T_NATIVE_FLOAT:
        return hdfeos5_swreadfield_float(mod,  start,  stride,  edge);
	break;

    case  HE5T_NATIVE_DOUBLE:
        return hdfeos5_swreadfield_double(mod,  start,  stride,  edge);
	break;
    default:
	rb_raise(rb_eHE5Error, "not match data type [%s:%d]",__FILE__,__LINE__);
    }
}

VALUE
hdfeos5_swfldsrch(VALUE mod)
{
    hid_t i_swathid;
    char *i_fieldname;
    hid_t o_fieldid;
    int o_rank;
    unsigned long long *o_dims;
    hid_t o_typeid;
    int o_fldgroup;
    VALUE fldgroup;
    VALUE fieldid;
    VALUE rank;
    VALUE dims;
    VALUE type_id;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_swathid=he5field->swid;
    i_fieldname=he5field->name;

    o_fldgroup = HE5_SWfldsrch(i_swathid, i_fieldname, &o_fieldid, &o_rank, NULL, &o_typeid);
    if(o_fldgroup == -1) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    o_dims = ALLOCA_N(unsigned long long, (o_rank + 1));
    o_fldgroup = HE5_SWfldsrch(i_swathid, i_fieldname, &o_fieldid, &o_rank, o_dims, &o_typeid);
    if(o_fldgroup == -1) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    fldgroup = INT2NUM(o_fldgroup);
    fieldid = INT2NUM(o_fieldid);
    rank    = INT2NUM(o_rank);
    dims    = hdfeos5_cunsint64ary2obj(o_dims, o_rank, 1, &o_rank);
    type_id = INT2NUM(o_typeid);

    return rb_ary_new3(5, fldgroup, fieldid, rank, dims, type_id);
}

VALUE
hdfeos5_swdetach(VALUE mod)
{
    hid_t i_swathid;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    o_rtn_val = HE5_SWdetach(i_swathid);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    return(rtn_val);
}

VALUE
hdfeos5_swdefboxregion(VALUE mod, VALUE cornerlon, VALUE cornerlat, VALUE mode)
{
    hid_t i_swathid;
    float *i_cornerlon;
    float *i_cornerlat;
    int i_mode;
    hid_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    if (TYPE(cornerlon) == T_FLOAT) {
      cornerlon = rb_Array(cornerlon);
    }
    if (TYPE(cornerlat) == T_FLOAT) {
      cornerlat = rb_Array(cornerlat);
    }
    Check_Type(mode,T_STRING);
    SafeStringValue(mode);
    i_mode = change_subsetmode(RSTRING_PTR(mode));
    i_cornerlon = hdfeos5_obj2cfloatary(cornerlon);
    i_cornerlat = hdfeos5_obj2cfloatary(cornerlat);

    o_rtn_val = HE5_SWdefboxregion(i_swathid, (double*)i_cornerlon, (double*)i_cornerlat, i_mode);
    rtn_val = INT2NUM(o_rtn_val);
    hdfeos5_freecfloatary(i_cornerlon);
    hdfeos5_freecfloatary(i_cornerlat);
    return(rtn_val);
}

VALUE
hdfeos5_swregionindex(VALUE mod, VALUE cornerlon, VALUE cornerlat, VALUE mode)
{
    hid_t i_swathid;
    float *i_cornerlon;
    float *i_cornerlat;
    int    i_mode;
    char   o_geodim[maxcharsize]="";
    unsigned long long o_idxrange;
    hid_t o_rtn_val;
    VALUE rtn_val;
    VALUE geodim;
    VALUE idxrange;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    if (TYPE(cornerlon) == T_FLOAT) {
      cornerlon = rb_Array(cornerlon);
    }
    if (TYPE(cornerlat) == T_FLOAT) {
      cornerlat = rb_Array(cornerlat);
    }
    Check_Type(mode,T_STRING);
    SafeStringValue(mode);
    i_mode = change_subsetmode(RSTRING_PTR(mode));

    i_cornerlon = hdfeos5_obj2cfloatary(cornerlon);
    i_cornerlat = hdfeos5_obj2cfloatary(cornerlat);

    o_rtn_val = HE5_SWregionindex(i_swathid, (double*)i_cornerlon, (double*)i_cornerlat, i_mode, o_geodim, &o_idxrange);

    rtn_val = INT2NUM(o_rtn_val);
    geodim = rb_str_new2(o_geodim);
    idxrange = INT2NUM(o_idxrange);
    hdfeos5_freecfloatary(i_cornerlon);
    hdfeos5_freecfloatary(i_cornerlat);

    return rb_ary_new3(3, rtn_val, geodim, idxrange);
}

VALUE
hdfeos5_swdeftimeperiod(VALUE mod, VALUE starttime, VALUE stoptime, VALUE mode)
{
    hid_t i_swathid;
    double i_starttime;
    double i_stoptime;
    int i_mode;
    hid_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    if (TYPE(starttime) != T_FLOAT) {
      starttime = rb_funcall(starttime, rb_intern("to_f"), 0);
    }
    if (TYPE(stoptime) != T_FLOAT) {
      stoptime = rb_funcall(stoptime, rb_intern("to_f"), 0);
    }
    Check_Type(mode,T_STRING);
    SafeStringValue(mode);
    i_mode = change_subsetmode(RSTRING_PTR(mode));

    i_starttime = (double)NUM2DBL(starttime);
    i_stoptime = (double)NUM2DBL(stoptime);

    o_rtn_val = HE5_SWdeftimeperiod(i_swathid, i_starttime, i_stoptime, i_mode);
    rtn_val = INT2NUM(o_rtn_val);
    return(rtn_val);
}

VALUE
hdfeos5_swextractregion(VALUE mod, VALUE regionid, VALUE externalflag)
{
    hid_t i_swathid;
    hid_t i_regionid;
    char *i_fieldname;
    int i_externalflag;
    void *o_buffer;
    herr_t o_rtn_val;
    VALUE buffer;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fieldname=he5field->name;
    i_swathid=he5field->swid;

    Check_Type(regionid,T_FIXNUM);
    Check_Type(externalflag,T_STRING);
    SafeStringValue(externalflag);

    i_regionid = NUM2INT(regionid);
    i_externalflag = change_subsetmode(RSTRING_PTR(externalflag));

    o_buffer = (void*)malloc(HE5_BLKSIZE);
    o_rtn_val = HE5_SWextractregion(i_swathid, i_regionid, i_fieldname, i_externalflag, o_buffer);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    buffer = rb_str_new2(o_buffer);

    return(buffer);

}

VALUE
hdfeos5_swextractperiod(VALUE mod, VALUE periodid, VALUE externalflag)
{
    hid_t i_swathid;
    hid_t i_periodid;
    char *i_fieldname;
    int i_externalflag;
    void *o_buffer;
    herr_t o_rtn_val;
    VALUE buffer;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fieldname=he5field->name;
    i_swathid=he5field->swid;

    Check_Type(periodid,T_FIXNUM);
    Check_Type(externalflag,T_STRING);
    SafeStringValue(externalflag);

    i_periodid = NUM2INT(periodid);
    i_externalflag = change_subsetmode(RSTRING_PTR(externalflag));

    o_buffer = (void*)malloc(HE5_BLKSIZE);
    o_rtn_val = HE5_SWextractperiod(i_swathid, i_periodid, i_fieldname, i_externalflag, o_buffer);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    buffer = rb_str_new2(o_buffer);
    return(buffer);
}

VALUE
hdfeos5_swdupregion(VALUE mod, VALUE oldregionid)
{
    hid_t i_oldregionid;
    hid_t o_rtn_val;
    VALUE rtn_val;

    Check_Type(oldregionid,T_FIXNUM);
    i_oldregionid = NUM2INT(oldregionid);

    o_rtn_val = HE5_SWdupregion(i_oldregionid);
    rtn_val = INT2NUM(o_rtn_val);
    return(rtn_val);
}

VALUE
hdfeos5_swdefvrtregion(VALUE mod, VALUE regionid, VALUE vertobj, VALUE range)
{
    hid_t i_swathid;
    hid_t i_regionid;
    char *i_vertobj;
    float *i_range;
    hid_t o_rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(regionid,T_FIXNUM);
    Check_Type(vertobj,T_STRING);
    SafeStringValue(vertobj);
    if (TYPE(range) == T_FLOAT) {
      range = rb_Array(range);
    }
    i_regionid = NUM2INT(regionid);
    i_vertobj = RSTRING_PTR(vertobj);
    i_range = hdfeos5_obj2cfloatary(range);

    o_rtn_val = HE5_SWdefvrtregion(i_swathid, i_regionid, i_vertobj, (double*)i_range);
    regionid = INT2NUM(o_rtn_val);
    hdfeos5_freecfloatary(i_range);

    return(regionid);
}

VALUE
hdfeos5_swsetfillvalue(VALUE mod, VALUE fieldname,VALUE numbertype, VALUE fillval)
{
    hid_t i_swathid;
    char *i_fieldname;
    hid_t i_numbertype;
    void *i_fillval;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fieldname,T_STRING);
    SafeStringValue(fieldname);
    Check_Type(numbertype,T_STRING);
    SafeStringValue(numbertype);
    i_fieldname = RSTRING_PTR(fieldname);
    i_numbertype = change_numbertype(RSTRING_PTR(numbertype));

    if (TYPE(fillval) == T_FLOAT) {
      fillval = rb_Array(fillval);
      i_fillval = hdfeos5_obj2cfloatary(fillval);
    }
    if (TYPE(fillval) == T_STRING) {
      Check_Type(fillval,T_STRING);
      SafeStringValue(fillval);
      i_fillval = RSTRING_PTR(fillval);
    }

    i_fillval = (void*)malloc(HE5_BLKSIZE);
    o_rtn_val = HE5_SWsetfillvalue(i_swathid, i_fieldname, i_numbertype, i_fillval);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecfloatary(i_fillval);
    return(rtn_val);
}

VALUE
hdfeos5_swgetfillvalue(VALUE mod,VALUE fieldname)
{
    hid_t i_swathid;
    char *i_fieldname;
    void *o_fillval;
    herr_t o_rtn_val;
    VALUE fillval;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fieldname,T_STRING);
    SafeStringValue(fieldname);
    i_fieldname = RSTRING_PTR(fieldname);

    o_fillval = (void*)malloc(HE5_BLKSIZE);
    o_rtn_val = HE5_SWgetfillvalue(i_swathid, i_fieldname, o_fillval);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    fillval = rb_str_new2(o_fillval);
    return(fillval);
}

VALUE
hdfeos5_swregioninfo(VALUE mod, VALUE regionid)
{
    hid_t i_swathid;
    hid_t i_regionid;
    char *i_fieldname;
    hid_t o_ntype;
    int o_rank=0;
    unsigned long long o_dims[maxcharsize];
    size_t o_size=0;
    herr_t o_rtn_val;
    char str[maxcharsize];
    VALUE ntype;
    VALUE rank;
    VALUE dims;
    VALUE size;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fieldname=he5field->name;
    i_swathid=he5field->swid;

    Check_Type(regionid,T_FIXNUM);
    i_regionid = NUM2INT(regionid);

    o_rtn_val = HE5_SWregioninfo(i_swathid, i_regionid, i_fieldname, &o_ntype, &o_rank, o_dims, &o_size);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    change_chartype(o_ntype, str);
    ntype =rb_str_new(str,strlen(str));
    rank = INT2NUM(o_rank);
    dims = hdfeos5_cunsint64ary2obj(o_dims, o_rank, 1, &o_rank);
    size = INT2NUM(o_size);

    return rb_ary_new3(4, ntype, rank, dims, size);
}

VALUE
hdfeos5_swperiodinfo(VALUE mod, VALUE periodid)
{
    hid_t i_swathid;
    hid_t i_periodid;
    char *i_fieldname;
    hid_t o_ntype;
    int o_rank=0;
    unsigned long long o_dims[maxcharsize];
    size_t o_size=0;
    herr_t o_rtn_val;
    char str[maxcharsize];
    VALUE ntype;
    VALUE rank;
    VALUE dims;
    VALUE size;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fieldname=he5field->name;
    i_swathid=he5field->swid;

    Check_Type(periodid,T_FIXNUM);
    i_periodid = NUM2INT(periodid);

    o_rtn_val = HE5_SWperiodinfo(i_swathid, i_periodid, i_fieldname, &o_ntype, &o_rank, o_dims, &o_size);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    change_chartype(o_ntype, str);
    ntype =rb_str_new(str,strlen(str));
    rank = INT2NUM(o_rank);
    dims = hdfeos5_cunsint64ary2obj(o_dims, o_rank, 1, &o_rank);
    size = INT2NUM(o_size);

    return rb_ary_new3(4, ntype, rank, dims, size);
}

VALUE
hdfeos5_swupdatescene(VALUE mod, VALUE regionid)
{
    hid_t i_swathid;
    hid_t i_regionid;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(regionid,T_FIXNUM);
    i_regionid = NUM2INT(regionid);

    o_rtn_val = HE5_SWupdatescene(i_swathid, i_regionid);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    return(rtn_val);
}

VALUE
hdfeos5_swupdateidxmap(VALUE mod, VALUE regionid, VALUE indexin)
{
    hid_t i_swathid;
    hid_t i_regionid;
    long *i_indexin;
    long o_indexout;
    long o_indicies;
    long o_rtn_val;
    VALUE rtn_val;
    VALUE indexout;
    VALUE indicies;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(regionid,T_FIXNUM);
    if ((TYPE(indexin) == T_BIGNUM) || (TYPE(indexin) == T_FIXNUM)) {
      indexin = rb_Array(indexin);
    }
    i_regionid = NUM2INT(regionid);
    i_indexin = (long*)hdfeos5_obj2clongary(indexin);

    o_rtn_val = HE5_SWupdateidxmap(i_swathid, i_regionid, i_indexin, &o_indexout, &o_indicies);
    if(o_rtn_val < 0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    rtn_val = LONG2NUM(o_rtn_val);
    indexout = INT2NUM(o_indexout);
    indicies = INT2NUM(o_indicies);
    hdfeos5_freeclongary(i_indexin);

    return rb_ary_new3(3, rtn_val, indexout, indicies);
}

VALUE
hdfeos5_swgeomapinfo(VALUE mod, VALUE geodim)
{
    hid_t i_swathid;
    char *i_geodim;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(geodim,T_STRING);
    SafeStringValue(geodim);
    i_geodim = RSTRING_PTR(geodim);

    o_rtn_val = HE5_SWgeomapinfo(i_swathid, i_geodim);
    if (o_rtn_val == FAIL) return Qfalse;
    return Qtrue;
    return(rtn_val);
}

VALUE
hdfeos5_swwritegrpattr(VALUE mod, VALUE attrname, VALUE numbertype, VALUE count, VALUE datbuf)
{
    hid_t i_swathid;
    char *i_attrname;
    hid_t i_numbertype;
    hid_t i_numbertypechk;
    unsigned long long *i_count;
    void *i_datbuf;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    Check_Type(numbertype,T_STRING);
    SafeStringValue(numbertype);
    count = rb_Array(count);

    i_attrname = RSTRING_PTR(attrname);
    i_numbertype    = change_numbertype(RSTRING_PTR(numbertype));
    i_numbertypechk = check_numbertype(RSTRING_PTR(numbertype));
    i_count = hdfeos5_obj2cunsint64ary(count);

    HE5Wrap_store_NArray1D_or_str(i_numbertypechk, datbuf, &i_datbuf); 
    o_rtn_val = HE5_SWwritegrpattr(i_swathid, i_attrname, i_numbertype, i_count, i_datbuf);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecunsint64ary(i_count);
    return(rtn_val);
}

VALUE
hdfeos5_sw_get_grpatt(VALUE mod, VALUE attrname)
{
    VALUE result;
    hid_t i_swathid;
    char *i_attrname;
    hid_t o_ntype;
    void *o_datbuf;
    unsigned long long o_count;
    herr_t o_rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    i_attrname = RSTRING_PTR(attrname);

    o_rtn_val = HE5_SWgrpattrinfo(i_swathid, i_attrname, &o_ntype, &o_count);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    HE5Wrap_make_NArray1D_or_str(o_ntype, o_count, &result, &o_datbuf);
    o_rtn_val = HE5_SWreadgrpattr(i_swathid, i_attrname, o_datbuf);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    return result;
}

VALUE
hdfeos5_swinqgrpattrs(VALUE mod)
{
    hid_t i_swathid;
    char *o_attrname;
    long o_strbufsize;
    long o_nattr;
    VALUE nattr;
    VALUE attrname;
    VALUE strbufsize;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    o_nattr = HE5_SWinqgrpattrs(i_swathid, NULL, &o_strbufsize);
    if(o_nattr < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    o_attrname = ALLOCA_N(char, (o_strbufsize + 1));

    o_nattr = HE5_SWinqgrpattrs(i_swathid, o_attrname, &o_strbufsize);
    if(o_nattr < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    nattr = LONG2NUM(o_nattr);
    attrname = rb_str_new(o_attrname,o_strbufsize);
    strbufsize = INT2NUM(o_strbufsize);
    return rb_ary_new3(3, nattr, attrname, strbufsize);
}

VALUE
hdfeos5_swwritegeogrpattr(VALUE mod, VALUE attrname, VALUE numbertype, VALUE count, VALUE datbuf)
{
    hid_t i_swathid;
    char *i_attrname;
    hid_t i_numbertype;
    unsigned long long *i_count;
    void *i_datbuf;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    Check_Type(numbertype,T_STRING);
    SafeStringValue(numbertype);
    count = rb_Array(count);
    if (TYPE(datbuf) == T_FLOAT) {
      datbuf = rb_Array(datbuf);
    }
    i_attrname = RSTRING_PTR(attrname);
    i_numbertype = change_numbertype(RSTRING_PTR(numbertype));
    i_count = hdfeos5_obj2cunsint64ary(count);
    i_datbuf = hdfeos5_obj2cfloatary(datbuf);

    o_rtn_val = HE5_SWwritegeogrpattr(i_swathid, i_attrname, i_numbertype, i_count, i_datbuf);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecunsint64ary(i_count);
    hdfeos5_freecfloatary(i_datbuf);
    return rtn_val;
}

VALUE
hdfeos5_sw_get_geogrpatt(VALUE mod, VALUE attrname)
{
    VALUE result;
    hid_t i_swathid;
    char *i_attrname;
    hid_t o_ntype;
    void *o_datbuf;
    unsigned long long o_count;
    herr_t o_rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    i_attrname = RSTRING_PTR(attrname);

    o_rtn_val = HE5_SWgeogrpattrinfo(i_swathid, i_attrname, &o_ntype, &o_count);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    HE5Wrap_make_NArray1D_or_str(o_ntype, o_count, &result, &o_datbuf);
    o_rtn_val = HE5_SWreadgeogrpattr(i_swathid, i_attrname, o_datbuf);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    return result;
}

VALUE
hdfeos5_swinqgeogrpattrs(VALUE mod)
{
    hid_t i_swathid;
    char *o_attrnames;
    long o_strbufsize;
    long o_nattr;
    VALUE nattr;
    VALUE attrname;
    VALUE strbufsize;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    o_nattr = HE5_SWinqgeogrpattrs(i_swathid, NULL, &o_strbufsize);
    if(o_nattr < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    o_attrnames = ALLOCA_N(char, (o_strbufsize + 1));
    
    o_nattr = HE5_SWinqgeogrpattrs(i_swathid, o_attrnames, &o_strbufsize);
    if(o_nattr < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    nattr = LONG2NUM(o_nattr);
    attrname = rb_str_new(o_attrnames,o_strbufsize);
    strbufsize = INT2NUM(o_strbufsize);
    return rb_ary_new3(3, nattr, attrname, strbufsize);
}

VALUE
hdfeos5_swwritelocattr(VALUE mod, VALUE attrname, VALUE numbertype, VALUE count, VALUE datbuf)
{
    hid_t i_swathid;
    char *i_fieldname;
    char *i_attrname;
    hid_t i_numbertype;
    hid_t i_numbertypechk;
    unsigned long long *i_count;
    void *i_datbuf;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fieldname=he5field->name;
    i_swathid=he5field->swid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    Check_Type(numbertype,T_STRING);
    SafeStringValue(numbertype);
    count = rb_Array(count);

    i_attrname = RSTRING_PTR(attrname);
    i_numbertype    = change_numbertype(RSTRING_PTR(numbertype));
    i_numbertypechk = check_numbertype(RSTRING_PTR(numbertype));
    i_count = hdfeos5_obj2cunsint64ary(count);

    HE5Wrap_store_NArray1D_or_str(i_numbertypechk, datbuf, &i_datbuf); 
    o_rtn_val = HE5_SWwritelocattr(i_swathid, i_fieldname, i_attrname, i_numbertype, i_count, i_datbuf);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecintary((int*)i_count);
    return rtn_val;
}

VALUE
hdfeos5_swfield_get_att(VALUE mod,VALUE  attrname)
{
    VALUE result;
    hid_t i_swathid;
    char *i_fieldname;
    char *i_attrname;
    void *o_datbuf;
    herr_t o_rtn_val;
    hid_t  o_ntype;
    unsigned long long o_count;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fieldname=he5field->name;
    i_swathid=he5field->swid;
    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    i_attrname = RSTRING_PTR(attrname);

    o_rtn_val = HE5_SWlocattrinfo(i_swathid, i_fieldname, i_attrname, 
				  &o_ntype, &o_count);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",
				   __FILE__,__LINE__);

    HE5Wrap_make_NArray1D_or_str(o_ntype, o_count, &result, &o_datbuf);
    o_rtn_val = HE5_SWreadlocattr(i_swathid, i_fieldname,i_attrname, o_datbuf);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",
				   __FILE__,__LINE__);
    return result;
}

VALUE
hdfeos5_swinqlocattrs(VALUE mod)
{
    hid_t i_swathid;
    char *i_fieldname;
    char *o_attrnames;
    long o_strbufsize;
    long o_nattr;
    VALUE nattr;
    VALUE attrname;
    VALUE strbufsize;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fieldname=he5field->name;
    i_swathid=he5field->swid;

    o_nattr = HE5_SWinqlocattrs(i_swathid, i_fieldname, NULL, &o_strbufsize);
    if(o_nattr < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
 
    o_attrnames = ALLOCA_N(char, (o_strbufsize + 1));
    o_nattr = HE5_SWinqlocattrs(i_swathid, i_fieldname, o_attrnames, &o_strbufsize);
    if(o_nattr < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    nattr = LONG2NUM(o_nattr);
    attrname = rb_str_new(o_attrnames,o_strbufsize);
    strbufsize = LONG2NUM(o_strbufsize);
    return rb_ary_new3(3, nattr, attrname, strbufsize);
}

VALUE
hdfeos5_prdefine(VALUE mod, VALUE profilename, VALUE dimlist, VALUE maxdimlist, VALUE datatype_id)
{
    hid_t i_swathid;
    char *i_profilename;
    char *i_dimlist;
    char *i_maxdimlist;
    hid_t i_datatype_id;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(profilename,T_STRING);
    SafeStringValue(profilename);
    Check_Type(dimlist,T_STRING);
    SafeStringValue(dimlist);
    Check_Type(maxdimlist,T_STRING);
    SafeStringValue(maxdimlist);
    Check_Type(datatype_id,T_STRING);
    SafeStringValue(datatype_id);

    i_profilename = RSTRING_PTR(profilename);
    i_dimlist = RSTRING_PTR(dimlist);
    i_maxdimlist = RSTRING_PTR(maxdimlist);
    i_datatype_id = change_numbertype(RSTRING_PTR(datatype_id));

    if(strcmp(i_maxdimlist,"NULL")==0)  i_maxdimlist = NULL;
    o_rtn_val = HE5_PRdefine(i_swathid, i_profilename, i_dimlist, i_maxdimlist, i_datatype_id);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    return rtn_val;
}

VALUE
hdfeos5_prwrite(VALUE mod, VALUE profilename, VALUE start, VALUE stride, VALUE edge, VALUE size, VALUE buffer)
{
    hid_t i_swathid;
    char *i_profilename;
    signed long long *i_start;
    unsigned long long *i_stride;
    unsigned long long *i_edge;
    size_t i_size;
    void *i_buffer;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(profilename,T_STRING);
    SafeStringValue(profilename);
    start = rb_Array(start);
    stride = rb_Array(stride);
    edge = rb_Array(edge);
    Check_Type(size,T_FIXNUM);
    if (TYPE(buffer) == T_FLOAT) {
      buffer = rb_Array(buffer);
    }
    i_profilename = RSTRING_PTR(profilename);
    i_size = NUM2LONG(size);
    i_start = hdfeos5_obj2csint64ary(start);
    i_stride = hdfeos5_obj2cunsint64ary(stride);
    i_edge = hdfeos5_obj2cunsint64ary(edge);
    i_buffer = hdfeos5_obj2cfloatary(buffer);

    o_rtn_val = HE5_PRwrite(i_swathid, i_profilename, i_start, i_stride, i_edge, i_size, i_buffer);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecsint64ary(i_start);
    hdfeos5_freecunsint64ary(i_stride);
    hdfeos5_freecunsint64ary(i_edge);
    hdfeos5_freecfloatary(i_buffer);
    return rtn_val;
}

VALUE
hdfeos5_prread(VALUE mod, VALUE profilename, VALUE start, VALUE stride, VALUE edge)
{
    hid_t i_swathid;
    char *i_profilename;
    signed long long *i_start;
    unsigned long long *i_stride;
    unsigned long long *i_edge;
    void *o_buffer;
    herr_t o_rtn_val;
    VALUE buffer;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(profilename,T_STRING);
    SafeStringValue(profilename);
    start = rb_Array(start);
    stride = rb_Array(stride);
    edge = rb_Array(edge);

    i_profilename = RSTRING_PTR(profilename);
    i_start = hdfeos5_obj2csint64ary(start);
    i_stride = hdfeos5_obj2cunsint64ary(stride);
    i_edge = hdfeos5_obj2cunsint64ary(edge);

    o_buffer = (void*)malloc(HE5_BLKSIZE);
    o_rtn_val = HE5_PRread(i_swathid, i_profilename, i_start, i_stride, i_edge, o_buffer);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    hdfeos5_freecsint64ary(i_start);
    hdfeos5_freecunsint64ary(i_stride);
    hdfeos5_freecunsint64ary(i_edge);
    buffer = rb_str_new2(o_buffer);
    return buffer;
}

VALUE
hdfeos5_prreclaimspace(VALUE mod, VALUE profilename)
{
    hid_t i_swathid;
    char *i_profilename;
    void *o_buffer;
    herr_t o_rtn_val;
    VALUE buffer;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(profilename,T_STRING);
    SafeStringValue(profilename);
    i_profilename = RSTRING_PTR(profilename);

    o_buffer = (void*)malloc(HE5_BLKSIZE);
    o_rtn_val = HE5_PRreclaimspace(i_swathid, i_profilename, o_buffer);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    buffer = rb_str_new2(o_buffer);
    return buffer;
}

VALUE
hdfeos5_prinquire(VALUE mod)
{
    hid_t i_swathid;
    char o_profnames[maxcharsize]="";
    int o_rank;
    H5T_class_t o_classid;
    long o_rtn_val;
    VALUE rtn_val;
    VALUE profnames;
    VALUE rank;
    VALUE classid;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    o_rtn_val = HE5_PRinquire(i_swathid, o_profnames, &o_rank, &o_classid);
    if(o_rtn_val < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    rtn_val = LONG2NUM(o_rtn_val);
    profnames = rb_str_new2(o_profnames);
    rank = INT2NUM(o_rank);
    classid = (o_classid == FAIL) ? Qfalse : Qtrue;
   
    return rb_ary_new3(4, rtn_val, profnames, rank, classid);
}

VALUE
hdfeos5_prinfo(VALUE mod, VALUE profilename)
{
    hid_t i_swathid;
    char *i_profilename;
    int o_rank;
    unsigned long long o_dims;
    unsigned long long o_maxdims;
    hid_t o_ntype;
    char o_dimlist[maxcharsize]="";
    herr_t o_rtn_val;
    VALUE rank;
    VALUE dims;
    VALUE maxdims;
    VALUE ntype;
    VALUE dimlist;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(profilename,T_STRING);
    SafeStringValue(profilename);
    i_profilename = RSTRING_PTR(profilename);

    o_rtn_val = HE5_PRinfo(i_swathid, i_profilename, &o_rank, &o_dims, &o_maxdims, &o_ntype, o_dimlist, NULL);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    rank = INT2NUM(o_rank);
    dims = INT2NUM(o_dims);
    maxdims = INT2NUM(o_maxdims);
    ntype = INT2NUM(o_ntype);
    dimlist = rb_str_new2(o_dimlist);
    return rb_ary_new3(6, rank, dims, maxdims, ntype, dimlist);
}

VALUE
hdfeos5_prwritegrpattr(VALUE mod, VALUE attrname, VALUE numbertype, VALUE count, VALUE datbuf)
{
    hid_t i_swathid;
    char *i_attrname;
    hid_t i_numbertype;
    unsigned long long *i_count;
    void *i_datbuf;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    Check_Type(numbertype,T_STRING);
    SafeStringValue(numbertype);
    count = rb_Array(count);
    if (TYPE(datbuf) == T_FLOAT) {
      datbuf = rb_Array(datbuf);
    }
    i_attrname = RSTRING_PTR(attrname);
    i_numbertype = change_numbertype(RSTRING_PTR(numbertype));
    i_count =  hdfeos5_obj2cunsint64ary(count);
    i_datbuf = hdfeos5_obj2cfloatary(datbuf);

    o_rtn_val = HE5_PRwritegrpattr(i_swathid, i_attrname, i_numbertype, i_count, i_datbuf);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecunsint64ary(i_count);
    hdfeos5_freecfloatary(i_datbuf);
    return rtn_val;
}

VALUE
hdfeos5_pr_get_grpatt(VALUE mod, VALUE attrname)
{
    VALUE result;
    hid_t i_swathid;
    char *i_attrname;
    hid_t o_ntype;
    void *o_buffer;
    unsigned long long o_count;
    herr_t o_rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    i_attrname = RSTRING_PTR(attrname);

    o_rtn_val = HE5_PRgrpattrinfo(i_swathid, i_attrname, &o_ntype, &o_count);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    HE5Wrap_make_NArray1D_or_str(o_ntype, o_count, &result, &o_buffer);
    o_rtn_val = HE5_PRreadgrpattr(i_swathid, i_attrname, o_buffer);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    return result;
}

VALUE
hdfeos5_prinqgrpattrs(VALUE mod)
{
    hid_t i_swathid;
    char *o_attrname;
    long o_strbufsize;
    long o_rtn_val;
    VALUE rtn_val;
    VALUE attrname;
    VALUE strbufsize;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    o_rtn_val = HE5_PRinqgrpattrs(i_swathid, NULL, &o_strbufsize);
    if(o_rtn_val < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    o_attrname = ALLOCA_N(char, (o_strbufsize + 1));

    o_rtn_val = HE5_PRinqgrpattrs(i_swathid, o_attrname, &o_strbufsize);
    if(o_rtn_val < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    rtn_val = LONG2NUM(o_rtn_val);
    attrname = rb_str_new(o_attrname,o_strbufsize);
    strbufsize = INT2NUM(o_strbufsize);
    return rb_ary_new3(3, rtn_val, attrname, strbufsize);
}

VALUE
hdfeos5_swsetalias(VALUE mod, VALUE fieldname)
{
    hid_t i_swathid;
    char *i_fieldname;
    char o_aliaslist[maxcharsize]="";
    herr_t o_rtn_val;
    VALUE aliaslist;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fieldname,T_STRING);
    SafeStringValue(fieldname);
    i_fieldname = RSTRING_PTR(fieldname);

    o_rtn_val = HE5_SWsetalias(i_swathid, i_fieldname, o_aliaslist);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    aliaslist = rb_str_new2(o_aliaslist);
    return aliaslist;
}

VALUE
hdfeos5_swdropalias(VALUE mod, VALUE fldgroup, VALUE aliasname)
{
    hid_t i_swathid;
    int i_fldgroup;
    char *i_aliasname;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fldgroup,T_STRING);
    SafeStringValue(fldgroup);
    Check_Type(aliasname,T_STRING);
    SafeStringValue(aliasname);

    i_fldgroup = change_groupcode(RSTRING_PTR(fldgroup));
    i_aliasname = RSTRING_PTR(aliasname);

    o_rtn_val = HE5_SWdropalias(i_swathid, i_fldgroup, i_aliasname);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    return rtn_val;
}

VALUE
hdfeos5_swinqdfldalias(VALUE mod)
{
    hid_t i_swathid;
    char o_fldalias[maxcharsize]="";
    long o_strbufsize;
    long o_rtn_val;
    VALUE rtn_val;
    VALUE fldalias;
    VALUE strbufsize;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    o_rtn_val = HE5_SWinqdfldalias(i_swathid, o_fldalias, &o_strbufsize);
    if(o_rtn_val < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    rtn_val = LONG2NUM(o_rtn_val);
    fldalias = rb_str_new2(o_fldalias);
    strbufsize = INT2NUM(o_strbufsize);
    return rb_ary_new3(3, rtn_val, fldalias, strbufsize);
}

VALUE
hdfeos5_swaliasinfo(VALUE mod, VALUE fldgroup, VALUE aliasname)
{
    hid_t i_swathid;
    int i_fldgroup;
    char *i_aliasname;
    int o_length;
    char o_buffer[maxcharsize]="";
    herr_t o_rtn_val;
    VALUE length;
    VALUE buffer;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fldgroup,T_STRING);
    SafeStringValue(fldgroup);
    Check_Type(aliasname,T_STRING);
    SafeStringValue(aliasname);

    i_fldgroup = change_groupcode(RSTRING_PTR(fldgroup));
    i_aliasname = RSTRING_PTR(aliasname);

    o_rtn_val = HE5_SWaliasinfo(i_swathid, i_fldgroup, i_aliasname, &o_length, o_buffer);
    if(o_rtn_val == FAIL) return Qfalse;
    length = INT2NUM(o_length);
    buffer = rb_str_new2(o_buffer);
    return rb_ary_new3(2, length, buffer);
}

VALUE
hdfeos5_swgetaliaslist(VALUE mod, VALUE fldgroup)
{
    hid_t i_swathid;
    int i_fldgroup;
    char o_aliaslist[maxcharsize]="";
    long o_strbufsize;
    long o_rtn_val;
    VALUE rtn_val;
    VALUE aliaslist;
    VALUE strbufsize;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fldgroup,T_STRING);
    SafeStringValue(fldgroup);
    i_fldgroup = change_groupcode(RSTRING_PTR(fldgroup));

    o_rtn_val = HE5_SWgetaliaslist(i_swathid, i_fldgroup, o_aliaslist, &o_strbufsize);
    if(o_rtn_val < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    rtn_val = LONG2NUM(o_rtn_val);
    aliaslist = rb_str_new2(o_aliaslist);
    strbufsize = INT2NUM(o_strbufsize);
    return rb_ary_new3(3, rtn_val, aliaslist, strbufsize);
}

VALUE
hdfeos5_swfldrename(VALUE mod, VALUE oldfieldname,VALUE newfieldname)
{
    hid_t i_swathid;
    char *i_oldfieldname;
    char *i_newfieldname;
    herr_t o_rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(oldfieldname,T_STRING);
    SafeStringValue(oldfieldname);
    i_oldfieldname = RSTRING_PTR(oldfieldname);
    Check_Type(newfieldname,T_STRING);
    SafeStringValue(newfieldname);
    i_newfieldname = RSTRING_PTR(newfieldname);


    o_rtn_val = HE5_SWfldrename(i_swathid, i_oldfieldname, i_newfieldname);
    if(o_rtn_val == FAIL) return Qfalse;
    return Qtrue;

}

VALUE
hdfeos5_swmountexternal(VALUE mod, VALUE fldgroup, VALUE extfilename)
{
    hid_t i_swathid;
    int i_fldgroup;
    char *i_extfilename;
    hid_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fldgroup,T_STRING);
    SafeStringValue(fldgroup);
    Check_Type(extfilename,T_STRING);
    SafeStringValue(extfilename);

    i_fldgroup = change_groupcode(RSTRING_PTR(fldgroup));
    i_extfilename = RSTRING_PTR(extfilename);

    o_rtn_val = HE5_SWmountexternal(i_swathid, i_fldgroup, i_extfilename);
    rtn_val = INT2NUM(o_rtn_val);
    return rtn_val;
}

VALUE
hdfeos5_swunmount(VALUE mod, VALUE fldgroup, VALUE fileid)
{
    hid_t i_swathid;
    int i_fldgroup;
    hid_t i_fileid;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fldgroup,T_STRING);
    SafeStringValue(fldgroup);
    Check_Type(fileid,T_FIXNUM);

    i_fldgroup = change_groupcode(RSTRING_PTR(fldgroup));
    i_fileid = NUM2INT(fileid);

    o_rtn_val = HE5_SWunmount(i_swathid, i_fldgroup, i_fileid);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    return rtn_val;
}

VALUE
hdfeos5_swreadexternal(VALUE mod, VALUE fldgroup, VALUE fieldname)
{
    hid_t i_swathid;
    int i_fldgroup;
    char *i_fieldname;
    void *o_buffer;
    herr_t o_rtn_val;
    VALUE buffer;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fldgroup,T_STRING);
    SafeStringValue(fldgroup);
    Check_Type(fieldname,T_STRING);
    SafeStringValue(fieldname);
    i_fldgroup = change_groupcode(RSTRING_PTR(fldgroup));
    i_fieldname = RSTRING_PTR(fieldname);

    o_buffer = (void*)malloc(HE5_BLKSIZE);
    o_rtn_val = HE5_SWreadexternal(i_swathid, i_fldgroup, i_fieldname, o_buffer);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    buffer = rb_str_new2(o_buffer);
    return buffer;
}

VALUE
hdfeos5_swsetextdata(VALUE mod, VALUE filelist, VALUE offset, VALUE size)
{
    hid_t i_swathid;
    char  *i_filelist;
    off_t *i_offset;
    unsigned long long *i_size;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(filelist,T_STRING);
    SafeStringValue(filelist);
    if ((TYPE(offset) == T_BIGNUM) || (TYPE(offset) == T_FIXNUM)) {
      offset = rb_Array(offset);
    }
    if ((TYPE(size) == T_BIGNUM) || (TYPE(size) == T_FIXNUM)) {
      size = rb_Array(size);
    }
    i_filelist = RSTRING_PTR(filelist);
    i_offset = hdfeos5_obj2clongary(offset);
    i_size = hdfeos5_obj2cunsint64ary(size);

    o_rtn_val = HE5_SWsetextdata(i_swathid, i_filelist, i_offset, i_size);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freeclongary(i_offset);
    hdfeos5_freecunsint64ary(i_size);
    return rtn_val;
}

VALUE
hdfeos5_swgetextdata(VALUE mod, VALUE fieldname)
{
    hid_t i_swathid;
    char *i_fieldname;
    size_t o_namelength=0;
    char  o_filelist[maxcharsize];
    off_t o_offset[maxcharsize];
    unsigned long long o_size[maxcharsize];
    int o_rtn_val;
    VALUE rtn_val;
    VALUE namelength;
    VALUE filelist;
    VALUE offset;
    VALUE size;

    struct HE5Sw *he5swath;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fieldname,T_STRING);
    SafeStringValue(fieldname);

    i_fieldname = RSTRING_PTR(fieldname);

    o_rtn_val = HE5_SWgetextdata(i_swathid, i_fieldname, o_namelength, o_filelist, o_offset, o_size);
    rtn_val = INT2NUM(o_rtn_val);
    
    namelength = hdfeos5_cintary2obj((int*)o_namelength,o_rtn_val,1,&o_rtn_val);
    filelist = hdfeos5_ccharary2obj(o_filelist,o_rtn_val,o_rtn_val);
    offset = hdfeos5_clongary2obj(o_offset,o_rtn_val,1,&o_rtn_val);
    size = hdfeos5_cunsint64ary2obj(o_size,o_rtn_val,1,&o_rtn_val);

    return rb_ary_new3(5,rtn_val, namelength, filelist, offset, size);
}

VALUE
hdfeos5_swindexinfo(VALUE mod, VALUE regionid, VALUE object)
{
    hid_t i_regionid;
    char *i_object;
    int o_rank;
    char o_dimlist[maxcharsize]="";
    unsigned long long *o_indices;
    herr_t o_rtn_val;
    VALUE rank;
    VALUE dimlist;
    VALUE indices;

    Check_Type(regionid,T_FIXNUM);
    Check_Type(object,T_STRING);
    SafeStringValue(object);

    i_regionid = NUM2INT(regionid);
    i_object = RSTRING_PTR(object);

    o_rtn_val = HE5_SWindexinfo(i_regionid, i_object, &o_rank, o_dimlist, &o_indices);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    rank = INT2NUM(o_rank);
    dimlist = rb_str_new2(o_dimlist);
    indices = INT2NUM((long)o_indices);
    return rb_ary_new3(3, rank, dimlist, indices);
}

VALUE
hdfeos5_swchkswath(VALUE mod)
{
    char *i_filename;
    long o_strbufsize;
    long o_rtn_val;

    struct HE5 *he5file;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5, he5file);
    i_filename=he5file->name;

    o_rtn_val = HE5_SWinqswath(i_filename, NULL, &o_strbufsize);
    if( o_rtn_val <= 0) return Qfalse;
    return Qtrue;
}

VALUE
hdfeos5_swchkswathname(VALUE mod)
{
    char *i_filename;
    char *o_swathlist;
    long o_strbufsize;
    long o_rtn_val;
    VALUE rstr;

    struct HE5 *he5file;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5, he5file);
    i_filename=he5file->name;

    o_rtn_val = HE5_SWinqswath(i_filename, NULL, &o_strbufsize);
    if( o_rtn_val <= 0) return Qfalse;
    o_swathlist = ALLOCA_N(char, (o_strbufsize + 1));
    
    o_rtn_val = HE5_SWinqswath(i_filename, o_swathlist, &o_strbufsize);
    if( o_rtn_val <= 0) return Qfalse;
    rstr = rb_str_new(o_swathlist, o_strbufsize);
    return rstr;
}

VALUE
hdfeos5_swsetfield(VALUE mod,VALUE fieldname)
{
    int i_swathid;
    char *i_fieldname;
    struct HE5Sw *he5swath;
    struct HE5SwField *he5field;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Sw, he5swath);
    i_swathid=he5swath->swid;

    Check_Type(fieldname,T_STRING);
    SafeStringValue(fieldname);
    i_fieldname = RSTRING_PTR(fieldname);
    
    he5field = HE5SwField_init(i_fieldname, i_swathid, mod);
    return(Data_Wrap_Struct(cHE5SwField, he5swfield_mark_obj, HE5SwField_free, he5field));
}

VALUE
hdfeos5_swgetfield(VALUE mod)
{
    char *i_fieldname;
    struct HE5SwField *he5field;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fieldname=he5field->name;

    return rb_str_new2(i_fieldname);
}

VALUE 
hdfeos5_sw_whether_in_define_mode(VALUE sw)
{
    int fid;
    hid_t HDFfid = FAIL;
    hid_t gid = FAIL;
    uintn access = 0;
    int status;
    struct HE5Sw *he5swath;
  
    Data_Get_Struct(sw, struct HE5Sw, he5swath);
    fid=he5swath->fid;

    status = HE5_EHchkfid(fid, "HE5_SWcreate", &HDFfid,  &gid, &access);
    if(status != FAIL){
      return Qtrue;
    }else {
      status = HE5_EHchkfid(fid, "HE5_SWattach", &HDFfid,  &gid, &access);
      if(status != FAIL){
        return Qtrue;
      } else {
        return Qnil;
      }
    }
}

VALUE
hdfeos5_sw_path(VALUE sw)
{
    char *i_name;
    struct HE5Sw *he5swath;

    Data_Get_Struct(sw, struct HE5Sw, he5swath);
    i_name=he5swath->name;

    return rb_str_new2(i_name);
}

VALUE
hdfeos5_sw_inqname(VALUE sw)
{
    char *i_name;
    struct HE5Sw *he5swath;
  
    Data_Get_Struct(sw, struct HE5Sw, he5swath);

    i_name=he5swath->name;
    return rb_str_new2(i_name);
}

VALUE
hdfeos5_sw_file(VALUE sw)
{
    struct HE5Sw *he5swath;
  
    rb_secure(4);
    Data_Get_Struct(sw, struct HE5Sw, he5swath);
    return(he5swath->file);
}

VALUE
hdfeos5_var_swath(VALUE field)
{
    struct HE5SwField *he5field;

    rb_secure(4);
    Data_Get_Struct(field, struct HE5SwField, he5field);
    return(he5field->swath);
}

VALUE
hdfeos5_var_inqname(VALUE field)
{
    char *i_name;
    struct HE5SwField *he5field;

    rb_secure(4);
    Data_Get_Struct(field, struct HE5SwField, he5field);

    i_name=he5field->name;
    return rb_str_new2(i_name);
}

VALUE
hdfeos5_swwritefield_char(VALUE mod, VALUE start, VALUE stride, VALUE edge, VALUE data)
{
    hid_t i_swathid;
    char *i_fldname;
    signed long long *c_start;
    unsigned long long *c_stride;
    unsigned long long *c_edge;

    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[maxcharsize];
    char o_dimlist[maxcharsize];
    int  len,i;
    int  c_edge_all=1;
    long l_start, l_edge;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    unsigned char  scalar,*i_data;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    status = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, o_dimlist, NULL);

    Check_Type(start,T_ARRAY);
    if(RARRAY_LEN(start) < i_rank) {
      rb_raise(rb_eHE5Error, "Length of 'start' is too short [%s:%d]",__FILE__,__LINE__);
    }
    c_start=ALLOCA_N(signed long long,i_rank);
    for(i=0; i<i_rank; i++){
      l_start=NUM2INT(RARRAY_PTR(start)[i]);    
      if(l_start < 0) {
	l_start += hs_dims[i];
      }
      c_start[i]=l_start;
    }
    c_stride=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(stride)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    default:
      Check_Type(stride,T_ARRAY);
      if(RARRAY_LEN(stride) < i_rank) {
	  rb_raise(rb_eHE5Error, "Length of 'stride' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
	c_stride[i]=NUM2INT(RARRAY_PTR(stride)[i]);
	if(c_stride[i]==0) {
	  rb_raise(rb_eHE5Error, "stride cannot be zero [%s:%d]",__FILE__,__LINE__);
	}
      }
    }

    Array_to_Cbyte_len_shape(data,i_data,len,shape);
    c_edge=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(edge)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
        c_edge[i]=shape[i];
      }
      c_edge_all=len;
      break;
    default:
      Check_Type(edge,T_ARRAY);
      if(RARRAY_LEN(edge) < i_rank) {
        rb_raise(rb_eHE5Error, "Length of 'end' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
        l_edge= NUM2INT(RARRAY_PTR(edge)[i]);
        if(l_edge < 0) {
	  l_edge +=hs_dims[i];
        }
        c_edge[i]=(l_edge-c_start[i])/c_stride[i]+1;
        c_edge_all=c_edge[i]*c_edge_all;
      }
      if(len == 1 && len != c_edge_all){
	scalar = *i_data;
	i_data = ALLOCA_N(unsigned char,(c_edge_all +1));
	for(i=0;i<c_edge_all;i++){i_data[i]=scalar;}
      } else if(len != c_edge_all) {
          rb_raise(rb_eHE5Error, "lengh of the array does not agree with that of the subset [%s:%d]",__FILE__,__LINE__); 
      }
    }

    status = HE5_SWwritefield(i_swathid, i_fldname, c_start, c_stride, c_edge, i_data);
    if(status != FAIL) return status;
    return Qnil;
}

VALUE
hdfeos5_swwritefield_short(VALUE mod, VALUE start, VALUE stride, VALUE edge, VALUE data)
{
    hid_t i_swathid;
    char *i_fldname;
    signed long long *c_start;
    unsigned long long *c_stride;
    unsigned long long *c_edge;

    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[maxcharsize];
    char o_dimlist[maxcharsize];
    int  len,i;
    int  c_edge_all=1;
    long l_start, l_edge;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    short scalar,*i_data;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    status = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, o_dimlist, NULL);

    Check_Type(start,T_ARRAY);
    if(RARRAY_LEN(start) < i_rank) {
      rb_raise(rb_eHE5Error, "Length of 'start' is too short [%s:%d]",__FILE__,__LINE__);
    }
    c_start=ALLOCA_N(signed long long,i_rank);
    for(i=0; i<i_rank; i++){
      l_start=NUM2INT(RARRAY_PTR(start)[i]);    
      if(l_start < 0) {
	l_start += hs_dims[i];
      }
      c_start[i]=l_start;
    }
    c_stride=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(stride)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    default:
      Check_Type(stride,T_ARRAY);
      if(RARRAY_LEN(stride) < i_rank) {
	  rb_raise(rb_eHE5Error, "Length of 'stride' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
	c_stride[i]=NUM2INT(RARRAY_PTR(stride)[i]);
	if(c_stride[i]==0) {
	  rb_raise(rb_eHE5Error, "stride cannot be zero [%s:%d]",__FILE__,__LINE__);
	}
      }
    }

    Array_to_Cshort_len_shape(data,i_data,len,shape);
    c_edge=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(edge)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
        c_edge[i]=shape[i];
      }
      c_edge_all=len;
      break;
    default:
      Check_Type(edge,T_ARRAY);
      if(RARRAY_LEN(edge) < i_rank) {
        rb_raise(rb_eHE5Error, "Length of 'end' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
        l_edge= NUM2INT(RARRAY_PTR(edge)[i]);
        if(l_edge < 0) {
	  l_edge +=hs_dims[i];
        }
        c_edge[i]=(l_edge-c_start[i])/c_stride[i]+1;
        c_edge_all=c_edge[i]*c_edge_all;
      }
      if(len == 1 && len != c_edge_all){
	scalar = *i_data;
	i_data = ALLOCA_N(short,c_edge_all);
	for(i=0;i<c_edge_all;i++){i_data[i]=scalar;}
      } else if(len != c_edge_all) {
          rb_raise(rb_eHE5Error, "lengh of the array does not agree with that of the subset [%s:%d]",__FILE__,__LINE__); 
      }
    }

    status = HE5_SWwritefield(i_swathid, i_fldname, c_start, c_stride, c_edge, i_data);
    if(status != FAIL) return status;
    return Qnil;
}

VALUE
hdfeos5_swwritefield_int(VALUE mod, VALUE start, VALUE stride, VALUE edge, VALUE data)
{
    hid_t i_swathid;
    char *i_fldname;
    signed long long *c_start;
    unsigned long long *c_stride;
    unsigned long long *c_edge;

    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[maxcharsize];
    char o_dimlist[maxcharsize];
    int  len,i;
    int  c_edge_all=1;
    long l_start, l_edge;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    int scalar,*i_data;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    status = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, o_dimlist, NULL);

    Check_Type(start,T_ARRAY);
    if(RARRAY_LEN(start) < i_rank) {
      rb_raise(rb_eHE5Error, "Length of 'start' is too short [%s:%d]",__FILE__,__LINE__);
    }
    c_start=ALLOCA_N(signed long long,i_rank);
    for(i=0; i<i_rank; i++){
      l_start=NUM2INT(RARRAY_PTR(start)[i]);    
      if(l_start < 0) {
	l_start += hs_dims[i];
      }
      c_start[i]=l_start;
    }
    c_stride=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(stride)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    default:
      Check_Type(stride,T_ARRAY);
      if(RARRAY_LEN(stride) < i_rank) {
	  rb_raise(rb_eHE5Error, "Length of 'stride' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
	c_stride[i]=NUM2INT(RARRAY_PTR(stride)[i]);
	if(c_stride[i]==0) {
	  rb_raise(rb_eHE5Error, "stride cannot be zero [%s:%d]",__FILE__,__LINE__);
	}
      }
    }

    Array_to_Cint_len_shape(data,i_data,len,shape);
    c_edge=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(edge)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
        c_edge[i]=shape[i];
      }
      c_edge_all=len;
      break;
    default:
      Check_Type(edge,T_ARRAY);
      if(RARRAY_LEN(edge) < i_rank) {
        rb_raise(rb_eHE5Error, "Length of 'end' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
        l_edge= NUM2INT(RARRAY_PTR(edge)[i]);
        if(l_edge < 0) {
	  l_edge +=hs_dims[i];
        }
        c_edge[i]=(l_edge-c_start[i])/c_stride[i]+1;
        c_edge_all=c_edge[i]*c_edge_all;
      }
      if(len == 1 && len != c_edge_all){
	scalar = *i_data;
	i_data = ALLOCA_N(int,c_edge_all);
	for(i=0;i<c_edge_all;i++){i_data[i]=scalar;}
      } else if(len != c_edge_all) {
          rb_raise(rb_eHE5Error, "lengh of the array does not agree with that of the subset [%s:%d]",__FILE__,__LINE__); 
      }
    }

    status = HE5_SWwritefield(i_swathid, i_fldname, c_start, c_stride, c_edge, i_data);
    if(status != FAIL) return status;
    return Qnil;
}

VALUE
hdfeos5_swwritefield_long(VALUE mod, VALUE start, VALUE stride, VALUE edge, VALUE data)
{
    hid_t i_swathid;
    char *i_fldname;
    signed long long *c_start;
    unsigned long long *c_stride;
    unsigned long long *c_edge;

    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[maxcharsize];
    char o_dimlist[maxcharsize];
    int  len,i;
    int  c_edge_all=1;
    long l_start, l_edge;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    long scalar,*i_data;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    status = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, o_dimlist, NULL);

    Check_Type(start,T_ARRAY);
    if(RARRAY_LEN(start) < i_rank) {
      rb_raise(rb_eHE5Error, "Length of 'start' is too short [%s:%d]",__FILE__,__LINE__);
    }
    c_start=ALLOCA_N(signed long long,i_rank);
    for(i=0; i<i_rank; i++){
      l_start=NUM2INT(RARRAY_PTR(start)[i]);
      if(l_start < 0) {
	l_start += hs_dims[i];
      }
      c_start[i]=l_start;
    }
    c_stride=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(stride)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    default:
      Check_Type(stride,T_ARRAY);
      if(RARRAY_LEN(stride) < i_rank) {
	  rb_raise(rb_eHE5Error, "Length of 'stride' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
	c_stride[i]=NUM2INT(RARRAY_PTR(stride)[i]);
	if(c_stride[i]==0) {
	  rb_raise(rb_eHE5Error, "stride cannot be zero [%s:%d]",__FILE__,__LINE__);
	}
      }
    }

    Array_to_Clong_len_shape(data,i_data,len,shape);
    c_edge=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(edge)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
        c_edge[i]=shape[i];
      }
      c_edge_all=len;
      break;
    default:
      Check_Type(edge,T_ARRAY);
      if(RARRAY_LEN(edge) < i_rank) {
        rb_raise(rb_eHE5Error, "Length of 'end' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
        l_edge= NUM2INT(RARRAY_PTR(edge)[i]);
        if(l_edge < 0) {
	  l_edge +=hs_dims[i];
        }
        c_edge[i]=(l_edge-c_start[i])/c_stride[i]+1;
        c_edge_all=c_edge[i]*c_edge_all;
      }
      if(len == 1 && len != c_edge_all){
	scalar = *i_data;
	i_data = ALLOCA_N(long,c_edge_all);
	for(i=0;i<c_edge_all;i++){i_data[i]=scalar;}
      } else if(len != c_edge_all) {
          rb_raise(rb_eHE5Error, "lengh of the array does not agree with that of the subset [%s:%d]",__FILE__,__LINE__); 
      }
    }

    status = HE5_SWwritefield(i_swathid, i_fldname, c_start, c_stride, c_edge, i_data);
    if(status != FAIL) return status;
    return Qnil;
}

VALUE
hdfeos5_swwritefield_float(VALUE mod, VALUE start, VALUE stride, VALUE edge, VALUE data)
{
    hid_t i_swathid;
    char *i_fldname;
    signed long long *c_start;
    unsigned long long *c_stride;
    unsigned long long *c_edge;

    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[maxcharsize];
    char o_dimlist[maxcharsize];
    int  len,i;
    int  c_edge_all=1;
    long l_start, l_edge;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    float scalar,*i_data;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    status = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, o_dimlist, NULL);

    Check_Type(start,T_ARRAY);
    if(RARRAY_LEN(start) < i_rank) {
      rb_raise(rb_eHE5Error, "Length of 'start' is too short [%s:%d]",__FILE__,__LINE__);
    }
    c_start=ALLOCA_N(signed long long,i_rank);
    for(i=0; i<i_rank; i++){
      l_start=NUM2INT(RARRAY_PTR(start)[i]);    
      if(l_start < 0) {
	l_start += hs_dims[i];
      }
      c_start[i]=l_start;
    }
    c_stride=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(stride)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    default:
      Check_Type(stride,T_ARRAY);
      if(RARRAY_LEN(stride) < i_rank) {
	  rb_raise(rb_eHE5Error, "Length of 'stride' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
	c_stride[i]=NUM2INT(RARRAY_PTR(stride)[i]);
	if(c_stride[i]==0) {
	  rb_raise(rb_eHE5Error, "stride cannot be zero [%s:%d]",__FILE__,__LINE__);
	}
      }
    }

    Array_to_Cfloat_len_shape(data,i_data,len,shape);
    c_edge=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(edge)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
        c_edge[i]=shape[i];
      }
      c_edge_all=len;
      break;
    default:
      Check_Type(edge,T_ARRAY);
      if(RARRAY_LEN(edge) < i_rank) {
        rb_raise(rb_eHE5Error, "Length of 'end' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
        l_edge= NUM2INT(RARRAY_PTR(edge)[i]);
        if(l_edge < 0) {
	  l_edge +=hs_dims[i];
        }
        c_edge[i]=(l_edge-c_start[i])/c_stride[i]+1;
        c_edge_all=c_edge[i]*c_edge_all;
      }
      if(len == 1 && len != c_edge_all){
	scalar = *i_data;
	i_data = ALLOCA_N(float,c_edge_all);
	for(i=0;i<c_edge_all;i++){i_data[i]=scalar;}
      } else if(len != c_edge_all) {
          rb_raise(rb_eHE5Error, "lengh of the array does not agree with that of the subset [%s:%d]",__FILE__,__LINE__); 
      }
    }

    status = HE5_SWwritefield(i_swathid, i_fldname, c_start, c_stride, c_edge, i_data);
    if(status != FAIL) return status;
    return Qnil;
}

VALUE
hdfeos5_swwritefield_double(VALUE mod, VALUE start, VALUE stride, VALUE edge, VALUE data)
{
    hid_t i_swathid;
    char *i_fldname;
    signed long long *c_start;
    unsigned long long *c_stride;
    unsigned long long *c_edge;

    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[maxcharsize];
    char o_dimlist[maxcharsize];
    int  len,i;
    int  c_edge_all=1;
    long l_start, l_edge;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    double scalar,*i_data;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    status = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, o_dimlist, NULL);

    Check_Type(start,T_ARRAY);
    if(RARRAY_LEN(start) < i_rank) {
      rb_raise(rb_eHE5Error, "Length of 'start' is too short [%s:%d]",__FILE__,__LINE__);
    }
    c_start=ALLOCA_N(signed long long,i_rank);
    for(i=0; i<i_rank; i++){
      l_start=NUM2INT(RARRAY_PTR(start)[i]);    
      if(l_start < 0) {
	l_start += hs_dims[i];
      }
      c_start[i]=l_start;
    }
    c_stride=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(stride)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    default:
      Check_Type(stride,T_ARRAY);
      if(RARRAY_LEN(stride) < i_rank) {
	  rb_raise(rb_eHE5Error, "Length of 'stride' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
	c_stride[i]=NUM2INT(RARRAY_PTR(stride)[i]);
	if(c_stride[i]==0) {
	  rb_raise(rb_eHE5Error, "stride cannot be zero [%s:%d]",__FILE__,__LINE__);
	}
      }
    }

    Array_to_Cdouble_len_shape(data,i_data,len,shape);
    c_edge=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(edge)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
        c_edge[i]=shape[i];
      }
      c_edge_all=len;
      break;
    default:
      Check_Type(edge,T_ARRAY);
      if(RARRAY_LEN(edge) < i_rank) {
        rb_raise(rb_eHE5Error, "Length of 'end' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
        l_edge= NUM2INT(RARRAY_PTR(edge)[i]);
        if(l_edge < 0) {
	  l_edge +=hs_dims[i];
        }
        c_edge[i]=(l_edge-c_start[i])/c_stride[i]+1;
        c_edge_all=c_edge[i]*c_edge_all;
      }
      if(len == 1 && len != c_edge_all){
	scalar = *i_data;
	i_data = ALLOCA_N(double,c_edge_all);
	for(i=0;i<c_edge_all;i++){i_data[i]=scalar;}
      } else if(len != c_edge_all) {
          rb_raise(rb_eHE5Error, "lengh of the array does not agree with that of the subset [%s:%d]",__FILE__,__LINE__); 
      }
    }

    status = HE5_SWwritefield(i_swathid, i_fldname, c_start, c_stride, c_edge, i_data);
    if(status != FAIL) return status;
    return Qnil;
}

VALUE
hdfeos5_swreadfield_char(VALUE mod, VALUE start, VALUE stride, VALUE edge)
{
    hid_t i_swathid;
    char *i_fldname;
    signed long long *c_start;
    unsigned long long *c_stride;
    unsigned long long *c_edge;

    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[10];
    int  i;
    long l_start, l_edge;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    void *o_data;
    VALUE NArray;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    status = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, NULL, NULL);

    Check_Type(start,T_ARRAY);
    if(RARRAY_LEN(start) < i_rank) {
      rb_raise(rb_eHE5Error, "Length of 'start' is too short [%s:%d]",
	       __FILE__,__LINE__);
    }
    c_start=ALLOCA_N(signed long long,i_rank);
    for(i=0; i<i_rank; i++){
      l_start=NUM2INT(RARRAY_PTR(start)[i_rank-1-i]);    
      if(l_start < 0) {
	l_start += hs_dims[i];
      }
      c_start[i]=l_start;
    }
    c_stride=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(stride)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    case T_FALSE:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    case T_TRUE:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    default:
      Check_Type(stride,T_ARRAY);
      if(RARRAY_LEN(stride) < i_rank) {
	  rb_raise(rb_eHE5Error, "Length of 'stride' is too short [%s:%d]",
		   __FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
	c_stride[i]=NUM2INT(RARRAY_PTR(stride)[i_rank-1-i]);
	if(c_stride[i]==0) {
	  rb_raise(rb_eHE5Error, "stride cannot be zero [%s:%d]",__FILE__,__LINE__);
	}
      }
    }
    c_edge=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(edge)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    case T_TRUE:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    case T_FALSE:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    default:
      Check_Type(edge,T_ARRAY);
      if(RARRAY_LEN(edge) < i_rank) {
        rb_raise(rb_eHE5Error, "Length of 'end' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
        l_edge= NUM2INT(RARRAY_PTR(edge)[i_rank-1-i]);
        if(l_edge < 0) {
	  l_edge +=hs_dims[i];
        }
        c_edge[i]=(l_edge-c_start[i])/c_stride[i]+1;
      }
    }

    shape = ALLOCA_N(int,i_rank);
    for(i=0;i<i_rank;i++){
      shape[i_rank-1-i]=c_edge[i];
    }
    Cbyte_to_NArray(NArray,i_rank,shape,o_data);
    status = HE5_SWreadfield(i_swathid, i_fldname, c_start, c_stride, c_edge, o_data);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    OBJ_TAINT(NArray);

    return(NArray);
}

VALUE
hdfeos5_swreadfield_short(VALUE mod, VALUE start, VALUE stride, VALUE edge)
{
    hid_t i_swathid;
    char *i_fldname;
    signed long long *c_start;
    unsigned long long *c_stride;
    unsigned long long *c_edge;

    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[10];
    int  i;
    long l_start, l_edge;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    void *o_data;
    VALUE NArray;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    status = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, NULL, NULL);

    Check_Type(start,T_ARRAY);
    if(RARRAY_LEN(start) < i_rank) {
      rb_raise(rb_eHE5Error, "Length of 'start' is too short [%s:%d]",
	       __FILE__,__LINE__);
    }
    c_start=ALLOCA_N(signed long long,i_rank);
    for(i=0; i<i_rank; i++){
      l_start=NUM2INT(RARRAY_PTR(start)[i_rank-1-i]);    
      if(l_start < 0) {
	l_start += hs_dims[i];
      }
      c_start[i]=l_start;
    }
    c_stride=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(stride)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    case T_FALSE:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    case T_TRUE:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    default:
      Check_Type(stride,T_ARRAY);
      if(RARRAY_LEN(stride) < i_rank) {
	  rb_raise(rb_eHE5Error, "Length of 'stride' is too short [%s:%d]",
		   __FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
	c_stride[i]=NUM2INT(RARRAY_PTR(stride)[i_rank-1-i]);
	if(c_stride[i]==0) {
	  rb_raise(rb_eHE5Error, "stride cannot be zero [%s:%d]",__FILE__,__LINE__);
	}
      }
    }
    c_edge=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(edge)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    case T_TRUE:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    case T_FALSE:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    default:
      Check_Type(edge,T_ARRAY);
      if(RARRAY_LEN(edge) < i_rank) {
        rb_raise(rb_eHE5Error, "Length of 'end' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
        l_edge= NUM2INT(RARRAY_PTR(edge)[i_rank-1-i]);
        if(l_edge < 0) {
	  l_edge +=hs_dims[i];
        }
        c_edge[i]=(l_edge-c_start[i])/c_stride[i]+1;
      }
    }

    shape = ALLOCA_N(int,i_rank);
    for(i=0;i<i_rank;i++){
      shape[i_rank-1-i]=c_edge[i];
    }
    Cshort_to_NArray(NArray,i_rank,shape,o_data);
    status = HE5_SWreadfield(i_swathid, i_fldname, c_start, c_stride, c_edge, o_data);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    OBJ_TAINT(NArray);

    return(NArray);
}

VALUE
hdfeos5_swreadfield_int(VALUE mod, VALUE start, VALUE stride, VALUE edge)
{
    hid_t i_swathid;
    char *i_fldname;
    signed long long *c_start;
    unsigned long long *c_stride;
    unsigned long long *c_edge;

    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[10];
    int  i;
    long l_start, l_edge;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    void *o_data;
    VALUE NArray;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    status = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, NULL, NULL);

    Check_Type(start,T_ARRAY);
    if(RARRAY_LEN(start) < i_rank) {
      rb_raise(rb_eHE5Error, "Length of 'start' is too short [%s:%d]",
	       __FILE__,__LINE__);
    }
    c_start=ALLOCA_N(signed long long,i_rank);
    for(i=0; i<i_rank; i++){
      l_start=NUM2INT(RARRAY_PTR(start)[i_rank-1-i]);    
      if(l_start < 0) {
	l_start += hs_dims[i];
      }
      c_start[i]=l_start;
    }
    c_stride=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(stride)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    case T_FALSE:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    case T_TRUE:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    default:
      Check_Type(stride,T_ARRAY);
      if(RARRAY_LEN(stride) < i_rank) {
	  rb_raise(rb_eHE5Error, "Length of 'stride' is too short [%s:%d]",
		   __FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
	c_stride[i]=NUM2INT(RARRAY_PTR(stride)[i_rank-1-i]);
	if(c_stride[i]==0) {
	  rb_raise(rb_eHE5Error, "stride cannot be zero [%s:%d]",__FILE__,__LINE__);
	}
      }
    }
    c_edge=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(edge)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    case T_TRUE:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    case T_FALSE:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    default:
      Check_Type(edge,T_ARRAY);
      if(RARRAY_LEN(edge) < i_rank) {
        rb_raise(rb_eHE5Error, "Length of 'end' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
        l_edge= NUM2INT(RARRAY_PTR(edge)[i_rank-1-i]);
        if(l_edge < 0) {
	  l_edge +=hs_dims[i];
        }
        c_edge[i]=(l_edge-c_start[i])/c_stride[i]+1;
      }
    }

    shape = ALLOCA_N(int,i_rank);
    for(i=0;i<i_rank;i++){
      shape[i_rank-1-i]=c_edge[i];
    }
    Cint_to_NArray(NArray,i_rank,shape,o_data);
    status = HE5_SWreadfield(i_swathid, i_fldname, c_start, c_stride, c_edge, o_data);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    OBJ_TAINT(NArray);

    return(NArray);
}

VALUE
hdfeos5_swreadfield_long(VALUE mod, VALUE start, VALUE stride, VALUE edge)
{
    hid_t i_swathid;
    char *i_fldname;
    signed long long *c_start;
    unsigned long long *c_stride;
    unsigned long long *c_edge;

    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[10];
    int  i;
    long l_start, l_edge;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    void *o_data;
    VALUE NArray;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    status = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, NULL, NULL);

    Check_Type(start,T_ARRAY);
    if(RARRAY_LEN(start) < i_rank) {
      rb_raise(rb_eHE5Error, "Length of 'start' is too short [%s:%d]",
	       __FILE__,__LINE__);
    }
    c_start=ALLOCA_N(signed long long,i_rank);
    for(i=0; i<i_rank; i++){
      l_start=NUM2INT(RARRAY_PTR(start)[i_rank-1-i]);    
      if(l_start < 0) {
	l_start += hs_dims[i];
      }
      c_start[i]=l_start;
    }
    c_stride=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(stride)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    case T_FALSE:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    case T_TRUE:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    default:
      Check_Type(stride,T_ARRAY);
      if(RARRAY_LEN(stride) < i_rank) {
	  rb_raise(rb_eHE5Error, "Length of 'stride' is too short [%s:%d]",
		   __FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
	c_stride[i]=NUM2INT(RARRAY_PTR(stride)[i_rank-1-i]);
	if(c_stride[i]==0) {
	  rb_raise(rb_eHE5Error, "stride cannot be zero [%s:%d]",__FILE__,__LINE__);
	}
      }
    }
    c_edge=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(edge)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    case T_TRUE:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    case T_FALSE:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    default:
      Check_Type(edge,T_ARRAY);
      if(RARRAY_LEN(edge) < i_rank) {
        rb_raise(rb_eHE5Error, "Length of 'end' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
        l_edge= NUM2INT(RARRAY_PTR(edge)[i_rank-1-i]);
        if(l_edge < 0) {
	  l_edge +=hs_dims[i];
        }
        c_edge[i]=(l_edge-c_start[i])/c_stride[i]+1;
      }
    }

    shape = ALLOCA_N(int,i_rank);
    for(i=0;i<i_rank;i++){
      shape[i_rank-1-i]=c_edge[i];
    }
    Clong_to_NArray(NArray,i_rank,shape,o_data);
    status = HE5_SWreadfield(i_swathid, i_fldname, c_start, c_stride, c_edge, o_data);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    OBJ_TAINT(NArray);

    return(NArray);
}

VALUE
hdfeos5_swreadfield_float(VALUE mod, VALUE start, VALUE stride, VALUE edge)
{
    hid_t i_swathid;
    char *i_fldname;
    signed long long *c_start;
    unsigned long long *c_stride;
    unsigned long long *c_edge;

    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[10];
    int  i;
    long l_start, l_edge;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    void *o_data;
    VALUE NArray;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    status = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, NULL, NULL);

    Check_Type(start,T_ARRAY);
    if(RARRAY_LEN(start) < i_rank) {
      rb_raise(rb_eHE5Error, "Length of 'start' is too short [%s:%d]",
	       __FILE__,__LINE__);
    }
    c_start=ALLOCA_N(signed long long,i_rank);
    for(i=0; i<i_rank; i++){
      l_start=NUM2INT(RARRAY_PTR(start)[i_rank-1-i]);    
      if(l_start < 0) {
	l_start += hs_dims[i];
      }
      c_start[i]=l_start;
    }
    c_stride=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(stride)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    case T_FALSE:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    case T_TRUE:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    default:
      Check_Type(stride,T_ARRAY);
      if(RARRAY_LEN(stride) < i_rank) {
	  rb_raise(rb_eHE5Error, "Length of 'stride' is too short [%s:%d]",
		   __FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
	c_stride[i]=NUM2INT(RARRAY_PTR(stride)[i_rank-1-i]);
	if(c_stride[i]==0) {
	  rb_raise(rb_eHE5Error, "stride cannot be zero [%s:%d]",__FILE__,__LINE__);
	}
      }
    }
    c_edge=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(edge)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    case T_TRUE:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    case T_FALSE:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    default:
      Check_Type(edge,T_ARRAY);
      if(RARRAY_LEN(edge) < i_rank) {
        rb_raise(rb_eHE5Error, "Length of 'end' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
        l_edge= NUM2INT(RARRAY_PTR(edge)[i_rank-1-i]);
        if(l_edge < 0) {
	  l_edge +=hs_dims[i];
        }
        c_edge[i]=(l_edge-c_start[i])/c_stride[i]+1;
      }
    }

    shape = ALLOCA_N(int,i_rank);
    for(i=0;i<i_rank;i++){
      shape[i_rank-1-i]=c_edge[i];
    }
    Cfloat_to_NArray(NArray,i_rank,shape,o_data);
    status = HE5_SWreadfield(i_swathid, i_fldname, c_start, c_stride, c_edge, o_data);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    OBJ_TAINT(NArray);

    return(NArray);
}

VALUE
hdfeos5_swreadfield_double(VALUE mod, VALUE start, VALUE stride, VALUE edge)
{
    hid_t i_swathid;
    char *i_fldname;
    signed long long *c_start;
    unsigned long long *c_stride;
    unsigned long long *c_edge;

    int i_rank;
    hid_t i_ntype = FAIL;
    unsigned long long hs_dims[10];
    int  i;
    long l_start, l_edge;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    void *o_data;
    VALUE NArray;

    struct HE5SwField *he5field;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5SwField, he5field);
    i_fldname=he5field->name;
    i_swathid=he5field->swid;

    status = HE5_SWfieldinfo(i_swathid, i_fldname, &i_rank, hs_dims, &i_ntype, NULL, NULL);

    Check_Type(start,T_ARRAY);
    if(RARRAY_LEN(start) < i_rank) {
      rb_raise(rb_eHE5Error, "Length of 'start' is too short [%s:%d]",
	       __FILE__,__LINE__);
    }
    c_start=ALLOCA_N(signed long long,i_rank);
    for(i=0; i<i_rank; i++){
      l_start=NUM2INT(RARRAY_PTR(start)[i_rank-1-i]);    
      if(l_start < 0) {
	l_start += hs_dims[i];
      }
      c_start[i]=l_start;
    }
    c_stride=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(stride)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    case T_FALSE:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    case T_TRUE:
      for(i=0; i<i_rank; i++){
	  c_stride[i]=1;
      }
      break;
    default:
      Check_Type(stride,T_ARRAY);
      if(RARRAY_LEN(stride) < i_rank) {
	  rb_raise(rb_eHE5Error, "Length of 'stride' is too short [%s:%d]",
		   __FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
	c_stride[i]=NUM2INT(RARRAY_PTR(stride)[i_rank-1-i]);
	if(c_stride[i]==0) {
	  rb_raise(rb_eHE5Error, "stride cannot be zero [%s:%d]",__FILE__,__LINE__);
	}
      }
    }
    c_edge=ALLOCA_N(unsigned long long,i_rank);
    switch(TYPE(edge)){
    case T_NIL:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    case T_TRUE:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    case T_FALSE:
      for(i=0; i<i_rank; i++){
        c_edge[i]=(hs_dims[i]-c_start[i]-1)/c_stride[i]+1;
      }
      break;
    default:
      Check_Type(edge,T_ARRAY);
      if(RARRAY_LEN(edge) < i_rank) {
        rb_raise(rb_eHE5Error, "Length of 'end' is too short [%s:%d]",__FILE__,__LINE__);
      }
      for(i=0; i<i_rank; i++){
        l_edge= NUM2INT(RARRAY_PTR(edge)[i_rank-1-i]);
        if(l_edge < 0) {
	  l_edge +=hs_dims[i];
        }
        c_edge[i]=(l_edge-c_start[i])/c_stride[i]+1;
      }
    }

    shape = ALLOCA_N(int,i_rank);
    for(i=0;i<i_rank;i++){
      shape[i_rank-1-i]=c_edge[i];
    }
    Cdouble_to_NArray(NArray,i_rank,shape,o_data);
    status = HE5_SWreadfield(i_swathid, i_fldname, c_start, c_stride, c_edge, o_data);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    OBJ_TAINT(NArray);

    return(NArray);
}

void
init_hdfeos5sw_wrap(void)
{
    mNumRu = rb_define_module("NumRu");

    /* Difinitions of the classes */;
    cHE5 = rb_define_class_under(mNumRu, "HE5",rb_cObject);
    cHE5Sw = rb_define_class_under(mNumRu, "HE5Sw",rb_cObject);
    cHE5SwField = rb_define_class_under(mNumRu, "HE5SwField",rb_cObject);
    rb_eHE5Error = rb_define_class("HE5Error",rb_eStandardError);

    /* Class Constants Definition */
    /* Difinitions of the HE5 Class */;
    rb_define_method(cHE5, "swcreate", hdfeos5_swcreate, 1);
    rb_define_method(cHE5, "swattach", hdfeos5_swattach, 1);
    rb_define_method(cHE5, "inqswath", hdfeos5_swinqswath, 0);
    rb_define_method(cHE5, "chkswath", hdfeos5_swchkswath, 0);
    rb_define_method(cHE5, "chkswathname", hdfeos5_swchkswathname, 0);
    /* Difinitions of the HE5 Swath Class */
    rb_define_method(cHE5Sw, "defdim", hdfeos5_swdefdim, 2);
    rb_define_method(cHE5Sw, "diminfo", hdfeos5_swdiminfo, 1);
    rb_define_method(cHE5Sw, "mapinfo", hdfeos5_swmapinfo, 2);
    rb_define_method(cHE5Sw, "idxmapinfo", hdfeos5_swidxmapinfo, 2);
    rb_define_method(cHE5Sw, "chunkinfo", hdfeos5_swchunkinfo, 1);
    rb_define_method(cHE5Sw, "defdimmap", hdfeos5_swdefdimmap, 4);
    rb_define_method(cHE5Sw, "defidxmap", hdfeos5_swdefidxmap, 3);
    rb_define_method(cHE5Sw, "defchunk", hdfeos5_swdefchunk, 2);
    rb_define_method(cHE5Sw, "defcomp", hdfeos5_swdefcomp, 2);
    rb_define_method(cHE5Sw, "defcomchunk", hdfeos5_swdefcomchunk, 4);
    rb_define_method(cHE5Sw, "defgeofield", hdfeos5_swdefgeofield, 5);
    rb_define_method(cHE5Sw, "defdatafield", hdfeos5_swdefdatafield, 5);
    rb_define_method(cHE5Sw, "writedatameta", hdfeos5_swwritedatameta, 2);
    rb_define_method(cHE5Sw, "writegeometa", hdfeos5_swwritegeometa, 2);
    rb_define_method(cHE5Sw, "writeattr", hdfeos5_swwriteattr, 4);
    rb_define_method(cHE5Sw, "get_att_", hdfeos5_sw_get_att, 1);
    rb_define_method(cHE5Sw, "inqattrs", hdfeos5_swinqattrs, 0);
    rb_define_method(cHE5Sw, "inqdims", hdfeos5_swinqdims, 1);
    rb_define_method(cHE5Sw, "inqmaps", hdfeos5_swinqmaps, 1);
    rb_define_method(cHE5Sw, "inqidxmaps", hdfeos5_swinqidxmaps, 1);
    rb_define_method(cHE5Sw, "inqdatafields", hdfeos5_swinqdatafields, 1);
    rb_define_method(cHE5Sw, "inqgeofields", hdfeos5_swinqgeofields, 1);
    rb_define_method(cHE5Sw, "inqdatatype", hdfeos5_swinqdatatype, 3);
    rb_define_method(cHE5Sw, "nentries", hdfeos5_swnentries, 1);
    rb_define_method(cHE5Sw, "swdetach", hdfeos5_swdetach, 0);
    rb_define_method(cHE5Sw, "defboxregion", hdfeos5_swdefboxregion, 3);
    rb_define_method(cHE5Sw, "regionindex", hdfeos5_swregionindex, 3);
    rb_define_method(cHE5Sw, "deftimeperiod", hdfeos5_swdeftimeperiod, 3);
    rb_define_method(cHE5Sw, "extractregion", hdfeos5_swextractregion, 2);
    rb_define_method(cHE5Sw, "extractperiod", hdfeos5_swextractperiod, 2);
    rb_define_method(cHE5Sw, "dupregion", hdfeos5_swdupregion, 1);
    rb_define_method(cHE5Sw, "defvrtregion", hdfeos5_swdefvrtregion, 3);
    rb_define_method(cHE5Sw, "setfillvalue", hdfeos5_swsetfillvalue, 3);
    rb_define_method(cHE5Sw, "getfillvalue", hdfeos5_swgetfillvalue, 1);
    rb_define_method(cHE5Sw, "regioninfo", hdfeos5_swregioninfo, 1);
    rb_define_method(cHE5Sw, "periodinfo", hdfeos5_swperiodinfo, 1);
    rb_define_method(cHE5Sw, "updatescene", hdfeos5_swupdatescene, 1);
    rb_define_method(cHE5Sw, "updateidxmap", hdfeos5_swupdateidxmap, 2);
    rb_define_method(cHE5Sw, "geomapinfo", hdfeos5_swgeomapinfo, 1);
    rb_define_method(cHE5Sw, "writegrpattr", hdfeos5_swwritegrpattr, 4);
    rb_define_method(cHE5Sw, "get_grpatt_", hdfeos5_sw_get_grpatt, 1);
    rb_define_method(cHE5Sw, "inqgrpattrs", hdfeos5_swinqgrpattrs, 0);
    rb_define_method(cHE5Sw, "writegeogrpattr", hdfeos5_swwritegeogrpattr, 4);
    rb_define_method(cHE5Sw, "get_geogrpatt_", hdfeos5_sw_get_geogrpatt, 1);
    rb_define_method(cHE5Sw, "inqgeogrpattrs", hdfeos5_swinqgeogrpattrs, 0);
    rb_define_method(cHE5Sw, "prdefine", hdfeos5_prdefine, 4);
    rb_define_method(cHE5Sw, "prwrite", hdfeos5_prwrite, 6);
    rb_define_method(cHE5Sw, "prread", hdfeos5_prread, 4);
    rb_define_method(cHE5Sw, "prreclaimspace", hdfeos5_prreclaimspace, 1);
    rb_define_method(cHE5Sw, "prinquire", hdfeos5_prinquire, 0);
    rb_define_method(cHE5Sw, "prinfo", hdfeos5_prinfo, 1);
    rb_define_method(cHE5Sw, "prwritegrpattr", hdfeos5_prwritegrpattr, 4);
    rb_define_method(cHE5Sw, "pr_get_grpatt_", hdfeos5_pr_get_grpatt, 1);
    rb_define_method(cHE5Sw, "prinqgrpattrs", hdfeos5_prinqgrpattrs, 0);
    rb_define_method(cHE5Sw, "setalias", hdfeos5_swsetalias, 1);
    rb_define_method(cHE5Sw, "dropalias", hdfeos5_swdropalias, 2);
    rb_define_method(cHE5Sw, "inqdfldalias", hdfeos5_swinqdfldalias, 0);
    rb_define_method(cHE5Sw, "aliasinfo", hdfeos5_swaliasinfo, 2);
    rb_define_method(cHE5Sw, "getaliaslist", hdfeos5_swgetaliaslist, 1);
    rb_define_method(cHE5Sw, "fldrename", hdfeos5_swfldrename, 2);
    rb_define_method(cHE5Sw, "mountexternal", hdfeos5_swmountexternal, 2);
    rb_define_method(cHE5Sw, "unmount", hdfeos5_swunmount, 2);
    rb_define_method(cHE5Sw, "readexternal", hdfeos5_swreadexternal, 2);
    rb_define_method(cHE5Sw, "setextdata", hdfeos5_swsetextdata, 3);
    rb_define_method(cHE5Sw, "getextdata", hdfeos5_swgetextdata, 1);
    rb_define_method(cHE5Sw, "indexinfo", hdfeos5_swindexinfo, 2);
    rb_define_method(cHE5Sw, "setfield", hdfeos5_swsetfield, 1);
    /* Original of the HE5 Swath Class */;
    rb_define_method(cHE5Sw, "file", hdfeos5_sw_file, 0);
    rb_define_method(cHE5Sw, "name", hdfeos5_sw_inqname, 0);
    rb_define_method(cHE5Sw, "define_mode?", hdfeos5_sw_whether_in_define_mode, 0);
    /* Difinitions of the HE5 Swath Field Class */;
    rb_define_method(cHE5SwField, "fieldinfo", hdfeos5_swfieldinfo, 0);
    rb_define_method(cHE5SwField, "writefield", hdfeos5_swwritefield, 5);
    rb_define_method(cHE5SwField, "readfield", hdfeos5_swreadfield, 4);
    rb_define_method(cHE5SwField, "writelocattr", hdfeos5_swwritelocattr, 4);
    rb_define_method(cHE5SwField, "get_att_", hdfeos5_swfield_get_att, 1);
    rb_define_method(cHE5SwField, "inqlocattrs", hdfeos5_swinqlocattrs, 0);
    rb_define_method(cHE5SwField, "fldsrch", hdfeos5_swfldsrch, 0);
    rb_define_method(cHE5SwField, "compinfo", hdfeos5_swcompinfo, 0);

    rb_define_method(cHE5SwField, "put_vars_char", hdfeos5_swwritefield_char, 4);
    rb_define_method(cHE5SwField, "put_vars_int", hdfeos5_swwritefield_int, 4);
    rb_define_method(cHE5SwField, "put_vars_long", hdfeos5_swwritefield_long, 4);
    rb_define_method(cHE5SwField, "put_vars_float", hdfeos5_swwritefield_float, 4);
    rb_define_method(cHE5SwField, "put_vars_double", hdfeos5_swwritefield_double, 4);
    rb_define_method(cHE5SwField, "put_vars_short", hdfeos5_swwritefield_short, 4);
    
    rb_define_method(cHE5SwField, "get_vars_char", hdfeos5_swreadfield_char, 3);
    rb_define_method(cHE5SwField, "get_vars_int", hdfeos5_swreadfield_int, 3);
    rb_define_method(cHE5SwField, "get_vars_long", hdfeos5_swreadfield_long, 3);
    rb_define_method(cHE5SwField, "get_vars_float", hdfeos5_swreadfield_float, 3);
    rb_define_method(cHE5SwField, "get_vars_double", hdfeos5_swreadfield_double, 3);
    rb_define_method(cHE5SwField, "get_vars_short", hdfeos5_swreadfield_short, 3);

    /* Original of the HE5 Swath Field Class */;
    rb_define_method(cHE5SwField, "swath", hdfeos5_var_swath, 0);
    rb_define_method(cHE5SwField, "name", hdfeos5_var_inqname, 0);
    rb_define_method(cHE5SwField, "setfield", hdfeos5_swsetfield, 1);
    rb_define_method(cHE5SwField, "getfield", hdfeos5_swgetfield, 0);
}

