#include<string.h>
#include "ruby.h"
#include "narray.h"

/*  functions  */
VALUE hdfeos5_ccharary2obj(char *, int, int);
VALUE hdfeos5_cintary2obj(int *, int, int, int *);
VALUE hdfeos5_clongary2obj(long *, int, int, int *);
VALUE hdfeos5_cfloatary2obj(float *, int, int, int *);
VALUE hdfeos5_csint64ary2obj(signed long long *, int, int, int *);
VALUE hdfeos5_cunsint64ary2obj(unsigned long long *, int, int, int *);

static VALUE ccharary2ary(char *, int, int);

/* kuro: depend on numarray.so */
static VALUE cintary2na(int *, int, int, int *);
static VALUE clongary2na(long *, int, int, int *);
static VALUE cfloatary2na(float *, int, int, int *);
static VALUE csint64ary2na(signed long long *, int, int, int *);
static VALUE cunsint64ary2na(unsigned long long *, int, int, int *);

/*
 * hdfeos5_cxxxary2obj() : convert c xxx type array to ruby object
 *   hdfeos5_ccharary2obj()
 *   hdfeos5_cintary2obj()
 *   hdfeos5_clongary2obj()
 *   hdfeos5_cfloatary2obj()
 */

VALUE
hdfeos5_ccharary2obj(char *cary,int size,int len)
{
    VALUE obj;

    obj = ccharary2ary(cary, size, len);

    return obj;
}

VALUE
hdfeos5_cintary2obj(int *cary,int size,int rank,int *shape)
{
    VALUE obj;

    obj = cintary2na(cary, size, rank, shape);

    return obj;
}

VALUE
hdfeos5_clongary2obj(long *cary,int size,int rank,int *shape)
{
    VALUE obj;

    obj = clongary2na(cary, size, rank, shape);

    return obj;
}

VALUE
hdfeos5_csint64ary2obj(signed long long *cary,int size,int rank,int *shape)
{
    VALUE obj;

    obj = csint64ary2na(cary, size, rank, shape);

    return obj;
}

VALUE
hdfeos5_cunsint64ary2obj(unsigned long long *cary,int size,int rank,int *shape)
{
    VALUE obj;

    obj = cunsint64ary2na(cary, size, rank, shape);

    return obj;
}

VALUE
hdfeos5_cfloatary2obj(float *cary,int size,int rank,int *shape)
{
    VALUE obj;

    obj = cfloatary2na(cary, size, rank, shape);

    return obj;
}

/*
 *  cxxxary2ary() : convert c xxx type array to Array object
 *                  called by cxxxary2obj()
 *   ccharary2ary()
 */
static VALUE
ccharary2ary(char *cary,int size,int len)
{
    VALUE obj, item;
    char *buf, *hd, *ed;
    int i, j;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create Array");

    obj = rb_ary_new2(size/len);
    buf = ALLOCA_N(char, len+1);
    hd = cary;
    for (i = 0; i < size/len; i++) {
        j = len - 1;
        ed = hd + j;
        while ((j >= 0) && (*ed == ' ' || *ed == '\0')) {
            ed--;
            j--;
        }
        if (j >= 0) memcpy(buf, hd, j+1);
        buf[j+1] = '\0';
        item = rb_str_new2(buf);
        rb_ary_push(obj, item);
        hd += len;
    }
    return obj;
}

/* kuro: depend on numarray.so */
/*
 *  cxxxary2na() : convert c xxx type array to NumArray object
 *                 called by cxxxary2obj()
 *   cintary2na() : not implemented
 *   clongary2na() : not implemented
 *   cfloatary2na()
 *   ccomplexary2na() : not implemented
 *   clogicalary2na()
 */

static VALUE
cfloatary2na(float *cary,int size,int rank,int *shape)
{
    VALUE obj;
    struct NARRAY *na;
    int i;
    float *ptr;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create NArray");
    if (rank <= 0)
	rb_raise(rb_eRuntimeError, "cannot create NArray");

    obj = na_make_object(NA_SFLOAT, rank, shape, cNArray);
    GetNArray(obj, na);
    ptr = (float *) NA_PTR(na, 0);

    for (i = 0; i < size; i++) {
	ptr[i] = (float)cary[i];
    }

    return obj;
}

static VALUE
cintary2na(int *cary,int size,int rank,int *shape)
{
    VALUE obj;
    struct NARRAY *na;
    int i;
    int32_t *ptr;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create NArray");
    if (rank <= 0)
	rb_raise(rb_eRuntimeError, "cannot create NArray");

    obj = na_make_object(NA_LINT, rank, shape, cNArray);
    GetNArray(obj, na);
    ptr = (int32_t *) NA_PTR(na, 0);

    for (i = 0; i < size; i++) {
	ptr[i] = (int32_t)cary[i];
    }
    return obj;
}

static VALUE
clongary2na(long *cary,int size,int rank,int *shape)
{
    VALUE obj;
    struct NARRAY *na;
    int i;
    int32_t *ptr;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create NArray");
    if (rank <= 0)
	rb_raise(rb_eRuntimeError, "cannot create NArray");

    obj = na_make_object(NA_LINT, rank, shape, cNArray);
    GetNArray(obj, na);
    ptr = (int32_t *) NA_PTR(na, 0);

    for (i = 0; i < size; i++) {
	ptr[i] = (int32_t)cary[i];
    }
    return obj;
}

static VALUE
csint64ary2na(signed long long *cary,int size,int rank,int *shape)
{
    VALUE obj;
    struct NARRAY *na;
    int i;
    int32_t *ptr;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create NArray");
    if (rank <= 0)
	rb_raise(rb_eRuntimeError, "cannot create NArray");

    obj = na_make_object(NA_LINT, rank, shape, cNArray);
    GetNArray(obj, na);
    ptr = (int32_t *) NA_PTR(na, 0);

    for (i = 0; i < size; i++) {
	ptr[i] = (int32_t)cary[i];
    }
    return obj;
}

static VALUE
cunsint64ary2na(unsigned long long *cary,int size,int rank,int *shape)
{
    VALUE obj;
    struct NARRAY *na;
    int i;
    int32_t *ptr;

    if (cary == NULL)
	rb_raise(rb_eRuntimeError, "cannot create NArray");
    if (rank <= 0)
	rb_raise(rb_eRuntimeError, "cannot create NArray");

    obj = na_make_object(NA_LINT, rank, shape, cNArray);
    GetNArray(obj, na);
    ptr = (int32_t *) NA_PTR(na, 0);

    for (i = 0; i < size; i++) {
	ptr[i] = (int32_t)cary[i];
    }
    return obj;
}
