// aplvalue.cpp

#include "StdAfx.h"
#include "aplValue.h"
#include "StepData.h"
#include <stdlib.h> 

#ifdef _MFC_VER
	//#include <AccCtrl.h>
	#include <Aclapi.h>
#endif


extern double MaxDoubleVal;

//************************************************************************
#ifdef _UNICODE
CaplValue::CaplValue(const char* str):type(aplNOTYPE), m_bUseExternalString(false)
{
	CaplStringAdapter ad(str);
	Set((LPCTSTR)ad);
}
#endif
#ifdef QSTRING_H
CaplValue::CaplValue(const QString &str):type(aplNOTYPE), m_bUseExternalString(false)
{
	Set(QS2CS(str));
}
#endif

void CaplValue::Print(CString &str, pCaplInstance *instmap, int instmapsize, aplRusSaveMode mode, CaplAttr *attr, bool bSaveRealId)
{
	str=_T("");
	CString buf;
	switch (type)
	{
		case aplINTEGER: str.Format(_T("%i"),ival); break;
		case aplREAL: 
			//str.Format("%1.15f",rval); break;
			//str.Format("%#4.10G",rval); break;
			str.Format(_T("%1.15G"),rval); // до 03/02/2010 была точность %#.8G. Заменил на 15G. ДИВ
			break;
		case aplBOOL: if(bval) str=_T(".T."); else str=_T(".F."); break;
		case aplLOGICAL: 
			switch(lval)
			{
			case APL_FALSE: str=_T(".F.");break;
			case APL_TRUE: str=_T(".T.");break;
			default:str=_T(".U.");break;
			}
			break;
		case aplSTRING: 
			{
				if(attr!=0)
				{
					if(attr->type==aplENUMERATION)
					{
						if(0==sval) str=_T("$");
						else if(sval[0]==_T('\0')) str=_T("$");
						else
						{
							str=_T(".");
							str+=sval;
							str.MakeUpper();
							str+=_T(".");
						}
						break;
					}
				}
				str += _T("'");
				CString stroka = sval;
				stroka.Replace(_T("'"),_T("''"));
				stroka.Replace(_T("\\"),_T("\\\\"));
				stroka.Replace(_T("\n"),_T("\\X\\0A"));
				stroka.Replace(_T("\r"),_T("\\X\\0D"));
				if (mode == aplWIN7BIT)
				{
					ConvertP21String(stroka, aplWIN, aplWIN7BIT);
				}

				str += stroka;
				str += _T("'");
			}
			break;
		case aplINSTANCE: 
			if (bSaveRealId)
			{
				if(instval!=0)
				{
					str.Format(_T("#%i"),instval->GetId());
					if(instval->GetType()==0 )str += _T("$");
					else if(instval->IsDeleted())str += _T("&");
				}
				else str = _T("$");
			}
			else
			{
				if(instmap==0) str.Format(_T("#%p"), instval);
				else
				{
					int instid=aplQuickFindP((void**)instmap, instmapsize, instval);
					if(instid==-1)	str = _T("$");
					else str.Format(_T("#%i"), instid+1);
				}
			}
			break;
		case aplBINARY: if(binval!=0) str.Format(_T("SIZE = %i"), binval->m_Size); break;
		case aplINTEGRATEDBIN: str.Format(_T("##%i"),intbinval->blobId); break;
		case aplAGGR: 
			str = _T("(");
			for (int i=0;i<aggrval->GetSize();i++)
			{
				if(i>0) str += _T(",");
				aggrval->GetByIndex(i)->Print(buf,instmap, instmapsize, mode,0,bSaveRealId);
				str+=buf;
			}
			str += _T(")");
			break;
		
		default: break; // Чтобы не ругался  QtCreator
	}
}

