/*  importi.C   */
/*  Copyright 1991 Mountain Math Software  */
/*  All Rights Reserved                    */
#include <stream.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include "cgidbg.h"
#include "sysconst.h"
#include "yacintfc.h"
#include "remcom.h"
#include "import.h"
#include "mkstr.h"

#ifdef INTERACTIVE
#include "array.h"
int ImportData::is_increasing(CheckAction TheAction, OneParameter * param)
{
	switch (TheAction) {
case CheckActionDescribe:
		*Output + OutputHelp <<
		"array elements must be in non decreasing order.\n" ;
		return 1 ;
case CheckActionCheck:
		break ;
default:
		DbgError("ImportData::is_increasing","bad action");
	}
	if (!param) {
		TheLog << "ImportData::is_increasing null param\n" ;
		return 0 ;
	}
	ArrayParam * aryp = param->ArrayP ;
	if (!aryp) {
		TheLog << "ImportData::is_increasing null aryp\n" ;
		return 0 ;
	}
	ArrayData * data = aryp->CurrentValue ;
	if (!data) {
		TheLog << "ImportData::is_increasing null data\n" ;
		return 0 ;
	}
	double prev = 0 ;
	for (int i = 0; i < data->Size; i ++) {
		double temp = data->access(i);
		if (i) if (temp < prev) {
			OutputCurrentChannel << "Array values not in increasing order.\n";
			return 0 ;
		}
		prev = temp ;
	}
	return 1 ;
}

int ImportData::check_format(CheckAction TheAction, OneParameter * param)
{
	switch (TheAction) {
case CheckActionDescribe:
		*Output + OutputHelp <<
		"must contain a `%' followed (not necessarily next) by one of `efoxd'."
		<< "Letters can be upper case.\n"
		<< "Float format characters must be preceded by `l'.\n" 
		<< "Other must not.\n" ;
		return 1 ;
case CheckActionCheck:
		break ;
default:
		DbgError("ImportData::check_format","bad action");
	}
	StringParam * str = param->StringP ;
	int ret =  AsciiInputFile::find_code(str->CurrentValue);
	if (!ret) OutputCurrentChannel << "Unknown foramt `" <<
		str->CurrentValue << "' for ImportData.\n" ;
	return ret ;
}
#endif

void ImportData::ctor()
{
	MaxRepeat = 4096 ;
	if (GetRepeatFlag()) TheRepeatedData = (MachWord *)
		new MachWordCast[MaxRepeat] ;
	TheRepeatedData = 0 ;
	TheRepeatIndex = 0 ;
	TheRepeatLimit = 0 ;
	TheInputFile = 0;
	if (!GetFileName()) return ;
	TheFormat = GetFormat();
	int LastChar = strlen(TheFormat)-1 ;
	WriteBinaryFlag =
		(TheFormat[LastChar] == 'X' || TheFormat[LastChar] == 'x')  ;
	scaled_mach_word = (TheArithType == ArithType::ArithFloat) || 
		(TheFormat[LastChar] == 'S' || TheFormat[LastChar] == 's') ;
	int increase = 1 ;
	TheInputFile = new AsciiInputFile(this);
	use_unsigned = TheInputFile->is_unsigned();
	TheInputFile->open_file(0);
	if (TheInputFile->GetTheFile()) FileName_1 = TheInputFile->file_name();
}

void ImportData::dtor()
{
	delete TheInputFile ;
}


ErrCode ImportData::kernel(int k)
{
/*
 *	LogOut << "ImportData::kernel(" << k << "), Format `" << TheFormat
 *		<< "' for `" << GetName() << "'\n" ;
 */
	if (State.IsError()) return FatalError ;
	TheInputFile->open_file(1);
	if (State.IsError()) return FatalError;
	FileName_1 = TheInputFile->file_name();
	if (GetRepeatFlag() && TheRepeatLimit) for (int i = 0 ; i < k ; i++) {
		if (TheRepeatIndex >= TheRepeatLimit)
			TheRepeatIndex = 0 ;
		if (WriteBinaryFlag)
			WriteInteger(((BinMachWord*)TheRepeatedData)[TheRepeatIndex++]) ;
		else WriteWord(((MachWord*)TheRepeatedData)[TheRepeatIndex++]) ;
	} else {
		for (int i = 0 ; i < k ; i++) {
			const double * val = TheInputFile->GetFieldContents();
			if (State.IsError()) return FatalError ;
			if (! val) {
				if (GetRepeatFlag()) if (TheRepeatedData) {
					TheRepeatLimit = TheRepeatIndex ;
					TheRepeatIndex = 0 ;
					k -= i ;
					break  ;	
				} else {
					TheInputFile->Rewind();
					i-- ;
					continue ;
				}
				return NodeState=EndOfData ;
			}
			double use = *val ;
			// LogOut << "use = " << use << "\n" ;
			int warn = 0 ;
			if (!scaled_mach_word) if (use_unsigned) {
				if (use < 0) use = 0,warn =1 ;
				else if (use > UINT_MAX) use = UINT_MAX,warn =1 ;
			} else {
				if (use < INT_MIN) use = INT_MIN,warn=1 ;
				else if (use > INT_MAX) use = INT_MAX,warn=1 ;
			}
			if (warn) State.Warning("MachWord overflow, hard limited");
			BinMachWord buse ;
			MachWord muse ;
			if (scaled_mach_word) {
				muse = use ;
				if (WriteBinaryFlag) buse = (BinMachWord) muse.val();
			} else if (WriteBinaryFlag) buse = (uint32) use ;
			else {
				muse = (int32) use ; 
			}
			if (GetRepeatFlag()) if (TheRepeatedData) 
			    if (TheRepeatIndex >= MaxRepeat) {
				delete TheRepeatedData ;
				TheRepeatedData = 0 ;
			} else if (WriteBinaryFlag)
				((BinMachWord *)TheRepeatedData)[TheRepeatIndex++]= buse ;
			else ((MachWord*)TheRepeatedData)[TheRepeatIndex++]= muse ;
/*
 *			LogOut << "bf = " << WriteBinaryFlag << ", scal = " <<
 *				scaled_mach_word << "\n" ;
 *			LogOut << "muse = " << muse.val() << ", buse = " << buse << "\n" ;
 */
			if (WriteBinaryFlag) WriteInteger(buse) ;
			else WriteWord(muse) ;
		}
	}
	return OK ;
}

