valuework.hpp at tip Вы: nobody
Вход

File sqlite1c/SQL_DBF/valuework.hpp from the latest check-in


//valuework.hpp
#pragma once

enum Types1C{
	typeUndefined       = 0,
	typeNumber          = 1,
	typeString          = 2,
	typeDate            = 3,
	typeEnum            = 10,
	typeReference       = 11,
	typeDocument        = 12,
	typeCalendar        = 13,
	typeCalcKind        = 14,
	typeAccount         = 15,
	typeSubcKind        = 16,
	typeChartOfAcc      = 17,
};

inline static DWORD str2id(const unsigned char* ptr, DWORD len)
{
	DWORD id = 0;
	while(len--)
	{
		DWORD s = (DWORD)*ptr++;
		if(s >= 'A')
			id = id * 36 + s - 'A' + 10;
		else if(s >= '0')
			id = id * 36 + s - '0';
	}
	return id;
}

inline static DWORD str2dec(const unsigned char* ptr, DWORD len)
{
	DWORD id = 0;
	while(len--)
	{
		DWORD s = (DWORD)*ptr++;
		if(s >= '0')
			id = id * 10 + s - '0';
	}
	return id;
}

inline static void dec2str(DWORD dec, unsigned char* ptr, DWORD len)
{
	ptr += len;
	do 
	{
		*--ptr = (dec % 10) + '0';
		dec /= 10;
	}while(dec);
}

inline static void id2str(DWORD id, unsigned char* ptr, DWORD len)
{
	ptr += len;
	do 
	{
		DWORD v = id % 36;
		*--ptr = v < 10 ? v + '0' : v - 10 + 'A';
		id /= 36;
	}while(id);
}


enum TypeOfString {
	tos9 = 9,
	tos13 = 13,
	tos23 = 23
};

template<TypeOfString tos>
struct ValueStrWork
{
	inline static void str2val(CValue* pValue, LPCSTR str, Types1C type = typeUndefined, long mdID = 0)
	{
		char test[tos == tos9 || tos == tos13 || tos == tos23 ? 1 : -1] = {0};

		unsigned char* ptr = (unsigned char*)str;
		
		if(tos == tos23)
		{
			switch((DWORD)*ptr)
			{
			case 'U':
				return;
			case 'N':
				{
					static CNumeric num;
					*pValue = num.FromString(str + 1, NULL);
				}
				return;
			case 'S':
				*pValue = str + 1;
				return;
			case 'D':
				*pValue = CDate(str2dec(ptr + 1, 4), str2dec(ptr + 5, 2), str2dec(ptr + 7, 2));
				return;
			case 'E':
				type = typeEnum;
				break;
			case 'B':
				type = typeReference;
				break;
			case 'O':
				type = typeDocument;
				break;
			case 'C':
				type = typeCalendar;
				break;
			case 'A':
				type = typeCalcKind;
				break;
			case 'T':
				type = typeAccount;
				break;
			case 'K':
				type = typeSubcKind;
				break;
			case 'P':
				type = typeChartOfAcc;
				break;
			default:
				return;
			}
			ptr++;
			ptr++;
		}
		pValue->type = type;
		pValue->m_mdid = mdID;
		
		if(tos == tos13 || tos == tos23)
		{
			if(typeCalendar == type || typeCalcKind == type)
				mdID = 0;
			else
				mdID = str2id(ptr, 4);
			ptr += 4;
		}
		pValue->ValTypeID = mdID;
		pValue->m_ObjID.ObjID = str2id(ptr, 6);
		*(DWORD*)pValue->m_ObjID.DBSign.Sign = (*(DWORD*)(ptr + 6)) & 0xFFFFFF;
	}
	