void CaplValue::PrintDebugInfo(CString &str)
{
	Print(str);
	if(type==aplINSTANCE && 0!=instval)
	{
		CString buf;
		buf.Format(_T("   id=%i"), instval->GetId());
		str+=buf;
		str+=_T("   type=");
		CaplEntity *ent = instval->GetType();
		if (0==ent) str += _T("0"); else str+=ent->name;
	}
}
//***********************************************************
bool CaplValue::ReadFromString(LPCTSTR str, int &pos, pCaplInstance *instmap, int instmapsize)
{
	Clear();
	if(aplIsStringEmpty(str)) return true;
	CString buf,buf1;
	int i,k;
	CaplInstance *inst;
	aplGetWord(str,pos,buf);
	if(buf.GetLength()<1) return true;

	if(buf[0]==_T('\''))
	{
		buf1=buf.Mid(1,buf.GetLength()-2);
		Set(buf1);
		return true;
	}
	if(buf[0]==_T(')'))
	{
		return false;
	}
	if(buf[0]==_T('#'))
	{
		i=_atoi(LPCTSTR(buf)+1);
		if(instmap!=0)
		{
			if(i<=instmapsize)
			{
				inst=instmap[i];
				Set(inst);
			}
		}
		return true;
	}
	if(buf[0]==_T('('))
	{
		CaplAggr aggr;
		CaplValue val;
		while(val.ReadFromString(str, pos,instmap, instmapsize))
		{
			aggr.Add(val);
			aplGetWord(str,pos,buf);
			if(buf != _T(",")) break;
		}
		Set(aggr);
		return true;
	}
	i=buf.Find(_T("."));
	if(i==-1)
	{
		k=_atoi(LPCTSTR(buf));
		Set(k);
		return true;
	}
	if((buf[0]==_T('.'))&&(buf[buf.GetLength()-1]==_T('.')))
	{
		if(buf.GetLength()==3)
		{
			if(buf[1]==_T('T')) Set(true);
			else if(buf[1]==_T('t')) Set(true);
			else if(buf[1]==_T('F')) Set(false);
			else if(buf[1]==_T('f')) Set(false);
			else Clear();
			return true;
		}

	}
	if(buf.ReverseFind(_T('.'))==i)
	{
		double fval=__atof(LPCTSTR(buf));
		Set(fval);
		return true;
	}
	return false;
}
//************************************************************************
// чтение атрибутов из строки файла stp ISO-10303-21
bool CaplValue::ReadFromP21String(CString &input_string, int &pos, pCaplInstance *instmap, int instmapsize)
{
	Clear();
	if (input_string==_T("")) return false;
	CString token;
	int i,k;
	aplGetWord(input_string,pos,token);
	if(token.GetLength()<1) return true;

	if (token == _T('$') || token == _T('*'))
	{
		type = aplNOTYPE;
		return true;
	}
	if(token[0]==_T('\''))
	{
		CString buf1 = token.Mid(1,token.GetLength() - 2);
		ConvertP21String(buf1, aplWIN7BIT, aplWIN);	// преобразуем русские буквы
		Set(buf1);
		return true;
	}
	if(token[0]==_T(')'))
	{
		return false;
	}
	if(token[0]==_T('#'))
	{
		long InstanceId = __atol(LPCTSTR(token)+1);
		if(instmap != 0) Set(instmap[InstanceId]);
		return true;
	}
	if(token[0]==_T('('))
	{
		CaplAggr aggr;
		CaplValue val;
		while(val.ReadFromP21String(input_string, pos,instmap, instmapsize))
		{
			aggr.Add(val);
			aplGetWord(input_string,pos,token);
			if(token != _T(",")) break;
		}
		Set(aggr);
		return true;
	}
	i = token.Find(_T("."));
	if(i == -1)
	{
		// небольшая проверочка
		int save_pos = pos;
		CString old_token=token;
		aplGetWord(input_string, save_pos, token);
		if (token == _T("("))
		{
			pos = save_pos;
			ReadFromP21String(input_string, pos,instmap, instmapsize);
			aplGetWord(input_string, pos, token);
		}
		else
		{
			k = _atoi(LPCTSTR(old_token));
			Set(k);
		}
		return true;
	}
	if (token.GetLength() > 1)
	{
		if((token[0]==_T('.'))&&(token[token.GetLength()-1]!=_T('.'))) // ЯАИ:  затычка на случай enum c пробелами
		{
			if(token[1]<_T('0') ||  token[1]>_T('9')) // это не цифра
			{
				CString sAdd;
				//TCHAR *input_string, int &pos
				int pos1=pos;
				while(true)
				{
					TCHAR c = input_string[pos1];
					if(c==_T('.'))
					{
						sAdd+=c;
						pos=pos1+1;
						sAdd.MakeLower();
						token+=sAdd;
						break;
					}
					else if(c==_T('\0')||c==_T(',')||c==_T('(')||c==_T(')')||c==_T(';')) break;
					sAdd+=c;
					pos1++;
				}
			}
		}


		if((token[0]==_T('.'))&&(token[token.GetLength()-1]==_T('.')))
		{
			if(token.GetLength() == 2)  // На случай кривой аписи пустого ENUM
			{
				type = aplNOTYPE;
				return true;
			}
			else if(token.GetLength() == 3)
			{
				if(token[1]==_T('t')) Set((char)APL_TRUE);
				else if(token[1]==_T('f')) Set((char)APL_FALSE);
				else if(token[1]==_T('u')) Set((char)APL_UNKNOWN);
				return true;
			}
			else
			{
				// отрезание точек
				token.Delete(0, 1);token.Delete(token.GetLength() - 1, 1);
				Set(token);
				return true;
			}
		}
	}
	if(token.ReverseFind(_T('.'))==i)
	{
		double fval=__atof(LPCTSTR(token));
		Set(fval);
		return true;
	}
	return false;
}
//***********************************************************

void CaplValue::Clear()
{
	switch (type)
	{
	case aplSTRING:
		{
			if (sval!=0)
			{
				if(!m_bUseExternalString) delete []sval;
				sval=0;
			}
			break;
		}
	case aplAGGR:	if (aggrval!=0) {aggrval->Clear(); delete aggrval; aggrval=0;} break;
	case aplINTEGRATEDBIN:	if (intbinval!=0) {intbinval->Clear(); delete intbinval; intbinval=0;} break;
	case aplBINARY:	if (binval!=0) {binval->Clear(); delete binval; binval=0;} break;
	default:  break;
	}
	rval=0;
	ival=0;
	type=aplNOTYPE;
	m_bUseExternalString=false;
}
//************************************************************************
bool CaplValue::Get(CaplAggr &rez) const
{
	rez.Clear();
	if(type==aplAGGR){
		if(aggrval==0)return false;
		rez.Append(*aggrval);
		return true;
	}
	else return false;
}
//************************************************************************
bool CaplValue::Get(CaplIntegrBINVal &rez) const
{
	rez.Clear();
	if(type==aplINTEGRATEDBIN){
		if(intbinval==0)return false;
		rez=(*intbinval);
		return true;
	}
	else return false;
}
//************************************************************************
bool CaplValue::Get(aplExtent &rez) const
{
	rez.Clear();
	if(type!=aplAGGR)return false;
	if(aggrval==0)return false;
	CaplInstance *inst;
	int i,k=aggrval->GetSize();
	for(i=0; i<k;i++)
	{
		aggrval->GetByIndex(i,inst);
		if(inst!=0) rez.Add(inst);
	}
	return true;
}
//************************************************************************
bool CaplValue::Get(bool &rez) const
{
	rez=false; 
	if(type==aplBOOL) {rez=bval; return true;} 
	else if(type==aplLOGICAL) {rez=lval==APL_TRUE; return true;}
	else return false;
}
//************************************************************************
bool CaplValue::Get(char &rez) const
{
	rez=APL_UNKNOWN; 
	if(type==aplLOGICAL) {rez=lval; return true;} 
	else if(type==aplBOOL) {rez=bval?APL_TRUE:APL_FALSE; return true;} 
	else return false;
}
//************************************************************************
void CaplValue::Set(const CString &val)
{
	Clear();
	int k = val.GetLength() + 1;
	sval = new TCHAR[k];
	memcpy(sval, LPCTSTR(val), k * sizeof(TCHAR));
	type = aplSTRING;
};
//************************************************************************
void CaplValue::Set(LPCTSTR val)
{
	Clear();
	if(val==0)return;
	int k=_strlen(val)+1;
	sval=new TCHAR[k];
	memcpy(sval, val, k * sizeof(TCHAR));
	type=aplSTRING;
};
//************************************************************************
void CaplValue::Set(double val)
{
	if(val>MaxDoubleVal)
	{
		//SetLastWarningWithFileInfo(APLAPIERR_BADDATA);
#ifdef _DEBUG
		if(true)
		{
			CString str; str.Format( APL_T("Максимальное возможное значение для данного атрибута %1.15G. Введенная величина будет усечена до максимального значения."),MaxDoubleVal);
			aplMessageBox(str,MB_ICONWARNING|MB_OK);
		}
#endif
		val=MaxDoubleVal;
	}
	Clear(); type=aplREAL; rval=val;
};



