/**********************************************************************
 
	Copyright (C) 2005- Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/

#include	"machine/include.h"
#include	"memory_debug.h"
#include	"pri_level.h"
#include	"lock_level.h"
#include	"utils.h"
#include	"task.h"
#include	"matrix.h"
#include	"xl.h"
#include	"xlerror.h"
#include	"memory_routine.h"
#include	"change_endian.h"

XL_SEXP *
xl_mxSeparate(XLISP_ENV * env,XL_SEXP * s,XLISP_ENV * a,XL_SYM_FIELD * sf);
void * mx_glay_compress_1(int * ,MATRIX_DH_SET * d1);
void * mx_glay_compress_2(int * ,MATRIX_DH_SET * d1);
void * mx_jpeg_compress_1(int * ,MATRIX_DH_SET * d1);
void * mx_jpeg_compress_2(int * ,MATRIX_DH_SET * d1);

void
init_mxSeparate(XLISP_ENV * env)
{
	set_env(env,l_string(std_cm,"mxSeparate"),
		get_func_prim(xl_mxSeparate,FO_APPLICATIVE,0,2,-1));
}



XL_SEXP *
xl_mxSeparate(XLISP_ENV * env,XL_SEXP * s,XLISP_ENV * a,XL_SYM_FIELD * sf)
{
void * d1;
MATRIX_ALLOC_BLOCK_PARAM * bp;
MATRIX_TOKEN * t;
XL_SEXP * ret;

char * ptr;

XL_SEXP * inp;
char type;
INTEGER64 size;
int rem_size;
char * buffer;
int buffer_len = 0;
MATRIX_DATA_TYPE * tp;

	t = get_env_work(env);
	if ( t == 0 )
		return 0;

	d1 = get_vdata_from_sexp(get_el(s,1));

	if ( d1 == 0 )
		goto inv_param;
	bp = d1;
	if ( bp->h.type != MDT_BLOCK )
		goto inv_param;
	ptr = bp->block;
	rem_size = bp->size;
	ret = 0;
	for ( ; rem_size ; ) {
		type = *ptr++;
		ptr = get_uncompressed_code64(&size,ptr);
		if ( buffer_len < size ) {
			buffer = d_re_alloc(buffer,size);
			buffer_len = size;
		}
		memcpy(buffer,ptr,size);
		ptr += size;
		rem_size -= size;

		tp = get_matrix_data_type(type);
		d1 = (*tp->convert_to_host)(tp,buffer,MD_MMALLOC,0);
		inp = (*tp->md2sexp)(tp,d1);
		switch ( type ) {
		case MDT_STRING:
		case MDT_INT64:
		case MDT_DOUBLE:
			ret = cons(inp,ret);
			break;
		default:
			ret = cons(List(
				n_get_symbol("data"),
				get_sexp_from_dim_code(t->process_node->matrix,t->process_node->dim_code),
				inp,
				-1),
				ret);
			break;
		}
	}
	
	goto end;
/*
type_missmatch:
	ret = get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"mxSeparate"),
		0);
	goto end;
*/
inv_param:
	ret = get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"mxSeparate"),
		n_get_string("invalid parameter in mxSeparate"));
	goto end;
end:
	return ret;
}