	inline static void val2str(const CValue& val, CString& res)
	{
		char test[tos == tos9 || tos == tos13 || tos == tos23 ? 1 : -1] = {0};

		unsigned char* ptr = (unsigned char*)res.GetBufferSetLength(tos);
		if(tos == tos23)
		{
			//   
			*(DWORD*)(ptr + 0) = 0x20202020;
			*(DWORD*)(ptr + 4) = 0x20202020;
			*(DWORD*)(ptr + 8) = 0x20202020;
			*(DWORD*)(ptr + 12) = 0x20202020;
			*(DWORD*)(ptr + 16) = 0x20202020;
			*(DWORD*)(ptr + 20) = 0x00202020;
			switch(val.type)
			{
			case typeUndefined:
				*ptr = 'U';
				return;
			case typeNumber:
				*ptr++ = 'N';
				{
					CString str = val.GetString();
					int l = str.GetLength();
					if(l <= 22)
						memcpy(ptr, (LPCSTR)str, l);
				}
				return;
			case typeString:
				*ptr++ = 'S';
				{
					int l = val.m_String.GetLength();
					memcpy(ptr, (LPCSTR)val.m_String, l < 22 ? l : 22);
				}
				return;
			case typeDate:
				*ptr++ = 'D';
				*(DWORD*)(ptr + 4) = '0000';
				dec2str(val.m_Date.GetYear(), ptr, 4);
				dec2str(val.m_Date.GetMonth(), ptr + 4, 2);
				dec2str(val.m_Date.GetMonthDay(), ptr + 6, 2);
				return;
			case typeEnum:
				*ptr++ = 'E';
				break;
			case typeReference:
				*ptr++ = 'B';
				break;
			case typeDocument:
				*ptr++ = 'O';
				break;
			case typeCalendar:
				*ptr++ = 'C';
				break;
			case typeCalcKind:
				*ptr++ = 'A';
				break;
			case typeAccount:
				*ptr++ = 'T';
				break;
			case typeSubcKind:
				*ptr++ = 'K';
				break;
			case typeChartOfAcc:
				*ptr++ = 'P';
				break;
			}
			*ptr++ = '1';
		}
		//      !!!
		if(val.type <= typeDate)
		{
			memset(ptr, ' ', tos);
			return;
		}
		
		if(tos == tos13 || tos == tos23)
		{
			//  
			if(typeCalendar == val.type || typeCalcKind == val.type)
				*(DWORD*)ptr = '0   ';
			else
			{
				if(tos == tos13)	//   ,     
					*(DWORD*)ptr = 0x20202020;
				id2str(val.m_mdid ? val.m_mdid : val.ValTypeID, ptr, 4);
			}
			ptr += 4;
		}
		
		if(tos != tos23)	//   ,     
		{
			*(DWORD*)ptr = 0x20202020;
			*(WORD*)(ptr + 4) = 0x2020;
		}
		//    .
		id2str(val.m_ObjID.ObjID, ptr, 6);
		*(DWORD*)(ptr + 6) = *(DWORD*)val.m_ObjID.DBSign.Sign;

		//           0
		if(tos == 23)
			ptr[9] = ' ';
	}
};

template<typename T>
inline static void bindNumeric(T& binder, const CValue* pValue, int mod)
{
	if(0 != mod)
		binder.error("    \"\"");
	binder.bindNumeric(pValue);
}

template<typename T>
inline static void bindString(T& binder, const CValue* pValue, int mod)
{
	switch(mod)
	{
	case 0:		//   
		binder.bindText(pValue->m_String);
		break;
	case 1:		//  
	case 2:		//       ,   DATE,TIME,IDDOC
		if(pValue->m_String.GetLength() == 32)
		{
			CString text;
			const BYTE* pSrc = (const BYTE*)(LPCSTR)pValue->m_String;
			BYTE* pDst = (BYTE*)text.GetBufferSetLength(2 == mod ? 24 : 23);
			//memcpy(pDst, pSrc + 1, 8);
			*(DWORD*)(pDst +  0) = *(DWORD*)(pSrc +  1);
			*(DWORD*)(pDst +  4) = *(DWORD*)(pSrc +  5);
			*(DWORD*)(pDst +  8) = '    ';
			*(DWORD*)(pDst + 12) = '    ';
			*(DWORD*)(pDst + 16) = '    ';
			id2str(str2dec(pSrc + 10, 9), pDst + 8, 6);
			id2str(str2dec(pSrc + 19, 10), pDst + 14, 6);
			*(DWORD*)(pDst + 20) = *(DWORD*)(pSrc + 29);
			if(2 == mod)
				pDst[23] = '';
			binder.bindText(text);
		}
		else
			binder.error("    ");
		break;
	case 3:
		binder.bindFragment(pValue->m_String);
		break;
	default:
		binder.error("    \"\"");
	}
}

template<typename T>
inline static void bindDate(T& binder, const CValue* pValue, int mod)
{
	switch(mod)
	{
	case 0:		//   
	case 1:
		{
			CString text;
			BYTE* buf = (BYTE*)text.GetBufferSetLength(mod ? 9 : 8);
			DWORD day = pValue->m_Date.GetMonthDay();
			if(day)		//  
			{
				dec2str(pValue->m_Date.GetYear(), buf, 4);
				*(DWORD*)(buf + 4) = '0000';
				dec2str(pValue->m_Date.GetMonth(), buf + 4, 2);
				dec2str(day, buf + 6, 2);
			}
			else
				*(unsigned __int64*)buf = 0x2020202020202020;
			if(mod)
				buf[8] = '';
			binder.bindText(text);
		}
		break;
	default:
		binder.error("    \"\"");
	}
}

template<typename T>
inline static void bindObject(T& binder, const CValue* pValue, int mod)
{
	CString text;
	switch(mod)
	{
	case 0:		//  9
		ValueStrWork<tos9>::val2str(*pValue, text);
		binder.bindText(text);
		break;
	case 1:		//  13
		ValueStrWork<tos13>::val2str(*pValue, text);
		binder.bindText(text);
		break;
	}
}

template<typename T>
inline static void bindKindOfObject(T& binder, const CValue* pValue)
{
	CString text;
	BYTE* ptr = (BYTE*)text.GetBufferSetLength(4);
	*(DWORD*)ptr = '    ';
	id2str(pValue->m_mdid ? pValue->m_mdid : pValue->ValTypeID, ptr, 4);
	binder.bindText(text);
}