//************************************************************************
void CaplValue::Set(const CaplAggr &val)
{
	if(type!=aplAGGR) Clear();
	else if(aggrval!=0)
	{
		//aggrval->Clear();
		aggrval->aggr.Clear();
		aggrval->type=aplNOTYPE;
	}
	if(aggrval==0) aggrval=new CaplAggr;
	aggrval->Append(val);
	type=aplAGGR;
};
void CaplValue::Set(const aplExtent &val)
{
	if (type!=aplAGGR) Clear();
	else if(aggrval != 0)
	{
		//aggrval->Clear();
		aggrval->aggr.Clear();
		aggrval->type=aplNOTYPE;
	}
	if(aggrval==0) aggrval=new CaplAggr;
	int i,k=val.GetSize();
	for(i=0; i<k;i++) aggrval->Add(val[i]);
	type=aplAGGR;
};

//************************************************************************
void CaplValue::Set(CaplDataBuf &val)
{
	if(type!=aplBINARY) Clear(); else if(binval!=0) binval->Clear();
	if(binval==0) binval=new CaplDataBuf;
	binval->Add(val.m_data,val.m_Size);
	type=aplBINARY;
};
//************************************************************************
void CaplValue::Set(CaplIntegrBINVal &val)
{
	if(type!=aplINTEGRATEDBIN) Clear();
	else if(intbinval!=0)
	{
		intbinval->Clear();
	}
	if(intbinval==0) intbinval=new CaplIntegrBINVal;
	*intbinval=val;
	type=aplINTEGRATEDBIN;
};
//************************************************************************
void CaplValue::Set(const CaplValue &val)
{
	if(this==&val)return;
	Clear();
	switch (val.type)
	{
	case aplINTEGER:	ival=val.ival; break;
	case aplREAL:		rval=val.rval; break;
	case aplBOOL:		bval=val.bval; break;
	case aplLOGICAL:	lval=val.lval; break;
	case aplINSTANCE:
	case aplSELECT:     instval=val.instval;break;
	case aplSTRING:		Set(val.sval);break;
	case aplAGGR:		Set(*val.aggrval);break;
	case aplBINARY:		Set(*val.binval); break;
	case aplINTEGRATEDBIN:	Set(*val.intbinval); break;

	default: break; // Чтобы не ругался  gcc
	}
	type=val.type;
}

void CaplValue::Set( CaplInstance *val )
{
	Clear();

	if (val != NULL)
	{
		type = aplINSTANCE;
		instval = val;
	}
}
void CaplValue::SetExternalString(LPCTSTR str)
{
	sval=(TCHAR *)str;
	m_bUseExternalString=true;
	type=aplSTRING;
}

//************************************************************************
int aplQuickFind(int *array, int count, int value)
{
	if(array==0) return -1;
	if(count==0) return -1;
	bool dir_low_high=true;
	if(count>1) if(array[0]>array[1]) dir_low_high=false;

	int i=0, i0=0, i1=count-1, io=-1, index=-1;
	// поиск упорядоченного значения
	do
	{
		io=i;
		i=(i0+i1)/2;
		if(io==i) break;
		if(array[i]==value){index=i; break;}
		if(dir_low_high)
		{
			if(value>array[i]) i0=i;
			else i1=i;
		}
		else
		{
			if(value>array[i]) i1=i;
			else i0=i;
		}
	} while(1);
	if(index!=-1) return index;
	if(array[i1]==value)return i1;
	if(array[i0]==value)return i0;
	// поиск неупорядоченного значения
	for(i=0;i<count;i++) if(array[i]==value)return i;
	return -1;
}

//************************************************************************
int aplQuickFindP(void **array, int count, void *value)
{
	if(array==0) return -1;
	if(count==0) return -1;
	bool dir_low_high=true;
	if(count>1) if(array[0]>array[1]) dir_low_high=false;

	int i=0, i0=0, i1=count-1, io=-1, index=-1;
	// поиск упорядоченного значения
	do
	{
		io=i;
		i=(i0+i1)/2;
		if(io==i) break;
		if(array[i]==value){index=i; break;}
		if(dir_low_high)
		{
			if(value>array[i]) i0=i;
			else i1=i;
		}
		else
		{
			if(value>array[i]) i1=i;
			else i0=i;
		}
	} while(1);
	if(index!=-1) return index;
	if(array[i1]==value)return i1;
	if(array[i0]==value)return i0;
	// поиск неупорядоченного значения
	for(i=0;i<count;i++) if(array[i]==value)return i;
	return -1;
}

//************************************************************************
int aplQFindInstIdInExtent(aplExtent &ext, apl_id id, int max_size, bool full_cycle, CaplInstance **founded_inst)
{
	if(founded_inst!=0){*founded_inst=0;}
	if(ext.Size<1) return -1;
	if(id==0)return -1;

	bool dir_low_high=true;
	bool ignore_sort=(max_size!=-1);
	// deschere
	
	if(max_size==-1 || max_size>ext.Size)max_size=ext.Size;
	if(max_size==0)return -1;
	int i=0, i0=0, i1=max_size-1, io=-1;
	if(max_size==1)
	{
		if(ext[0]->GetId()==id){if(founded_inst!=0){*founded_inst=ext[0];};return 0;}
	}
	else if(max_size>1 && (ext.Sorted_id || ignore_sort))
	{
		if((ext[0]!=0)&&(ext[1]!=0))
		{
			if(ext[0]->GetId()>ext[1]->GetId()) dir_low_high=false;
			// поиск упорядоченного значения
			do
			{
				io=i;
				i=(i0+i1)/2;
				if(io==i) break;
				bool end=false;
				while(ext[i]==0)
				{
					i--;
					if(i<0){end=true;break;}
				}
				if(end) break;

				if(ext[i]->GetId()==id){if(founded_inst!=0){*founded_inst=ext[i];};return i;}
				if(dir_low_high)
				{
					if(id>ext[i]->GetId()) i0=i;
					else i1=i;
				}
				else
				{
					if(id>ext[i]->GetId()) i1=i;
					else i0=i;
				}
			} while(1);
			if(ext[i1]!=0){if(ext[i1]->GetId()==id){if(founded_inst!=0){*founded_inst=ext[i1];};return i1;}}
			if(ext[i0]!=0){if(ext[i0]->GetId()==id){if(founded_inst!=0){*founded_inst=ext[i0];};return i0;}}
		}
	}
	if(!full_cycle)return -1;
	// поиск неупорядоченного значения
	for(i=0;i<max_size;i++)
	{
		if(ext[i]==0) continue;
		if(ext[i]->GetId()==id){if(founded_inst!=0){*founded_inst=ext[i];};return i;}
	}
	return -1;
}


