//-----------------------------------------------------------
// maCom Standart: Matrix Algorithm Components
// maCom C++ wrapper
// Copyright (c) S.V.Eliseev, Forecsys, 2002-2003.
//-----------------------------------------------------------

#if !defined(MACOMCLASSES_H_INCLUDED_)
#define MACOMCLASSES_H_INCLUDED_

#define COM_NO_WINDOWS_H
#include "maCom.h"
#include <stdarg.h>
#include <wchar.h>



#define MAX_INDEX_SIZE 5

class CmaCell;
class CmaMatrix;
class CmaList;
class CmaReadList;
class CmaStream;
class CmaKernel;
class CmaMethod;
class CmaAlgorithm;
class CmaSparseMatrix;
class CmaMatrixIterator;

#define IS_FLAG(val,flag) (((val) & (flag)) == (flag))



#ifdef MA_USE_EXCEPTIONS 
#ifdef MA_CLASS_EXCEPTIONS

class CmaException{
public:
	int maLastError;
	int lineNo;
	char* fileName;
	CmaException(int m_maLastError,int m_lineNo,char* m_fileName){
		maLastError=m_maLastError;
		lineNo=m_lineNo;
		fileName=m_fileName;
	}
};
#define MA_THROW(hr) {maLastError=(hr);if(maLastError) throw CmaException(maLastError,__LINE__,__FILE__);}

#else  //#ifndef MA_CLASS_EXCEPTIONS

#define MA_THROW(hr) {maLastError=(hr);if(maLastError) throw (int)maLastError;}

#endif //#ifdef MA_CLASS_EXCEPTIONS
#else  //#ifndef MA_USE_EXCEPTIONS

#define MA_THROW(hr) maLastError=(hr);

#endif //#ifdef MA_USE_EXCEPTIONS


HRESULT maGetLastError();

extern int printfBufLen;
extern HRESULT maLastError;


//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     Utility classes                                    ----
//----                                                                        ----
//--------------------------------------------------------------------------------


ImaCell* maCellNewInstance();
ImaMatrix* maMatrixNewInstance(maType type);
ImaMatrix* maSubMatrixNewInstance(); 
ImaMatrix* maCompositeMatrixNewInstance(); 

ImaList* maListNewInstance();
ImaFileStream* maTextFileStreamNewInstance();
ImaFileStream* maBinaryFileStreamNewInstance();
ImaClientDataStream* maClientDataStreamNewInstance();

ImaMethod* maMethodNewInstance();
ImaAlgorithm* maAlgorithmNewInstance();
ImaKernel* maKernelNewInstance();

ImaSparseMatrix* maSparseMatrixNewInstance();

ImaList2* maList2NewInstance();



class CmaComponent{
public:
	virtual void setIntf(ImaComponent* val)=0;
public:
	virtual ImaComponent* getIntf() const=0;
	CmaComponent& operator = (CmaComponent& rvalue){
		if(&rvalue){
			ImaComponent* i=getIntf();
			setIntf(rvalue.getIntf());
			if(getIntf()) getIntf()->AddRef();
			if(i) i->Release();
		}
		return *this;
	}
	
	bool isNil() const{
		return getIntf()==0;
	}
	maString GetName() const{
		ImaComponent* c=getIntf();
		if(c) return c->GetName();
		return 0;
	}
	void SetName(maString name) {
		ImaComponent* c=getIntf();
		if(c) c->SetName(name);
	}
	
	HRESULT GetLastError() const;
	
};

class CmaIndex {
protected:
	bool clear;
	long *data; 
	
	
public:
	CmaIndex(long size=MAX_INDEX_SIZE){
		data=(long*)malloc(size*sizeof(long));
		data[0]=0;
		clear=false;
	}
	~CmaIndex(){
		free(data);
	}
	
	CmaIndex& operator[] (long i){
		if (clear){ data[0]=0;clear=false;}
		data[++data[0]]=i;
		return *this;
	}
	maIndex AsIndex(){
		clear=true;
		return (maIndex)data;
	}
	
};


//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaCell                                            ----
//----                                                                        ----
//--------------------------------------------------------------------------------


class CmaCell:public CmaComponent{
protected:
	static double default_double;
	static maString default_string;
	ImaCell* intf;
	
	friend class CmaMethod;
	friend class CmaStream;
	virtual void setIntf(ImaComponent* val){intf=(ImaCell*)val;}
public:
	virtual ImaComponent* getIntf() const{return intf;}
	
	CmaCell (){
		intf=maCellNewInstance();
#ifdef MA_USE_EXCEPTIONS
		if(!intf) MA_THROW(MA_ERR_NOINTERFACE);
#endif
	}
	
	CmaCell (ImaCell *cell){
		
		intf=cell;
		if(intf) intf->AddRef();
	}
	
	CmaCell (const CmaCell &cell){
		intf=(&cell)?cell.intf:0;
		if(intf) intf->AddRef();
	}
	~CmaCell(){ 
		if(intf) intf->Release();
	}

	CmaCell operator = (CmaCell rvalue){
		if(intf) intf->Release();
		intf=rvalue.intf;
		if(intf) intf->AddRef();
		return rvalue;
	}
//	CmaCell* AsCell(){
//		return intf;
//	}
	
	
	maType Type() const{
		maType r=MA_EMPTY;
		if(intf) intf->GetType(&r);
		return r;
	}
	