template<typename T>
inline static void bindEnum(T& binder, const CValue* pValue, int mod)
{
	switch(mod)
	{
	case 0:
	case 1:
		bindObject(binder, pValue, mod);
		break;
	default:
		binder.error("    \"\"");
	}
}

template<typename T>
inline static void bindReference(T& binder, const CValue* pValue, int mod)
{
	switch(mod)
	{
	case 0:
	case 1:
		bindObject(binder, pValue, mod);
		break;
	case 2:
		bindKindOfObject(binder, pValue);
		break;
	default:
		binder.error("    \"\"");
	}
}

template<typename T>
inline static void bindDocument(T& binder, const CValue* pValue, int mod)
{
	switch(mod)
	{
	case 0:
	case 1:
		bindObject(binder, pValue, mod);
		break;
	case 2:
		bindKindOfObject(binder, pValue);
		break;
	case 3:		//  
	case 4:		//       ,   DATE,TIME,IDDOC
        {
			CString text;
			BYTE* ptr = (BYTE*)text.GetBufferSetLength(4 == mod ? 24 : 23);
			CEventTime EventTime;
			CDate Date(0,0,0);
			GetDateTimeFromValue(*pValue, Date, EventTime);
			dec2str(Date.GetYear(), ptr, 4);
			*(DWORD*)(ptr + 4) = '0000';
			dec2str(Date.GetMonth(), ptr + 4, 2);
			dec2str(Date.GetMonthDay(), ptr + 6, 2);
			*(DWORD*)(ptr +  8) = '    ';
			*(DWORD*)(ptr + 12) = '    ';
			*(DWORD*)(ptr + 16) = '    ';
			id2str(EventTime.GetlTime(), ptr + 8, 6);
			id2str(pValue->m_ObjID.ObjID, ptr + 14, 6);
			*(DWORD*)(ptr + 20) = *(DWORD*)pValue->m_ObjID.DBSign.Sign;
			if(4 == mod)
				ptr[23] = '';
			binder.bindText(text);
		}
		break;
	default:
		binder.error("    \"\"");
	}
}

template<typename T>
inline static void bindCalendar(T& binder, const CValue* pValue, int mod)
{
	switch(mod)
	{
	case 0:
	case 1:
		bindObject(binder, pValue, mod);
		break;
	default:
		binder.error("    \"\"");
	}
}

template<typename T>
inline static void bindCalcKind(T& binder, const CValue* pValue, int mod)
{
	switch(mod)
	{
	case 0:
	case 1:
		bindObject(binder, pValue, mod);
		break;
	case 2:
		bindKindOfObject(binder, pValue);
		break;
	default:
		binder.error("    \"\"");
	}
}

template<typename T>
inline static void bindAccount(T& binder, const CValue* pValue, int mod)
{
	switch(mod)
	{
	case 0:
	case 1:
		bindObject(binder, pValue, mod);
		break;
	case 2:
		bindKindOfObject(binder, pValue);
		break;
	default:
		binder.error("    \"\"");
	}
}

template<typename T>
inline static void bindSubcKind(T& binder, const CValue* pValue, int mod)
{
	switch(mod)
	{
	case 0:
	case 1:
		bindObject(binder, pValue, mod);
		break;
	case 2:
		bindKindOfObject(binder, pValue);
		break;
	default:
		binder.error("    \"\"");
	}
}

template<typename T>
inline static void bindChartOfAccount(T& binder, const CValue* pValue, int mod)
{
	switch(mod)
	{
	case 0:
	case 1:
		bindObject(binder, pValue, mod);
		break;
	case 2:
		bindKindOfObject(binder, pValue);
		break;
	default:
		binder.error("    \"\"");
	}
}

template<typename T>
static void bindValue(T& binder, const CValue* pValue, int mod)
{
	if(-1 == mod)
	{
		CString text;
		ValueStrWork<tos23>::val2str(*pValue, text);
		binder.bindText(text);
		return;
	}
	switch(pValue->type)
	{
	case typeUndefined:
		binder.bindNull();
		break;
	case typeNumber:
		bindNumeric(binder, pValue, mod);
		break;
	case typeString:
		bindString(binder, pValue, mod);
		break;
	case typeDate:
		bindDate(binder, pValue, mod);
		break;
	case typeEnum:
		bindEnum(binder, pValue, mod);
		break;
	case typeReference:
		bindReference(binder, pValue, mod);
		break;
	case typeDocument:
		bindDocument(binder, pValue, mod);
		break;
	case typeCalendar:
		bindCalendar(binder, pValue, mod);
		break;
	case typeCalcKind:
		bindCalcKind(binder, pValue, mod);
		break;
	case typeAccount:
		bindAccount(binder, pValue, mod);
		break;
	case typeSubcKind:
		bindSubcKind(binder, pValue, mod);
		break;
	case typeChartOfAcc:
		break;
	default:
		binder.error("  ");
	}
}