//************************************************************************
int aplQFindInstInExtent(aplExtent &ext, CaplInstance *inst, bool full_cycle)
{
	if(ext.Size<1) return -1;

	if(ext.Size==1)
	{
		if(ext[0]==inst) return 0;
		return -1;
	}

	bool dir_low_high=true;
	int max_size=ext.Size;

	int i=0, i0=0, i1=max_size-1, io=-1;
	if( /*(ext[0]!=0) && (ext[1]!=0) &&*/  ext.Sorted_inst)
	{
		if(ext[0]>ext[1]) dir_low_high=false;
		// поиск упорядоченного значения
		do
		{
			io=i;
			i=(i0+i1)/2;
			if(io==i) break;
			bool end=false;
			while(ext[i]==0)
			{
				i--;
				if(i<0){end=true;break;}
			}
			if(end) break;

			if(ext[i]==inst){return i;}
			if(dir_low_high)
			{
				if(inst>ext[i]) i0=i;
				else i1=i;
			}
			else
			{
				if(inst>ext[i]) i1=i;
				else i0=i;
			}
		} while(1);
	}
	if(ext[i1]!=0){if(ext[i1]==inst){return i1;}}
	if(ext[i0]!=0){if(ext[i0]==inst){return i0;}}

	if(!full_cycle)return -1;
	// поиск неупорядоченного значения
	for(i=0;i<max_size;i++)
	{
		if(ext[i]==0) continue;
		if(ext[i]==inst){return i;}
	}
	return -1;
}

//************************************************************************
bool CaplValue::IsEqu(const CaplValue &val) const
{
	if(type!=val.type) return false;
	if(type==val.type)	{
		switch (type)
		{
		case aplNOTYPE: return true; break;
		case aplINSTANCE: 
		case aplSELECT: 
			if(instval==val.instval) return true; else return false;
		case aplINTEGER: if(ival==val.ival) return true; else return false;
		case aplREAL: if(rval==val.rval) return true; else return false;
		case aplSTRING:
		case aplENUMERATION:
			if(CString(sval)==val.sval) return true; else return false;
		case aplBOOL: if(bval==val.bval) return true; else return false;
		case aplLOGICAL: if(lval==val.lval) return true; else return false;
		case aplBINARY: return false;
		case aplINTEGRATEDBIN: if(ival==val.ival) return true; else return false;
		case aplAGGR: 
				if(aggrval->GetSize() != val.aggrval->GetSize())
					return false;
				for(int i=0; i<aggrval->GetSize();i++)
				{
						CaplValue val1,val2;
						aggrval->GetByIndex(i,val1);
						val.aggrval->GetByIndex(i,val2);
						if(val1!=val2)return false;
				}
				return true; 
		case aplBLOB: break; 
		}
		
	}
/*  Блок использовался для поиска FindInstWithAttrVal, но был некорректен.
	Для использования в поиске сделана функция IsEquWithAggr
	if(type==aplAGGR)
	{
		for(int i=0; i<aggrval->GetSize();i++)
		{
			CaplValue val1;
			aggrval->GetByIndex(i,val1);
			if(val1==val)return true;
		}
		return false; 
	}
	if(val.type==aplAGGR)
	{
		for(int i=0; i<val.aggrval->GetSize();i++)
		{
			CaplValue val1;
			val.aggrval->GetByIndex(i,val1);
			if(val1==*this) return true;
		}
		return false; 
	}
*/
    return false;
}
//************************************************************************
bool CaplValue::IsEquWithAggr(const CaplValue &val) const
{
	if(type==val.type)	{
		switch (type)
		{
		case aplNOTYPE: return true; break;
		case aplINSTANCE: 
		case aplSELECT: 
			if(instval==val.instval) return true; else return false;
		case aplINTEGER: if(ival==val.ival) return true; else return false;
		case aplREAL: if(rval==val.rval) return true; else return false;
		case aplSTRING:
		case aplENUMERATION:
			if(CString(sval)==val.sval) return true; else return false;
		case aplBOOL: if(bval==val.bval) return true; else return false;
		case aplLOGICAL: if(lval==val.lval) return true; else return false;
		case aplBINARY: return false;
		case aplINTEGRATEDBIN: if(ival==val.ival) return true; else return false;
		case aplAGGR: 
				for(int i=0; i<aggrval->GetSize();i++)
				{
						CaplValue val1,val2;
						aggrval->GetByIndex(i,val1);
						val.aggrval->GetByIndex(i,val2);
						if(val1!=val2)return false;
				}
				return true; 
		case aplBLOB: break; 
		}
		
	}
	if(type==aplAGGR)
	{
		for(int i=0; i<aggrval->GetSize();i++)
		{
			CaplValue val1;
			aggrval->GetByIndex(i,val1);
			if(val1==val)return true;
		}
		return false; 
	}
	if(val.type==aplAGGR)
	{
		for(int i=0; i<val.aggrval->GetSize();i++)
		{
			CaplValue val1;
			val.aggrval->GetByIndex(i,val1);
			if(val1==*this) return true;
		}
		return false; 
	}
    return false;
}
//************************************************************************
//************************************************************************
//************************************************************************
bool CaplAggr::Append(const CaplAggr &ap_aggr)
{
	CaplValue *val;
	if(type==aplNOTYPE) type=ap_aggr.type;
	if(type!=ap_aggr.type) return false;
	
	for(int i=0;i<ap_aggr.GetSize();i++)
	{
		CaplValue *addval=ap_aggr.GetByIndex(i);
		if(0==addval) continue;
		if(addval->type==type)
		{
			val=new CaplValue;
			val->Set(*addval);
			bool bOldUnique=aggr.Unique;
			aggr.Unique=false; // Ибо только что создали
			aggr.Add(val);
			aggr.Unique=bOldUnique;
		}
	}
	return true;
}
//************************************************************************

#define APL_AGGR_TYPE_ADD(TYPE) \
	if(type==aplNOTYPE) type=TYPE;\
	if(type!=TYPE) return false;\
	CaplValue *val=new CaplValue;\
	val->Set(value);\
	if(aggr.Add(val)==-1)return false;\
	return true;