	CmaCell operator[] (long i);
	CmaCell operator[] (maString i);
	int Size() const;
	
	
	operator int ();
	operator boolean ();
	operator double ();
	maString AsString ();
	
	
	int operator= (int rvalue);
	boolean operator= (boolean rvalue);
	double operator= (double rvalue);
	maString operator= (maString rvalue);

	CmaCell& Default (double rvalue);
	CmaCell& Default (maString rvalue);
	
	CmaMatrix& operator= (CmaMatrix& rvalue);
	CmaList&   operator= (CmaList& rvalue);
	CmaStream& operator= (CmaStream& rvalue);
	CmaAlgorithm& operator= (CmaAlgorithm& rvalue);
	void Copy(CmaCell& source);
	bool  IsEmpty() const;
	void Clear() const;


	

	ImaReadList* AsReadList();
	ImaList* AsList();
	ImaMatrix* AsMatrix();
	ImaStream* AsStream();
	ImaAlgorithm* AsAlgorithm();
	
	
	//new in 1.1
   	void SetConversionStrings(maConvertStrings strings){
		ImaSupportsStringConversion* i;
		if(intf && !intf->QueryInterface(IID_ImaSupportsStringConversion,(void**)&i)){
		  i->SetConversionStrings(&strings);
		  i->Release();
		}
	};


	maConvertStrings GetConversionStrings(){
		maConvertStrings s;
		ImaSupportsStringConversion* i;
		if(intf && !intf->QueryInterface(IID_ImaSupportsStringConversion,(void**)&i)){
		  i->GetConversionStrings(&s);
		  i->Release();
		}
		return s;
	}

	void ClearConversionStrings(){
		ImaSupportsStringConversion* i;
		if(intf && !intf->QueryInterface(IID_ImaSupportsStringConversion,(void**)&i)){
		  i->ClearConversionStrings();
		  i->Release();
		}
	}

};

//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaMatrixIterator                                  ----
//----                                                                        ----
//--------------------------------------------------------------------------------
class CmaMatrixIterator{
	CmaMatrix* src;
	int cookie;
    maIndex curIndex;
	bool completed;
	friend class CmaMatrix;
public:
	CmaMatrixIterator(CmaMatrix& source);
	~CmaMatrixIterator();
	bool First();	
	//	bool Next();
	void operator ++();
	void operator ++(int);
	
	operator bool () const;
	
	bool Completed() const;
	int operator[] (int dimno) const;
};



//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaMatrix                                          ----
//----                                                                        ----
//--------------------------------------------------------------------------------

class CmaMatrix:public CmaComponent{
public:
	long idx[MAX_INDEX_SIZE];
	ImaMatrix* intf;
	friend class CmaCell;
	friend class CmaStream;
	friend class CmaMatrixIterator;
	virtual void setIntf(ImaComponent* val){intf=(ImaMatrix*)val;}

public:
	virtual ImaComponent* getIntf() const{return intf;}
	
	CmaMatrix(){
	intf=0;idx[0]=0;
	}

	CmaMatrix (maType type, CmaIndex& sizes){
		idx[0]=0;
		intf=maMatrixNewInstance(type);
#ifdef MA_USE_EXCEPTIONS
		if(!intf) MA_THROW(MA_ERR_NOINTERFACE);
#endif
		if (intf && &sizes) MA_THROW(intf->Create(sizes.AsIndex()));
		sizes.AsIndex()->count=0;
	}
	
	CmaMatrix (maType type){
		idx[0]=0;
		intf=maMatrixNewInstance(type);
#ifdef MA_USE_EXCEPTIONS
		if(!intf) MA_THROW(MA_ERR_NOINTERFACE);
#endif
	}

	CmaMatrix(maType type,CmaIndex& sizes,maString name,int maxSize){
		idx[0]=0;
		
		intf=maMatrixNewInstance(type);
#ifdef MA_USE_EXCEPTIONS
		if(!intf) MA_THROW(MA_ERR_NOINTERFACE);
#endif
		if(intf) MA_THROW(intf->CreateShared(sizes.AsIndex(),name,maxSize));
		sizes.AsIndex()->count=0;
	}

	ImaMatrix* operator = (ImaMatrix* rvalue){
		if(intf) intf->Release();
		intf=rvalue;
		if(intf) intf->AddRef();
		return rvalue;
	}



	CmaMatrix (ImaMatrix *matrix){
		idx[0]=0;
		//	if(intf) intf->Release();
		intf=matrix;
		if(intf) intf->AddRef();
	}
	CmaMatrix (const CmaMatrix &matrix){
		idx[0]=0;
		
		intf=(&matrix)?matrix.intf:0;
		if(intf) intf->AddRef();
	}
	
	CmaMatrix (CmaCell &cell){
		idx[0]=0;
		if(&cell && cell.getIntf())
		  ((ImaCell*)cell.getIntf())->GetAsComponent(MA_MATRIX,(ImaComponent**)&intf);
	}
	~CmaMatrix(){ if(intf) intf->Release();}
	
	void Resize(CmaIndex& sizes){
		if(intf && &sizes) 
			MA_THROW(intf->Resize(sizes.AsIndex()));
		sizes.AsIndex()->count=0;
	}
	int Dim() const{
		int i=0;
		if(intf) intf->GetDim(&i);
		return i;
	}
	int Size(int dim) const{
		int i=0;
		if(intf) intf->GetSize(dim,&i);
		return i;
	}
	maType Type() const{
		maType i=0;
		if(intf) intf->GetType(&i);
		return i;
	}
	
