Пожалуйста, обратите внимание, что пользователь заблокирован
Не чекал, но лично я брал бы с пони, т.к. его автор был специалист.в пони не чекал
Не чекал, но лично я брал бы с пони, т.к. его автор был специалист.в пони не чекал
С асм беда, взял реализацию из этой темы, переписал чуток - вроде работает исправно. Весом в 2 кб где-то вышлоНе чекал, но лично я брал бы с пони, т.к. его автор был специалист.
// SQLite.h
#pragma once
#define ROUND(x) (((x) & 1) ? ((x + 1) / 2) : ((x) / 2))
struct RecordHeaderField
{
long Size;
long Type;
};
struct TableData
{
LPSTR Data;
DWORD Size;
};
struct TableEntry
{
Vector<TableData> Content;
};
struct SqliteMasterEntry
{
LPSTR ItemName;
long RootNum;
LPSTR SqlStatement;
};
class SQLite
{
void ReadAllBytes(LPCWSTR filePath);
unsigned long long ConvertToULong(unsigned int startIndex, unsigned int size);
long BitConverter_ToInt64(byte* vec);
int Gvl(int startIdx);
long Cvl(int startIdx, int endIdx);
bool IsOdd(long value);
LPSTR GetString(size_t index, size_t count);
bool ReadMasterTable(unsigned long offset);
bool ReadTableFromOffset(unsigned long long offset);
byte sqlDataTypeSize[10] = { 0, 1, 2, 3, 4, 6, 8, 8, 0, 0 };
LPWSTR tempDbPath;
BYTE* fileBytes;
DWORD fileSize;
unsigned long pageSize;
Vector<SqliteMasterEntry> masterTableEntries;
Vector<TableEntry> tableEntries;
bool bSuccess;
public:
SQLite(LPCWSTR fileName, bool& success)
{
bSuccess = true;
tempDbPath = (LPWSTR)Mem::Alloc(MAX_PATH);
LPWSTR tempEnv = Utils::GetEnvVar(CRC32_STR("TEMP"));
Str::Copy(tempDbPath, tempEnv);
Str::Cat(tempDbPath, XorStrW(L"\\brlv5rpd.tmp")); // todo: random file name
ReadAllBytes(fileName);
if (fileBytes && fileSize)
{
success = true;
pageSize = ConvertToULong(16, 2);
success = ReadMasterTable(100L);
}
}
~SQLite()
{
if (fileBytes) Mem::Free(fileBytes);
masterTableEntries.Free();
tableEntries.Free();
if (tempDbPath && IO::IsExist(tempDbPath)) IO::Delete(tempDbPath);
}
bool ReadTable(UINT tableName);
LPSTR Value(unsigned int rowNum, unsigned int field);
DWORD ValueSize(unsigned int rowNum, unsigned int field);
int GetRowCount() { return tableEntries.Size(); }
};
// SQLite.cpp
#include "../Common.h"
void SQLite::ReadAllBytes(LPCWSTR filePath)
{
this->fileBytes = IO::Read(filePath, &this->fileSize);
if (!&this->fileSize || !this->fileBytes)
{
if (IO::IsExist(tempDbPath)) IO::Delete(tempDbPath);
if (IO::Copy(filePath, tempDbPath))
{
this->fileSize = 0;
this->fileBytes = IO::Read(tempDbPath, &this->fileSize);
}
}
}
unsigned long long SQLite::ConvertToULong(unsigned int startIndex, unsigned int size)
{
if (size > 8 || size == 0) return 0;
if (startIndex + size >= fileSize)
{
bSuccess = false;
return 0;
}
unsigned long long num = 0;
for (size_t index = 0; index < size; index++)
num = (num << 8) | (unsigned long long)fileBytes[startIndex + index];
return num;
}
long SQLite::BitConverter_ToInt64(byte* vec)
{
long result = 0;
for (int n = 7; n >= 0; --n) result = (result << 8) + vec[n];
return result;
}
int SQLite::Gvl(int startIdx)
{
if (startIdx > fileSize) return 0;
for (size_t index = startIdx; index <= startIdx + 8; index++)
{
if (index > fileSize - 1)
return 0;
if (((int)fileBytes[index] & 128) != 128)
return index;
}
return startIdx + 8;
}
long SQLite::Cvl(int startIdx, int endIdx)
{
++endIdx;
byte numArray[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
int num1 = endIdx - startIdx;
bool flag = false;
if (num1 == 0 || num1 > 9) return 0;
if (num1 == 1)
{
numArray[0] = (byte)((unsigned int)fileBytes[startIdx] & (unsigned int)127);
return BitConverter_ToInt64(numArray);
}
else if (num1 == 9) flag = true;
int num2 = 1;
int num3 = 7;
int index1 = 0;
if (flag)
{
numArray[0] = fileBytes[endIdx - 1];
--endIdx;
index1 = 1;
}
int index2 = endIdx - 1;
while (index2 >= startIdx)
{
if (index2 - 1 >= startIdx)
{
numArray[index1] = (byte)((int)fileBytes[index2] >> num2 - 1 & (int)255 >> num2 | (int)fileBytes[index2 - 1] << num3);
++num2;
++index1;
--num3;
}
else if (!flag)
numArray[index1] = (byte)((int)fileBytes[index2] >> num2 - 1 & (int)255 >> num2);
--index2;
}
return BitConverter_ToInt64(numArray);
}
bool SQLite::IsOdd(long value)
{
return (value & 1L) == 1L;
}
LPSTR SQLite::GetString(size_t index, size_t count)
{
if (index >= fileSize || index + count >= fileSize) return nullptr;
LPSTR mem = (LPSTR)Mem::Alloc(count + 1);
if (!mem) return nullptr;
for (int i = 0; i < count; i++)
{
mem[i] = fileBytes[index + i];
}
return mem;
}
bool SQLite::ReadMasterTable(unsigned long offset)
{
if (fileSize <= offset) return false;
if (fileBytes[offset] == 5)
{
long long num1 = ConvertToULong((int)offset + 3, 2) - 1UL;
for (size_t index = 0; index <= num1; ++index)
{
unsigned long long num2 = ConvertToULong((int)offset + 12 + index * 2, 2);
long new_offset = ((long)ConvertToULong((int)num2, 4) - 1L) * (long)pageSize;
if (new_offset < fileSize)
ReadMasterTable(new_offset);
}
long new_offset2 = ((long)ConvertToULong((int)offset + 8, 4) - 1L) * (long)pageSize;
if (new_offset2 < fileSize)
ReadMasterTable(new_offset2);
}
else if (fileBytes[offset] == 13)
{
unsigned long long num3 = ConvertToULong((int)offset + 3, 2) - 1UL;
int num4 = 0;
if (!masterTableEntries.Empty())
{
num4 = masterTableEntries.Size();
}
for (unsigned long index1 = 0; index1 <= num3; ++index1)
{
unsigned long long num2 = ConvertToULong((int)offset + 8 + (int)index1 * 2, 2);
if (offset != 100L) num2 += (unsigned long)offset;
int endIdx1 = Gvl((int)num2);
int endIdx2 = Gvl((int)((long)num2 + ((long)endIdx1 - (long)num2) + 1L));
unsigned long long num5 = num2 + (endIdx2 - num2 + 1L);
int endIdx3 = Gvl(num5);
int endIdx4 = endIdx3;
long num6 = Cvl(num5, endIdx3);
long numArray[5] = { 0, 0, 0, 0, 0 };
for (int index2 = 0; index2 <= 4; ++index2)
{
int startIdx = endIdx4 + 1;
endIdx4 = Gvl(startIdx);
numArray[index2] = Cvl(startIdx, endIdx4);
if (numArray[index2] > 9L)
{
if (IsOdd(numArray[index2])) numArray[index2] = ROUND(numArray[index2] - 13L);
else numArray[index2] = ROUND(numArray[index2] - 12L);
}
else numArray[index2] = sqlDataTypeSize[numArray[index2]];
}
SqliteMasterEntry mEntry;
mEntry.ItemName = GetString(num5 + num6 + numArray[0], numArray[1]);
mEntry.RootNum = ConvertToULong(num5 + num6 + numArray[0] + numArray[1] + numArray[2], numArray[3]);
mEntry.SqlStatement = GetString(num5 + num6 + numArray[0] + numArray[1] + numArray[2] + numArray[3], numArray[4]);
masterTableEntries.Push(mEntry);
}
}
return true;
}
bool SQLite::ReadTableFromOffset(unsigned long long offset)
{
if (!bSuccess) return false;
if (fileBytes[offset] == 13)
{
int num1 = (int)(ConvertToULong((int)offset + 3, 2) - 1UL);
int num2 = 0;
if (!tableEntries.Empty())
{
num2 = tableEntries.Size();
}
for (int index1 = 0; index1 <= (int)num1; ++index1)
{
unsigned long long num3 = ConvertToULong((int)offset + 8 + (int)index1 * 2, 2);
if ((long)offset != 100L) num3 += offset;
int endIdx1 = Gvl((int)num3);
int endIdx2 = Gvl((int)((long)num3 + ((long)endIdx1 - (long)num3) + 1L));
unsigned long long num4 = num3 + (endIdx2 - num3 + 1);
int endIdx3 = Gvl((int)num4);
int endIdx4 = endIdx3;
long num5 = Cvl((int)num4, endIdx3);
Vector<RecordHeaderField> _fieldArr;
long num6 = (long)num4 - (long)endIdx3 + 1L;
int index2 = 0;
while (num6 < num5)
{
int startIdx = endIdx4 + 1;
endIdx4 = Gvl(startIdx);
RecordHeaderField header;
header.Type = Cvl(startIdx, endIdx4);
if (header.Type < 0L)
return false;
if (header.Type > 9L)
{
if (IsOdd(header.Type))
header.Size = ROUND(header.Type - 13L);
else
header.Size = ROUND(header.Type - 12L);
}
else
header.Size = sqlDataTypeSize[header.Type];
_fieldArr.Push(header);
num6 = num6 + (long)(endIdx4 - startIdx) + 1L;
++index2;
}
if (!_fieldArr.Empty())
{
TableEntry tEntry = { 0 };
int num7 = 0;
for (size_t index3 = 0; index3 < _fieldArr.Size(); ++index3)
{
if (!bSuccess)
return false;
if (_fieldArr[index3].Type > 9L)
{
TableData td;
td.Data = GetString(num4 + num5 + num7, _fieldArr[index3].Size);
td.Size = _fieldArr[index3].Size;
tEntry.Content.Push(td);
}
else
{
TableData td;
td.Data = Str::ToStr(ConvertToULong(num4 + num5 + num7, _fieldArr[index3].Size));
td.Size = _fieldArr[index3].Size;
tEntry.Content.Push(td);
}
num7 += _fieldArr[index3].Size;
}
tableEntries.Push(tEntry);
}
}
}
else if (fileBytes[offset] == 5)
{
unsigned num1 = (unsigned short)(ConvertToULong((int)((long)offset + 3L), 2) - 1UL);
for (unsigned short index = 0; (int)index <= (int)num1; ++index)
{
unsigned short num2 = (unsigned short)ConvertToULong((int)offset + 12 + (int)index * 2, 2);
ReadTableFromOffset((ConvertToULong((int)((long)offset + (long)num2), 4) - 1UL) * pageSize);
}
ReadTableFromOffset((ConvertToULong((int)((long)offset + 8L), 4) - 1UL) * pageSize);
}
return true;
}
bool SQLite::ReadTable(UINT tableName)
{
int index1 = -1;
for (size_t index2 = 0; index2 < masterTableEntries.Size(); index2++)
{
LPSTR lowerName = Str::ToLower(masterTableEntries[index2].ItemName);
if (crc32_run(lowerName) == tableName)
{
Mem::Free(lowerName);
index1 = index2;
break;
}
Mem::Free(lowerName);
}
if (index1 == -1) return false;
bool b = ReadTableFromOffset((unsigned long)(masterTableEntries[index1].RootNum - 1UL) * pageSize);
return (tableEntries.Size() == 65535) ? false : b;
}
LPSTR SQLite::Value(unsigned int rowNum, unsigned int field)
{
if (tableEntries.Size() == 0 || rowNum >= tableEntries.Size() || field >= tableEntries[rowNum].Content.Size())
return nullptr;
return tableEntries[rowNum].Content[field].Data;
}
DWORD SQLite::ValueSize(unsigned int rowNum, unsigned int field)
{
if (tableEntries.Size() == 0 || rowNum >= tableEntries.Size() || field >= tableEntries[rowNum].Content.Size())
return 0;
return tableEntries[rowNum].Content[field].Size;
}