bool CaplAggr::Add(const CaplValue &value)
{
	if (type == aplNOTYPE) type = value.type;
	if(value.type!=type) return false;
	CaplValue *val = new CaplValue;
	val->Set(value);
	aggr.Add(val);
	return true;
}

void CaplAggr::Clear()
{
	aggr.Clear();
	type=aplNOTYPE;
};

int CaplAggr::GetSize() const
{
	if(type==aplNOTYPE) return 0;
	return aggr.Size;
};

CaplAggr::CaplAggr(aplValueType def_type)
{
	type = def_type;
}

CaplAggr::~CaplAggr()
{
}

bool CaplAggr::Add(int value){APL_AGGR_TYPE_ADD(aplINTEGER)}
bool CaplAggr::Add(double value){APL_AGGR_TYPE_ADD(aplREAL)}
bool CaplAggr::Add(bool value){APL_AGGR_TYPE_ADD(aplBOOL)}
bool CaplAggr::Add(pCaplInstance value){APL_AGGR_TYPE_ADD(aplINSTANCE)}
bool CaplAggr::Add(LPCTSTR value){APL_AGGR_TYPE_ADD(aplSTRING)}
bool CaplAggr::Add(const CString &value){APL_AGGR_TYPE_ADD(aplSTRING)}
bool CaplAggr::Add(const CaplAggr &value){APL_AGGR_TYPE_ADD(aplINTEGER)}

bool CaplAggr::Insert(int index, const CaplValue &value)
{
	if(type==aplNOTYPE) type=value.type;
	if(value.type!=type) return false;
	if(index<0) return false;
	if(index>aggr.Size) return false;
	CaplValue *val=new CaplValue;
	val->Set(value);
	aggr.Add(0);
	for(int i=aggr.Size-1;i>index;i--)
		aggr.Data[i]=aggr[i-1];
	aggr.Data[index]=val;
	return true;
}

//************************************************************************
bool CaplAggr::GetByIndex(int index, CaplValue &value) const
{
	if (index<0) return false;
	if (index>=aggr.Size) return false;
	value.Set(*aggr[index]);
	return true;
}

#define APL_AGGR_TYPE_GET(TYPE) \
	if(index<0) return false;\
	if(index>=aggr.Size) return false;\
	if(aggr[index]->type!=TYPE) return false;\
	aggr[index]->Get(value);\
	return true;\

bool CaplAggr::GetByIndex(int index,int &value) const
{	value=0; APL_AGGR_TYPE_GET(aplINTEGER) }
bool CaplAggr::GetByIndex(int index,double &value) const
{	value=0; APL_AGGR_TYPE_GET(aplREAL) }
bool CaplAggr::GetByIndex(int index,bool &value) const
{	value=false; APL_AGGR_TYPE_GET(aplBOOL) }
bool CaplAggr::GetByIndex(int index,pCaplInstance &value) const
{	value=0; APL_AGGR_TYPE_GET(aplINSTANCE) }
bool CaplAggr::GetByIndex(int index,CString &value) const
{	value=_T(""); APL_AGGR_TYPE_GET(aplSTRING) }
bool CaplAggr::GetByIndex(int index,CaplAggr &value) const
{	value.Clear();APL_AGGR_TYPE_GET(aplAGGR) }

bool CaplAggr::Remove(int index) {return aggr.Remove(index);}


bool CaplAggr::IsEqual(CaplAggr &aggr2)
{
	if(aggr.GetSize()!=aggr2.GetSize()) return false;

	int i,j;
	for(i=0;i<aggr.GetSize();i++)
	{
		bool bFound=false;
		CaplValue *v_i=aggr[i];

		for(j=0;j<aggr2.GetSize();j++)
		{
			CaplValue *v_j=aggr2.GetByIndex(j);
			if(v_i->IsEqu(*v_j))
			{
				bFound=true;
				break;
			}
		}
		if(!bFound) return false;
	}
	return true;
}

bool aplExtentIsEqual(aplExtent &ext1, aplExtent &ext2)
{
	if(ext1.Size!=ext2.Size) return false;
	int i,j;
	for(i=0;i<ext1.Size;i++)
	{
		bool bFound=false;
		CaplInstance *v_i=ext1[i];

		for(j=0;j<ext2.Size;j++)
		{
			CaplInstance *v_j=ext2[j];
			if(v_i==v_j)
			{
				bFound=true;
				break;
			}
		}
		if(!bFound) return false;
	}
	return true;
}

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

CaplAggrMap::CaplAggrMap()
	: Data(NULL)
	, Size(0)
	, MaxSize(0)
	, m_sorted(true)
{
}

CaplAggrMap::CaplAggrMap(int max_size)
	: Data(NULL)
	, Size(0)
	, MaxSize(0)
	, m_sorted(true)
{
	SetSize(max_size);
}

CaplAggrMap::~CaplAggrMap()
{
	if(Data) delete [] Data;
	Data=0;Size=0;MaxSize=0;
}

//********************************************************
void  CaplAggrMap::Clear()
{
	if(Data) delete [] Data;
	Data=0;Size=0;
}

bool CaplAggrMap::SetSize(int max_size) // число элементов
{
	if(max_size<Size) return false;
	if(max_size==Size) return true;
	
	CaplAggrMapItem *data1=new CaplAggrMapItem[max_size];

	if(Data)
	{
		for(int i=0;i<Size;i++)	
			data1[i]=Data[i];
		delete [] Data;
	}
	Data=data1;
	MaxSize=max_size;
	return true;
}
//********************************************************
int CaplAggrMap::Add(long in, CaplAggr &out)
{
	int index=QFindByIn(in);
	if(index<0)
	{
		if(Size+1>MaxSize) SetSize((MaxSize+1)*2);
		else if(!Data) SetSize(MaxSize);
		Data[Size].in=in; 
		Data[Size].out.Append(out); 
		m_sorted=false;
		Size++;
	}
	else
	{
		Data[index].out.Append(out); 
	}
	return Size;
}