	void Clear() const{
		if(intf) MA_THROW(intf->Clear());
	}
	
	CmaMatrix& operator[] (long i){
		idx[++idx[0]]=i;
		return *this;
	}
	CmaMatrix& operator[] (CmaIndex& idx){
		if(&idx && idx.AsIndex())
			memcpy(this->idx,idx.AsIndex(),(idx.AsIndex()->count+1)*sizeof(long));
#ifdef MA_USE_EXCEPTIONS
		else MA_THROW(MA_ERR_NOMEMORY);
#endif
		return *this;
	}
	CmaMatrix& operator[] (CmaMatrixIterator& idx){
		if(&idx && idx.curIndex)
			memcpy(this->idx,idx.curIndex,(idx.curIndex->count+1)*sizeof(long));
#ifdef MA_USE_EXCEPTIONS
		else MA_THROW(MA_ERR_NOMEMORY);
#endif
		return *this;
	}
	
	operator double (){
		double d=0.0;
		if(intf) MA_THROW(intf->GetAsDouble((maIndex)idx,&d));
		idx[0]=0;
		return d;
	}
	
	
	int AsInt(){
		int d=0;
		if(intf) MA_THROW(intf->GetAsLong((maIndex)idx,&d));
		idx[0]=0;
		return d;
	}
	
	double AsDouble(){
		double d=0.0;
		if(intf) MA_THROW(intf->GetAsDouble((maIndex)idx,&d));
		idx[0]=0;
		return d;
	}
	
	maString AsString(){
		maString s=0;
		if(intf) MA_THROW(intf->GetAsString((maIndex)idx,&s));
		idx[0]=0;
		return s;
	}
	
	double operator= (double rvalue){
		if(intf) MA_THROW(intf->SetAsDouble((maIndex)idx,rvalue));
		idx[0]=0;
		return rvalue; 
	}
	int operator= (int rvalue){
		if(intf) MA_THROW(intf->SetAsLong((maIndex)idx,rvalue));
		idx[0]=0;
		return rvalue; 
	}
	
	maString operator= (maString rvalue){
		if(intf) MA_THROW(intf->SetAsString((maIndex)idx,rvalue));
		idx[0]=0;
		return rvalue; 
	}
	
	bool IsEmpty(){
		bool b=false;
		if(intf) b= (intf->IsEmpty((maIndex)idx)!=0);
		idx[0]=0;  
		return b;
	}
	void SetEmpty(){
		if(intf) intf->SetEmpty((maIndex)idx);
		idx[0]=0;
	}
	
	
    void SetEmptyDoubleValue(double value) const{  
		if(intf) intf->SetEmptyDoubleValue(value);
	}
	
    void SetEmptyStringValue(maString value) const{
		if(intf) intf->SetEmptyStringValue(value);
	}
    void SetEmptyLongValue(int value) const{
		if(intf) intf->SetEmptyLongValue(value);
	}
    double GetEmptyDoubleValue() const{  //added 11.03.2004
		double d=0.0;
		if(intf) intf->GetEmptyDoubleValue(&d);
		return d;
	}
	
    maString GetEmptyStringValue() const{ //added 11.03.2004
		maString s=0;
		if(intf) intf->GetEmptyStringValue(&s);
		return s;
	}
    int GetEmptyLongValue() const{	//added 11.03.2004
		int l=0;
		if(intf) intf->GetEmptyLongValue(&l);
		return l;
	}
	
	void CacheMatrix(char cacheRead,CmaMatrix& source) const{
		if(intf) MA_THROW(intf->CacheMatrix(cacheRead,source.intf));
	}
	
    void Commit( void) const{
		if(intf) MA_THROW(maLastError=intf->Commit());
	}
	
	void StopCacheing( void) const{
		if(intf) intf->CacheMatrix(0,0);
	}


	//new in 1.1
   	void SetConversionStrings(maConvertStrings strings){
		ImaSupportsStringConversion* i;
		if(intf && !intf->QueryInterface(IID_ImaSupportsStringConversion,(void**)&i)){
		  i->SetConversionStrings(&strings);
		  i->Release();
		}
	};


	maConvertStrings GetConversionStrings(){
		maConvertStrings s;
		ImaSupportsStringConversion* i;
		if(intf && !intf->QueryInterface(IID_ImaSupportsStringConversion,(void**)&i)){
		  i->GetConversionStrings(&s);
		  i->Release();
		}
		return s;
	}

	void ClearConversionStrings(){
		ImaSupportsStringConversion* i;
		if(intf && !intf->QueryInterface(IID_ImaSupportsStringConversion,(void**)&i)){
		  i->ClearConversionStrings();
		  i->Release();
		}
	}
	
};



//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaSubMatrix                                       ----
//----                                                                        ----
//--------------------------------------------------------------------------------

class CmaSubMatrix:public CmaMatrix{
protected:
	friend class CmaCell;
	friend class CmaStream;
	friend class CmaMatrixIterator;
	
	ImaSubMatrix* sintf;
public:
	
	CmaSubMatrix ():CmaMatrix((ImaMatrix*)0){
		intf=maSubMatrixNewInstance();
#ifdef MA_USE_EXCEPTIONS
		if(!intf) MA_THROW(MA_ERR_NOINTERFACE);
#endif
		if(intf) intf->QueryInterface(IID_ImaSubMatrix,(void**)&sintf);
	}
	