/**< Добавление комбинации  in -  ключ, out - добавляемый элемент*/
int CaplAggrMap::Add(long in, long out)
{
	int index=QFindByIn(in);
	if(index<0)
	{
		if(Size+1>MaxSize) SetSize((MaxSize+1)*2);
		else if(!Data) SetSize(MaxSize);
		Data[Size].in=in; 
		Data[Size].out.Add((int)out); 
		m_sorted=false;
		Size++;
	}
	else
	{
		Data[index].out.Add((int)out); 
	}
	return Size;
}
/**< Добавление комбинации  in -  ключ, out - добавляемый элемент*/
int CaplAggrMap::Add(long in, CaplInstance *out)
{
	int index=QFindByIn(in);
	if(index<0)
	{
		if(Size+1>MaxSize) SetSize((MaxSize+1)*2);
		else if(!Data) SetSize(MaxSize);
		Data[Size].in=in; 
		Data[Size].out.Add(out); 
		m_sorted=false;
		Size++;
	}
	else
	{
		Data[index].out.Add(out); 
	}
	return Size;
}


bool CaplAggrMap::Remove(int index)
{
	if(index<0)return false;
	if(index>=Size)return false;

	for(int i=index;i<Size-1;i++){
		Data[i]=Data[i+1];
	}
	Size--;
	return true;
}

//********************************************************
int compare_aplAggrMap_elements( const void *arg1, const void *arg2 )
{
	if(((CaplAggrMap::CaplAggrMapItem*)arg1)->in>((CaplAggrMap::CaplAggrMapItem*)arg2)->in) return 1;
	if(((CaplAggrMap::CaplAggrMapItem*)arg1)->in==((CaplAggrMap::CaplAggrMapItem*)arg2)->in) return 0;
	return -1;
}

void CaplAggrMap::SortIn()
{
	if(!Data) return;
	if(Size<2) return;

	qsort(Data,Size,sizeof(CaplAggrMapItem),compare_aplAggrMap_elements);
	/*
	int i,j;
	long min;
	int min_num;
	CaplAggrMapItem buf;
	for(i=0;i<Size;i++)
	{
		min=Data[i].in;
		min_num=i;
		for(j=i+1;j<Size;j++)
		{
			if(Data[j].in<min) 
			{
				min=Data[j].in;
				min_num=j;
			}
		}
		buf=Data[i];
		Data[i]=Data[min_num];
		Data[min_num]=buf;
	}*/
	m_sorted=true;
	
}