	CmaSubMatrix (ImaMatrix *matrix):CmaMatrix(matrix){
		if(intf) intf->QueryInterface(IID_ImaSubMatrix,(void**)&sintf);
#ifdef MA_USE_EXCEPTIONS
		if(!sintf) MA_THROW(MA_ERR_NOINTERFACE);
#endif
	}
	CmaSubMatrix (const CmaSubMatrix &matrix):CmaMatrix(matrix){
		sintf=matrix.sintf;
		if(sintf) sintf->AddRef();
	}
	
	CmaSubMatrix (CmaCell &cell):CmaMatrix(cell){
		
		if(intf){ 
			intf->QueryInterface(IID_ImaSubMatrix,(void**)&sintf);
#ifdef MA_USE_EXCEPTIONS
			if(!sintf) MA_THROW(MA_ERR_NOINTERFACE);
#endif
		}

	}
	~CmaSubMatrix(){ if(sintf) sintf->Release();}
	
	
	ImaMatrix* Parent() const{
		ImaMatrix* m=0;
		if(sintf) sintf->GetParent(&m);
		return m;
	}
	
	void Parent(CmaMatrix& par) const{
		if(sintf ) sintf->SetParent((ImaMatrix*)par.getIntf());
	}
	
    void SetDim(int parentDim,int dim,int size,int *index) const{
		if(sintf) MA_THROW(sintf->SetDim(parentDim,dim,size,index));
	}
    void SetDimBool(int parentDim,int dim,bool *index) const{
		if(sintf) MA_THROW(sintf->SetDimBool(parentDim,dim,(boolean*)index));
	}
	
    void FixDim(int parentDim,int index) const{
		if(sintf) MA_THROW(sintf->FixDim(parentDim,index));	
	}
	
    void SetIdentityDim(int dim) const{
		if(sintf) MA_THROW(sintf->SetIdentityDim(dim));	
	}

	void ClearStructure() const{
		if(sintf) sintf->ClearStructure();
	}
	
	bool VerifyStructure() const{
		if(sintf) return (sintf->VerifyStructure()==MA_NOERROR);
		return true;
	}
	
	
};

//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaCompositeMatrix                                 ----
//----                                                                        ----
//--------------------------------------------------------------------------------

class CmaCompositeMatrix:public CmaMatrix{
protected:
	friend class CmaCell;
	friend class CmaStream;
	friend class CmaMatrixIterator;
	
	ImaCompositeMatrix* cintf;
public:
	
	CmaCompositeMatrix ():CmaMatrix((ImaMatrix*)0){
		intf=maCompositeMatrixNewInstance();
#ifdef MA_USE_EXCEPTIONS
		if(!intf) MA_THROW(MA_ERR_NOINTERFACE);
#endif
		if(intf) intf->QueryInterface(IID_ImaCompositeMatrix,(void**)&cintf);
	}
	
	CmaCompositeMatrix (ImaMatrix *matrix):CmaMatrix(matrix){
		if(intf) intf->QueryInterface(IID_ImaCompositeMatrix,(void**)&cintf);
#ifdef MA_USE_EXCEPTIONS
		if(!cintf) MA_THROW(MA_ERR_NOINTERFACE);
#endif

	}
	CmaCompositeMatrix (const CmaCompositeMatrix &matrix):CmaMatrix(matrix){
		cintf=matrix.cintf;
		if(cintf) cintf->AddRef();
	}
	
	CmaCompositeMatrix (CmaCell &cell):CmaMatrix(cell){
		
		if(intf) intf->QueryInterface(IID_ImaCompositeMatrix,(void**)&cintf);
#ifdef MA_USE_EXCEPTIONS
		if(!cintf) MA_THROW(MA_ERR_NOINTERFACE);
#endif

	}
	~CmaCompositeMatrix(){ if(cintf) cintf->Release();}


	void PutMatrix(CmaIndex& startPos,CmaMatrix &mat) const{
		if(cintf && (&mat)) 
			MA_THROW(cintf->PutMatrix(startPos.AsIndex(),mat.intf));
	}
        
    CmaMatrix GetMatrixAtPos(CmaIndex& pos) const{
		if(cintf){ 
			ImaMatrix* i=0;
			cintf->GetMatrixAtPos(pos.AsIndex(),&i);
			return CmaMatrix(i);
		}
		return CmaMatrix();
	}
        
	maType GetPosType(CmaIndex& pos) const{
		maType t=MA_EMPTY;
		if(cintf)
			cintf->GetPosType(pos.AsIndex(),&t);
		return t;
	}
        
    int MatrixCount() const{
		int count=0;
		if(cintf)
			cintf->MatrixCount(&count);
		return count;
	}

    CmaMatrix GetMatrix(int no) const{
		if(cintf){ 
			ImaMatrix* i=0;
			cintf->GetMatrix(no,&i);
			return CmaMatrix(i);
		}
		return CmaMatrix();
	}
    void DeleteMatrix(int no) const{
		if(cintf)
			cintf->DeleteMatrixno(no);
	}
    void DeleteMatrix(CmaMatrix& mat) const{
		if(cintf)
			cintf->DeleteMatrix(mat.intf);
	}
	
};

//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaSparseMatrix                                    ----
//----                                                                        ----
//--------------------------------------------------------------------------------

class CmaSparseMatrix:public CmaComponent{
protected:
	ImaSparseMatrix* intf;
	friend class CmaCell;
	friend class CmaStream;
	virtual void setIntf(ImaComponent* val){intf=(ImaSparseMatrix*)val;}
public:
	virtual ImaComponent* getIntf() const{return intf;}
	
	CmaSparseMatrix(){
		intf=maSparseMatrixNewInstance();
#ifdef MA_USE_EXCEPTIONS
		MA_THROW(MA_ERR_NOINTERFACE);
#endif
	}
	
	CmaSparseMatrix (ImaSparseMatrix *matrix){
		intf=matrix;
		if(intf) intf->AddRef();
	}
	CmaSparseMatrix (const CmaSparseMatrix &matrix){
		intf=(&matrix)? matrix.intf:0;
		if(intf) intf->AddRef();
	}
	
	CmaSparseMatrix (CmaCell &cell){
		if(&cell && cell.getIntf())
  		  ((ImaCell*)cell.getIntf())->GetAsComponent(MA_SPARSEMATRIX,(ImaComponent**)&intf);
#ifdef MA_USE_EXCEPTIONS
		if(!intf) MA_THROW(MA_ERR_NOINTERFACE);
#endif
	}
	
	void Clear() const{
		if(intf) intf->Clear();
	}
	void Add(int i,int j,double val) const{
		if(intf) intf->Add(i,j,val) ;
	}
	void CreateIndex() const{
		if(intf) intf->CreateIndex() ;
	}
	void DeleteIndex() const{
		if(intf) intf->DeleteIndex() ;
	}
	int ElemCount() const{
		int count=0;
		if(intf) intf->ElemCount( &count) ;
		return count;
	}
	double Elem(int i) const{
		double  elem=0.0;
		if(intf) intf->Elem(i, &elem);
		return elem;
	}
	int ElemIndex(int i,int dim) const{
		int  index=-1;
		if(intf) intf->ElemIndex(i,dim, &index) ;
		return index;
	}
	int ElemNo(int i,int dim) const{
		int  index=-1;
		if(intf) intf->ElemNo(i,dim, &index) ;
		return index;
	}
	int Rows() const{
		int  size=0;
		if(intf) intf->Rows( &size);
		return size;
	}
	int RowSize(int row) const{
		int  count=0;
		if(intf) intf->RowSize(row, &count) ;
		return count;
	}
	double Row( int row,int i) const{
		double  elem=0.0;
		if(intf) intf->Row( row,i, &elem) ;
		return elem;
	}
	int RowIndex(int row) const{
		int  index=-1;
		if(intf) intf->RowIndex(row, &index) ;
		return index;
	}
	int RowElemIndex(int row,int i) const{
		int  index=-1;
		if(intf) intf->RowElemIndex(row,i, &index) ;
		return index;
	}
	int RowElemNo(int row,int i) const{
		int  index=-1;
		if(intf) intf->RowElemNo(row,i, &index) ;
		return index;
	}
	int Cols() const{
		int  size=0;
		if(intf) intf->Cols( &size) ;
		return size;
	}
	int ColSize( int col) const{
		int  count=0;
		if(intf) intf->ColSize( col, &count) ;
		return count;
	}
	double Col( int col,int i) const{
		double  elem=0.0;
		if(intf) intf->Col( col,i, &elem) ;
		return elem;
	}
	int ColIndex(int col) const{
		int  index=-1;
		if(intf) intf->ColIndex(col, &index) ;
		return index;
	}
	int ColElemIndex(int col,int i) const{
		int  index=-1;
		if(intf) intf->ColElemIndex(col,i, &index) ;
		return index;
	}
	int ColElemNo(int col,int i) const{
		int  index=-1;
		if(intf) intf->ColElemNo(col,i, &index) ;    
		return index;
	}
	
	
};

//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaReadList                                        ----
//----                                                                        ----
//--------------------------------------------------------------------------------

class CmaReadList:public CmaComponent{
protected:
	ImaReadList* intf;
	friend class CmaCell;
	friend class CmaStream;
	virtual void setIntf(ImaComponent* val){intf=(ImaReadList*)val;}
public:
	virtual ImaComponent* getIntf() const{return intf;}
	
	CmaReadList (){
		intf=0;
	};
	
	CmaReadList (ImaReadList *list){
		intf=list;
		if(intf) intf->AddRef();
	};
	CmaReadList (const CmaReadList &list){

		intf=(&list)? list.intf : 0;
		if(intf) intf->AddRef();
	};
	
	CmaReadList (CmaCell &cell){
		if(&cell && cell.getIntf()){
			((ImaCell*)cell.getIntf())->GetAsComponent(MA_READLIST,(ImaComponent**)&intf);
		}
	};
	~CmaReadList(){ if(intf) intf->Release();}
	

	ImaReadList* operator = (ImaReadList* rvalue){
		if(intf) intf->Release();
		intf=rvalue;
		if(intf) intf->AddRef();
		return rvalue;
	}

	long Size() const;
	
	CmaCell operator[] (long i) const;
	
	CmaCell operator[] (maString i) const;
	
	maString NameOf(long index) const;
	
	long IndexOf(maString name) const;
	
};

//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaList                                            ----
//----                                                                        ----
//--------------------------------------------------------------------------------


class CmaList:public CmaComponent{
protected:
	ImaList* intf;
	friend class CmaCell;
	friend class CmaStream;
	virtual void setIntf(ImaComponent* val){intf=(ImaList*)val;}
public:
	virtual ImaComponent* getIntf() const{return intf;}
	