//********************************************************
int CaplAggrMap::QFindByIn(long value)
{
	if(Data==0) return -1;
	if(Size==0) return -1;

	if(!m_sorted) SortIn();

	bool dir_low_high=true;
	if(Size>1) if(Data[0].in>Data[1].in) dir_low_high=false;

	int i=0, i0=0, i1=Size-1, io=-1, index=-1;
	// поиск упорядоченного значения
	do
	{
		io = i;
		i = (i0 + i1) >> 1;
		if(io==i) break;
		if(Data[i].in==value){index=i; break;}
		if(dir_low_high)
		{
			if(value>Data[i].in) i0=i;
			else i1=i;
		}
		else
		{
			if(value>Data[i].in) i1=i;
			else i0=i;
		}
	} while(1);
	if(index!=-1) return index;
	if(Data[i1].in==value)return i1;
	if(Data[i0].in==value)return i0;

	return -1;
}
//********************************************************
CaplAggr* CaplAggrMap::QGetByIn(long data)
{
	int i=QFindByIn(data);
	if(i==-1) return 0;
	return &Data[i].out;
}
/*
void *CaplAggrMap::QGetPointerByIn(long data)
{
	int i=QFindByIn(data);
	if(i==-1) return 0;
	return (void*)Data[i].out;
}
*/
//********************************************************
bool CaplValue::operator>(const CaplValue &rVal) const
{
	if(type!=rVal.type) return false;
//	enum aplValueType{  aplNOTYPE=0,		/**< тип не задан*/
//		aplINSTANCE=1,		/**< CaplInstance**/
//		aplAGGR=2,			/**< CaplAggr*/
//		aplINTEGER=3,		/**< int*/
//		aplREAL=4,			/**< double*/
//		aplSTRING=5,		/**< char**/
//		aplBOOL=6,			/**< bool*/
//		aplLOGICAL=7,		/**< long*/
//		aplBINARY=8,		/**< char**/
//		aplSELECT=9,		/**< char*/
//		aplBLOB=10,			/**< любой*/
//		aplENUMERATION=11,	/**< любой*/
//		aplINTEGRATEDBIN=12	/**< CaplIntegrBINVal*/
//	};
	switch(type)
	{
	case aplINSTANCE:
	case aplSELECT:
		{
			CaplInstance* lTstVal, *rTstVal;
			Get(lTstVal);
			rVal.Get(rTstVal);
			return (void*)rTstVal<(void*)lTstVal;
		}
		break;
	case aplINTEGER:
		{
			int lTstVal, rTstVal;
			Get(lTstVal);
			rVal.Get(rTstVal);
			return rTstVal<lTstVal;
		}
		break;
	case aplREAL:
		{
			double lTstVal, rTstVal;
			Get(lTstVal);
			rVal.Get(rTstVal);
			return rTstVal<lTstVal;
		}
		break;
	case aplSTRING:
	case aplENUMERATION:
		{
			CString lTstVal, rTstVal;
			Get(lTstVal);
			rVal.Get(rTstVal);
			return rTstVal<lTstVal;
		}
		break;
	case aplBOOL:
		{
			bool lTstVal, rTstVal;
			Get(lTstVal);
			rVal.Get(rTstVal);
			return rTstVal<lTstVal;
		}
		break;
	case aplLOGICAL: return rVal.lval<lval; break;	
		
	default: break; // Чтобы не ругался QtCreator
	}
	return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////
aplAccessEl::aplAccessEl()
{
	inst=0;is_individual=0;access=aplNOT_DEFINED;pattern=0;
}
void aplAccessEl::Set(aplAccessEl* old_el)
{
	is_individual=old_el->is_individual;
	inst=old_el->inst;
	access=old_el->access;
	pattern=old_el->pattern;
};
bool aplAccessEl::compare(aplAccessEl* el)
{
	if(el->access==access && el->inst==inst && el->is_individual==is_individual && el->pattern==pattern)
		return true;
	return false;
}

aplAccessList::aplAccessList()
{
	user=0;
	changed=false;
	multy=false;
}
aplAccessList::~aplAccessList()
{
	Clear();
}//aplAccessList::~aplAccessList(){

void aplAccessList::Clear()
{
	for(int i=0;i<m_nSize;i++){
		delete m_pData[i];
	}
	m_nSize=0;
}
aplAccessEl* aplAccessList::Find(CaplInstance* inst)
{
	for(int i=0;i<m_nSize;i++){
		if(GetAt(i)->inst==inst)
			return GetAt(i);
	}
	return NULL;
}
void aplAccessList::Set(aplAccessList* old_list)
{
	aplAccessEl* new_el=0;
	Clear();
	user=old_list->user;
	for(int i=0;i<old_list->GetSize();i++)
	{
		new_el=new aplAccessEl();
		new_el->Set(old_list->GetAt(i));
		Add(new_el);
	}
}

bool aplAccessList::IsSetAccess()
{
	bool res=false;
	for(int i=0;i<GetSize();i++)
	{
		if(GetAt(i)->access!=aplNOT_DEFINED){
			res=true;
			break;
		}
	}
	return res;
}

CString aplAccessList::GetText(bool for_dialog)
{
	CString res=_T(""), buf_pat=_T(""), buf;
	CArray<BYTE,BYTE> arr_ass;
	aplExtent ext_pat;
	int i,j;
	bool flag;
	for(i=0;i<GetSize();i++)
	{
		flag=true;
		for(j=0;j<arr_ass.GetSize();j++)
		{
			if(arr_ass.GetAt(j)==GetAt(i)->access)
			{
				flag=false;
				break;
			}
			ext_pat.Add(GetAt(i)->pattern);
		}
		if(flag)
		{
			arr_ass.Add(GetAt(i)->access);
		}
	}
	if(arr_ass.GetSize()>1)
	{
		multy=true;
		if(for_dialog)res=APL_T("Не изменять (");
	}
	for(i=0;i<arr_ass.GetSize();i++)
	{
		if(i>0)res+=_T(", ");
		res+=GetNameAccess((aplAccessModeType)arr_ass.GetAt(i));
	}
	if(arr_ass.GetSize()>1 && for_dialog)res+=_T(")");
	for(i=0;i<ext_pat.GetSize();i++)
	{
		if(ext_pat[i]==0)continue;
		buf.Format(_T("%i; "),ext_pat[i]->GetId());
		buf_pat+=buf;
	}
	if(buf_pat != _T("")){res+= APL_T("; Шаблоны: ")+buf_pat;}
	if(res== _T("")){res= APL_T("Не определен");}
	return res;
}

aplAccessList* aplUsers::Find(CaplInstance* user)
{
	for(int i=0;i<GetSize();i++)
	{
		if(GetAt(i)->user==user)
			return GetAt(i);
	}
	if(m_auto_add)
	{
		aplAccessList* list=new aplAccessList();
		aplAccessEl* el=new aplAccessEl();
		list->user=user;
		list->Add(el);
		Add(list);
		return list;
	}
	return NULL;
}

aplUsers::~aplUsers()
{
	Clear();
};
void aplUsers::Clear()
{
	for(int i=0;i<m_nSize;i++)
	{
		delete m_pData[i];
	}
	m_nSize=0;
}
void aplUsers::RemoveAtWithDel(int indx)
{
	delete m_pData[indx];
	CArray::RemoveAt(indx);
}
void aplUsers::Sort()
{
	//aplUsers temp_users;
	CaplMap map;
	aplAccessList* list;
	int i;
	for(i=0;i<GetSize();i++){
		list=GetAt(i);
		//temp_users.Add(list);
		map.Add(list->user==0?0:list->user->GetId(),list);
	}
	map.SortIn();
	m_nSize=0;
	for(i=0;i<map.Size;i++){
		Add((aplAccessList*)map[i].out);
	}
}

void aplUsers::Set(aplUsers &table)
{
	aplAccessList* list=0;
	Clear();
	for(int i=0;i<table.GetSize();i++){
		list=new aplAccessList();
		list->Set(table.GetAt(i));
		Add(list);
	}
	code1=table.code1;
	code2=table.code2;
}


void aplUsers::Set(aplListAccess2Inst *table)
{
	aplAccess2Inst *acc_inst;
	CaplInstance* user;
	aplAccessModeType access;
	aplAccessList* list=0;
	aplAccessList* list_def=0;
	aplAccessEl* el;
	int i,j,k;
	Clear();
	if(table==0) return;

	for(i=0;i<table->Size;i++)
	{
		acc_inst = table->GetAt(i);
		if(acc_inst==0)continue;
		if(list_def==0)
		{
			list_def = new aplAccessList();
			Add(list_def);
		}
		el = new aplAccessEl();
		el->inst = acc_inst->inst;
		el->access = (aplAccessModeType) acc_inst->access_def;
		el->pattern = acc_inst->pattern;
		el->is_individual = acc_inst->is_individual;
		list_def->Add(el);
		

		for(j=0;j<acc_inst->GetSize();j++)
		{
			acc_inst->Get(j,&user,access);
			list = 0;

			for(k=0;k<GetSize();k++)
			{
				if(GetAt(k)->user==user)
				{
					list=GetAt(k);
					break;
				}
			}
			if(list==0)
			{
				list=new aplAccessList();
				list->user = user;
				Add(list);
			}
			el = new aplAccessEl();
			el->inst = acc_inst->inst;
			el->access = access;
			list->Add(el);
		}
	}
	// заполняем пустые пары юзер-инстанс значениями aplNOT_DEFINED
	for(k=0;k<GetSize();k++)
	{
		list=GetAt(k);
		for(i=0;i<table->Size;i++)
		{
			acc_inst = table->GetAt(i);
			if(acc_inst==0)continue;
			if(list->Find(acc_inst->inst)==0)
			{
				el = new aplAccessEl();
				el->inst = acc_inst->inst;
				el->access = aplNOT_DEFINED;
				list->Add(el);
			}
		}
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////

int aplListAccess2Inst::Add(aplAccess2Inst* el)
{
	if(el==0) return -1;
	return CaplMap::Add(el->inst,el);
}


aplAccess2Inst* aplListAccess2Inst::Find(CaplInstance* inst)
{
	aplAccess2Inst* el;
	el=(aplAccess2Inst*)QGetPointerByIn(inst);
	if(el==0 && m_auto_add)
	{
		el=new aplAccess2Inst();
		el->inst=inst;
		Add(el);
	}
	return el;
}

aplListAccess2Inst::~aplListAccess2Inst()
{
	Clear();
}

void aplListAccess2Inst::Clear()
{
	for(int i=0;i<Size;i++)
	{
		delete (aplAccess2Inst*)(Data[i].out);
	}
	m_auto_add=false;
	code1=0;code2=0;
	identical_access4all=false;
	clear_old_ind_access=true;
	changed = false;
	CaplMap::Clear();
}

// void aplListAccess2Inst::RemoveAtWithDel(int indx)
// {
// 	delete m_pData[indx];
// 	CArray::RemoveAt(indx);
// }

void aplListAccess2Inst::Sort()
{
	SortIn();	
}

aplAccess2Inst* aplListAccess2Inst::GetAt(int indx)
{
	if(indx>=Size || indx<0)return 0;
	return (aplAccess2Inst*)Data[indx].out;
}

void aplListAccess2Inst::Set(aplListAccess2Inst &table)
{
	aplAccess2Inst* el=0;
	Clear();
	for(int i=0;i<table.Size;i++)
	{
		el=new aplAccess2Inst();
		el->Set(table.GetAt(i));
		Add(el);
	}
	code1=table.code1;
	code2=table.code2;
	identical_access4all=table.identical_access4all;
	clear_old_ind_access=table.clear_old_ind_access;
}

void aplListAccess2Inst::Set(aplUsers* old_access,bool clear)
{
	aplAccessList* list=0;
	aplAccessEl* el2u=0;

	aplAccess2Inst *acc_inst;
	aplAccess2Inst *acc_inst_prev;

	CaplInstance *user, *user_prev;
	aplAccessModeType access, access_prev;

	int i,j,k;
	if(clear)Clear();

	for(i=0;i<old_access->GetSize();i++)
	{
		list=old_access->GetAt(i);
		if(list->changed)changed = true;
		if(!clear && !list->changed) continue;
		for(j=0;j<list->GetSize();j++)
		{
			el2u=list->GetAt(j);
			acc_inst = 0;
			if(clear)
			{
				for(k=0;k<Size;k++)
				{
					if(GetAt(k)->inst == el2u->inst)
					{
						acc_inst = GetAt(k);
						break;
					}
				}
				if(acc_inst==0)
				{
					acc_inst = new aplAccess2Inst();
					acc_inst->inst = el2u->inst;
					Add(acc_inst);
				}
				if(list->user==0)
				{
					acc_inst->access_def = el2u->access;
					acc_inst->is_individual = el2u->is_individual;
					acc_inst->pattern = el2u->pattern;
				}
				else
				{
					acc_inst->Add(list->user,el2u->access);
				}
			}
			else
			{
				if(el2u->inst==0)
				{
					for(k=0;k<Size;k++)
					{
						acc_inst = GetAt(k);
						if(list->user==0)
						{
							acc_inst->access_def = el2u->access;
							acc_inst->is_individual = el2u->is_individual;
							acc_inst->pattern = el2u->pattern;
						}
						else
						{
							acc_inst->Add(list->user,el2u->access);
						}						
					}
				}
				else
				{
					for(k=0;k<Size;k++)
					{
						if(GetAt(k)->inst == el2u->inst)
						{
							acc_inst = GetAt(k);
							break;
						}
					}
					if(acc_inst==0)
					{
						acc_inst = new aplAccess2Inst();
						acc_inst->inst = el2u->inst;
						Add(acc_inst);
					}
					if(list->user==0)
					{
						acc_inst->access_def = el2u->access;
						acc_inst->is_individual = el2u->is_individual;
						acc_inst->pattern = el2u->pattern;
					}
					else
					{
						acc_inst->Add(list->user,el2u->access);
					}
				}
			}
		}
	}
	// проверка на одинаковость
	bool identical = true;
	for(i=1;i<Size;i++)
	{
		acc_inst_prev = GetAt(i-1);
		acc_inst = GetAt(i);
		
		if(acc_inst_prev == 0 || acc_inst == 0) {identical=false; break;}
		if(acc_inst_prev->is_individual != acc_inst->is_individual){identical=false; break;}
		if(acc_inst_prev->access_def != acc_inst->access_def){identical=false; break;}
		if(acc_inst_prev->pattern != acc_inst->pattern){identical=false; break;}

		for(j=0;(j<acc_inst_prev->GetSize() && j<acc_inst->GetSize());j++)
		{
			acc_inst->Get(j,&user, access);
			acc_inst_prev->Get(j,&user_prev, access_prev);
			if(user_prev != user || access_prev != access){identical = false; break;}
		}
	}
	if(identical)
	{
		identical_access4all = true;
	}

}

///////////////////////////////////////////////////////////////////////////////////////
BYTE aplAccess2Inst::Find(CaplInstance* user)
{
	aplAccessModeType access=(aplAccessModeType)user_access.QGetByIn(user);
	if(access==-1)access=aplNOT_DEFINED;
	return access;
}

void aplAccess2Inst::ResetAccess()
{
	for(int i=0;i<user_access.Size;i++)
	{
		user_access.Data[i].out = 4;
	}
}

void aplAccess2Inst::Set(aplAccess2Inst* old_access)
{
	if(old_access==0)return;

	inst=old_access->inst;
	is_individual=old_access->is_individual;
	access_def=old_access->access_def;
	pattern=old_access->pattern;  
	changed=false;

	//Карта доступа юзеров. В in - (CaplInstance* )user, в out - aplAccessModeType access;
	user_access.Clear();
	for(int i=0;i<old_access->user_access.Size;i++)
	{
		user_access.Add(old_access->user_access.Data[i].in,old_access->user_access.Data[i].out);
	}
	multy=old_access->multy;
}

void aplAccess2Inst::Add(CaplInstance* user, aplAccessModeType access)
{
	user_access.Add(user,(INT_PTR)access);
}

CString aplAccess2Inst::GetText()
{
	CString res=_T(""),buf;
	int i;
	CaplInstance* user;

	res=GetNameAccess((aplAccessModeType)access_def);
	if(pattern != 0)
	{
		buf.Format(_T(" %i"),pattern->GetId());
		res+= APL_T("; Шаблон: ")+buf;
	}
	if(is_individual)
	{
		for(i=0;i<user_access.Size;i++)
		{
			user=(CaplInstance*)user_access.Data[i].in;
			buf.Format(_T(";%i:"),user->GetId());
			res+=buf+GetNameAccess((aplAccessModeType)user_access.Data[i].out);
		}
	}
	return res;
}

bool aplAccess2Inst::Get(int indx, CaplInstance** user, aplAccessModeType &access)
{
	if(indx < 0 ||indx > user_access.Size) return false;
	*user= (CaplInstance*) user_access.Data[indx].in;
	access = (aplAccessModeType) user_access.Data[indx].out;

	return true;
}