	CmaList (){
		intf=maListNewInstance();
#ifdef MA_USE_EXCEPTIONS
		if(!intf) MA_THROW(MA_ERR_NOINTERFACE);
#endif
	}
	
	CmaList (ImaList *list){
		intf=list;
		if(intf) intf->AddRef();
	}
	CmaList (CmaList &list){
		intf=(&list)?list.intf:0;
		if(intf) intf->AddRef();
	}
	
	CmaList (CmaCell &cell){
		intf=0;
		if(&cell && cell.getIntf()){
			if((cell.Type() & MA_LIST) == MA_LIST) {
				((ImaCell*)cell.getIntf())->GetAsComponent(MA_LIST,(ImaComponent**)&intf);
			}else{
				intf=maListNewInstance();
				((ImaCell*)cell.getIntf())->SetAsComponent(MA_LIST,(ImaComponent*)intf);
			}
		}
	}
	
	~CmaList(){ if(intf) intf->Release();}
	
	ImaList* operator = (ImaList* rvalue){
		if(intf) intf->Release();
		intf=rvalue;
		if(intf) intf->AddRef();
		return rvalue;
	}
	
	long Size() const;
	
	CmaCell operator[] (long i) const;
	CmaCell operator[] (maString i) const;
	
	CmaCell GetCell (long i) const;
	CmaCell GetCell (maString i) const;
	
	long AddCell(maString name) const;
	void CreateCells(long count) const;
	
	maString NameOf(long index) const;
	long IndexOf(maString name) const;
	
	
	void Clear() const;
};


//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaMethod                                          ----
//----                                                                        ----
//--------------------------------------------------------------------------------



class CmaMethod:public CmaComponent{
protected:
	ImaMethod* intf;
	friend class CmaCell;
	friend class CmaStream;
	virtual void setIntf(ImaComponent* val){intf=(ImaMethod*)val;}
public:
	
	virtual ImaComponent* getIntf() const{return intf;}
	
	CmaMethod (CmaCell &cell){
		intf=0;
        if(&cell && cell.getIntf())
  		  ((ImaCell*)cell.getIntf())->GetAsComponent(MA_METHOD,(ImaComponent**)&intf);
	}
	
	CmaMethod (ImaMethod *method){
		intf=method;
		if(intf) intf->AddRef();
	}
	CmaMethod(const CmaMethod& method){
		intf=(&method)? method.intf:0;
		if(intf) intf->AddRef();
	}
	
	~CmaMethod(){ if(intf) intf->Release();}
	
	ImaMethodDef* MethodDef() const{
		ImaMethodDef* d=0;
		if(intf) intf->GetMethodDef(&d);
		return d;
	};
	
	CmaCell operator[] (long i) const;
	
	CmaCell operator[] (maString i) const;
	
	CmaList Param () const;
	
	
	
	CmaReadList Input () const;
	CmaReadList Output () const;
	
	CmaCell Input (maString name) const;
	CmaCell Input (int cellno) const;
	
	CmaCell Output (maString name) const;
	CmaCell Output (int cellno) const;

	void Calc () const;
	void CalcCell (int cellno, CmaIndex& index, CmaCell& cell) const;
	
};

//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaKernel                                          ----
//----                                                                        ----
//--------------------------------------------------------------------------------


class CmaKernel{
protected:
	ImaKernel* intf;
	void VPrintF (maString buf,maString format, va_list varg);
public:
	ImaKernel* getIntf(){return intf;}
	
	CmaKernel();
	CmaKernel(maString logName);
	~CmaKernel();
	
	void LoadLibraryByName (maString clsname);
	void LoadLibraryByClsid (maString clsid);
	void RegisterLibrary(ImaLibrary* lib);
	void UnloadLibraries();
	
	void OpenLogFile(maString name);
	
	CmaStream GetDebugStream ();
    void SetDebugStream (CmaStream stream);
	
	void LogError(ImaComponent *sender,HRESULT ecode,maString message);
	void LogMessage( ImaComponent *sender,maString message);
	
	void DebugLevel(int level);
	int DebugLevel();
	
	void LogMemoryReport();
	
	void SetProgressHandler(ImaProgressHandler *handler);
	
	bool Progress(double percent,maString message=0);
	void SetMinProgressStep(double minProgressStep);
	
	void Message (maString format, ...);
	void Error (int eCode,maString format, ...);
	
	
};


//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaAlgorithm                                       ----
//----                                                                        ----
//--------------------------------------------------------------------------------



class CmaAlgorithm:public CmaComponent{
protected:
	ImaAlgorithm* intf;
	friend class CmaCell;
	friend class CmaStream;
	virtual void setIntf(ImaComponent* val){intf=(ImaAlgorithm*)val;}
public:
	
	virtual ImaComponent* getIntf() const{return intf;}
	
	
	CmaAlgorithm(CmaCell &cell){
		intf=0;
        if(&cell && cell.getIntf())
  		  ((ImaCell*)cell.getIntf())->GetAsComponent(MA_ALGORITHM,(ImaComponent**)&intf);

	}

	CmaAlgorithm(maString name, CmaKernel* kernel);
	
	CmaAlgorithm(ImaAlgorithm* a){
		//	if(intf) intf->Release();
		intf=a;
		if(intf) intf->AddRef();
	}
	CmaAlgorithm(const CmaAlgorithm& a){
		intf=(&a)?a.intf:0;
		if(intf) intf->AddRef();
	}
	
	~CmaAlgorithm(){if(intf) intf->Release();}

	ImaAlgorithm* operator = (ImaAlgorithm* rvalue){
		if(intf) intf->Release();
		intf=rvalue;
		if(intf) intf->AddRef();
		return rvalue;
	}

	
	maString GetDescription();
	
	CmaCell operator[] (long i);
	CmaCell operator[] (maString i);
	
	CmaList Param ();
	
	CmaMethod Method (maString name);
	void SetMethod(ImaMethodDef *mdef);
	
	void Verify ();
	void Verify(int cellno);
	void Verify(maString name);
};


//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaStream                                          ----
//----                                                                        ----
//--------------------------------------------------------------------------------


class CmaStream:public CmaComponent{
protected:
	ImaStream* intf;
	friend class CMaCell;
	virtual void setIntf(ImaComponent* val){intf=(ImaStream*)val;}
	
public:
	virtual ImaComponent* getIntf() const{return intf;}
	
	CmaStream(maType type, maString location){
		bool text=(type & MA_FILE_TEXT)==MA_FILE_TEXT;
		type=type & (~MA_FILE_TEXT);
		if(text)
		  intf=maTextFileStreamNewInstance();
		else
		  intf=maBinaryFileStreamNewInstance();

#ifdef MA_USE_EXCEPTIONS
		if(!intf) MA_THROW(MA_ERR_NOINTERFACE);
#endif
		if(intf)
			MA_THROW(((ImaFileStream*)intf)->Create(location,type));
	}

	CmaStream(ImaDataHandler* conn){
		intf=maClientDataStreamNewInstance();
#ifdef MA_USE_EXCEPTIONS
		if(!intf) MA_THROW(MA_ERR_NOINTERFACE);
#endif
		if(intf)
			MA_THROW(((ImaClientDataStream*)intf)->SetDataConnection(conn));
	}

	CmaStream(ImaStream* i=0){
		intf=i;
		if(intf)
			intf->AddRef();
	}
	
	CmaStream(CmaCell& cell){
		intf=0;
        if(&cell && cell.getIntf())
  		  ((ImaCell*)cell.getIntf())->GetAsComponent(MA_STREAM,(ImaComponent**)&intf);
	}
	
	~CmaStream(){ if(intf) intf->Release();}

	CmaStream& operator = (ImaStream* rvalue){
		if(intf) intf->Release();
		intf=rvalue;
		if(intf) intf->AddRef();
		return *this;
	}

	
	void Create(maType type, maString location){
		if(!intf){
			bool text=(type & MA_FILE_TEXT)==MA_FILE_TEXT;
			type=type & (~MA_FILE_TEXT);
			if(text)
				intf=maTextFileStreamNewInstance();
			else
				intf=maBinaryFileStreamNewInstance();
		}
#ifdef MA_USE_EXCEPTIONS
		if(!intf) MA_THROW(MA_ERR_NOINTERFACE);
#endif

		if(intf)
			MA_THROW(((ImaFileStream*)intf)->Create(location,type));
	};
	
	void Open(){
		if(intf) intf->Open();
	}
	void Close(){
		if(intf) intf->Close();
	}
	void Flush(){
		if(intf) intf->Flush();
	}
	
	CmaStream& newLine(CmaStream& rvalue){
		if(intf) intf->NewLine();
		return rvalue;
	}
	CmaStream& newField(CmaStream& rvalue){
		if(intf) intf->NewField();
		return rvalue;
	}
	
	void newLine(){
		if(intf) intf->NewLine();
	}
	void newField(){
		if(intf) intf->NewField();
	}
	
	maStreamOptions GetOptions(){
		maStreamOptions ret;
		if(intf) MA_THROW(intf->GetOptions(&ret));
		return ret;
	}

	void PushOptions(maStreamOptions& opt){
		if(intf) MA_THROW(intf->PushOptions(&opt));
	}
	
	void PopOptions(){
		if(intf) intf->PopOptions();
	}
	
	CmaStream& operator<< (int data){
		if(intf) MA_THROW(intf->WriteLong(data));
		return *this;
	}
	
	CmaStream& operator<< (double data){
		if(intf) MA_THROW(intf->WriteDouble(data));
		return *this;
	}
	
	CmaStream& operator<< (maString data){
		if(intf) MA_THROW(intf->WriteStr(data));
		return *this;
	}
	CmaStream& operator<< (CmaComponent &data){
		if(intf) MA_THROW(intf->WriteComponent(data.getIntf()));
		return *this;
	}
	
	CmaStream& operator>> (int &data){
		if(intf) MA_THROW(intf->ReadLong(&data));
		return *this;
	}
	CmaStream& operator>> (double &data){
		if(intf) MA_THROW(intf->ReadDouble(&data));
		return *this;
	}
	CmaStream& operator>> (maString &data){
		if(intf) MA_THROW(intf->ReadStr(&data));
		return *this;
	}
	CmaStream& operator>> (CmaCell &data){
		ImaCell* r;
		if(intf){
			if(&data)
				MA_THROW(intf->ReadComponent((ImaComponent**)&(data.intf)))
			else{
				r=0;
				MA_THROW(intf->ReadComponent((ImaComponent**)&r));
				data= *(new CmaCell(r));
			};
			
		}
		return *this;
	}
	
	CmaStream& operator>> (CmaMatrix &data){
		ImaMatrix* r=0;
		if(intf){ 
			if(&data)
				MA_THROW(intf->ReadComponent((ImaComponent**)&(data.intf)))
			else{
				r=0;
				MA_THROW(intf->ReadComponent((ImaComponent**)&r));
				data= *(new CmaMatrix(r));
			};
		}
		return *this;
	}
	
	CmaStream& operator>> (CmaList &data){
		ImaList* r=0;
		if(intf){ 
			if(&data)
				MA_THROW(intf->ReadComponent((ImaComponent**)&(data.intf)))
			else{
				r=0;
				MA_THROW(intf->ReadComponent((ImaComponent**)&r));
				data= *(new CmaList(r));
			};
		}
		return *this;
	}
	CmaStream& operator>> (CmaMethod &data){
		ImaMethod* r=0;
		if(intf){ 
			if(&data)
				MA_THROW(intf->ReadComponent((ImaComponent**)&(data.intf)))
			else{
				r=0;
				MA_THROW(intf->ReadComponent((ImaComponent**)&r));
				data= *(new CmaMethod(r));
			};
		}
		return *this;
	}
	CmaStream& operator>> (CmaAlgorithm &data){
		ImaAlgorithm* r=0;
		if(intf){ 
			if(&data)
				MA_THROW(intf->ReadComponent((ImaComponent**)&(data.intf)))
			else{
				r=0;
				MA_THROW(intf->ReadComponent((ImaComponent**)&r));
				data= *(new CmaAlgorithm(r));
			};
		}
		return *this;
	}
	
	
	
	// Добавляет в буфер результат форматной печати (не более inc_portion байт)
	void VPrintF (maString format, va_list varg) {
		if(printfBufLen==0) printfBufLen=2048;
		maString buf=new wchar_t[printfBufLen+1];
		
		// форматная печать в строку
		int ret = _vsnwprintf(buf, printfBufLen, format, varg);
		if (ret>=0) {
			buf[ret] = L'\0';
			intf->WriteStr(buf);
		}
		delete[] buf;
	}
	
	// Добавляет в буфер результат форматной печати (не более inc_portion байт)
	void PrintF (maString format, ...) {
		va_list varg;
		va_start (varg, format);
		if (format && *format)
			VPrintF (format, varg);
		va_end (varg);
	}
	
	
};



//--------------------------------------------------------------------------------
//----                                                                        ----
//----                     CmaList2                                           ----
//----                                                                        ----
//--------------------------------------------------------------------------------
/*

class CmaList2:public CmaComponent{
protected:
	ImaList2* intf;
	int curI;

	friend class CmaCell;
	friend class CmaStream;
	virtual void setIntf(ImaComponent* val){intf=(ImaList2*)val;}
public:
	virtual ImaComponent* getIntf() const{return intf;}
	
	CmaList2 (){
		intf=maList2NewInstance();
		if(!intf) MA_THROW(MA_ERR_NOINTERFACE);
	}
	
	CmaList2 (ImaList2 *list){
		intf=list;
		if(intf) intf->AddRef();
	}
	CmaList2 (CmaList2 &list){
		intf=(&list)?list.intf:0;
		if(intf) intf->AddRef();
	}
	
	CmaList2 (CmaCell &cell){
		intf=0;
		if(&cell && cell.getIntf()){
			if((cell.Type() & MA_LIST) == MA_LIST) {
				((ImaCell*)cell.getIntf())->GetAsComponent(MA_LIST,(ImaComponent**)&intf);
			}else{
				intf=maList2NewInstance();
				((ImaCell*)cell.getIntf())->SetAsComponent(MA_LIST,(ImaComponent*)intf);
			}
		}
	}
	
	~CmaList2(){ if(intf) intf->Release();}
	
	ImaList2* operator = (ImaList2* rvalue){
		if(intf) intf->Release();
		intf=rvalue;
		if(intf) intf->AddRef();
		return rvalue;
	}
	
	int Size() {
		int s=0;
		if(intf){
			if(curI){
				ImaList* l;
				intf->GetAsComponent(curI,MA_LIST,(ImaComponent**)&l);
				if(l) l->GetSize(&s);
			}else
				intf->GetSize(&s);
		}
		return s;
	}
	
	CmaList2 operator[] (long i);
	CmaList2 operator[] (maString i);
	
	CmaCell GetCell (long i);
	CmaCell GetCell (maString i);
	
	long AddCell(maString name);
	void CreateCells(long count);
	
	maString NameOf(long index);
	long IndexOf(maString name);
	
	
	void Clear();


	
	maType Type(){
		maType r=MA_EMPTY;
		if(intf){
			if(curI)
				intf->GetType(curI,&r);
			else
				r=MA_LIST;
		}
		return r;
	}
	
	
	operator int ();
	operator boolean ();
	operator double ();
	maString AsString ();
	
	
	int operator= (int rvalue);
	boolean operator= (boolean rvalue);
	double operator= (double rvalue);
	maString operator= (maString rvalue);

	CmaCell& Default (double rvalue);
	CmaCell& Default (maString rvalue);
	
	CmaMatrix& operator= (CmaMatrix& rvalue);
	CmaList&   operator= (CmaList& rvalue);
	CmaStream& operator= (CmaStream& rvalue);
	CmaAlgorithm& operator= (CmaAlgorithm& rvalue);
	void Copy(CmaCell& source);
	bool  IsEmpty();


	

	ImaReadList* AsReadList();
	ImaList* AsList();
	ImaMatrix* AsMatrix();
	ImaStream* AsStream();
	ImaAlgorithm* AsAlgorithm();

};
*/



#endif //MACOMCLASSES_H_INCLUDED_
