2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-09 23:47:43 +00:00

additional database implementation; integrated blowfish

This commit is contained in:
Jack Andersen
2015-05-17 23:29:23 -10:00
parent 3cf64ed8da
commit e07ed779d6
13 changed files with 1291 additions and 35 deletions

View File

@@ -2,6 +2,8 @@
#error This file must only be included from HECLDatabase.cpp
#endif
#include <stdio.h>
#include "HECLDatabase.hpp"
#include "CSQLite.hpp"
@@ -34,7 +36,7 @@ public:
return m_access;
}
const IDataObject* lookupObject(std::size_t id) const
const IDataObject* lookupObject(size_t id) const
{
}
@@ -42,16 +44,26 @@ public:
{
}
const IDataObject* addDataBlob(const std::string& name, const void* data, std::size_t length)
const IDataObject* addDataBlob(const std::string& name, const void* data, size_t length)
{
}
const IDataObject* addDataBlob(const void* data, std::size_t length)
const IDataObject* addDataBlob(const void* data, size_t length)
{
}
bool writeDatabase(IDatabase::Type type, const std::string& path) const
{
if (type == PACKED)
{
size_t bufSz;
void* buf = m_sql.fillDBBuffer(bufSz);
FILE* fp = fopen(path.c_str(), "wb");
fwrite(buf, 1, bufSz, fp);
return true;
}
return false;
}
};

View File

@@ -14,7 +14,7 @@ class CMemoryDatabase final : public IDatabase
Access m_access;
public:
CMemoryDatabase(Access access)
: m_sql(":memory:"), m_access(access)
: m_sql(":memory:", (m_access == READONLY) ? true : false), m_access(access)
{
}
@@ -34,7 +34,7 @@ public:
return m_access;
}
const IDataObject* lookupObject(std::size_t id) const
const IDataObject* lookupObject(size_t id) const
{
}
@@ -42,11 +42,11 @@ public:
{
}
const IDataObject* addDataBlob(const std::string& name, const void* data, std::size_t length)
const IDataObject* addDataBlob(const std::string& name, const void* data, size_t length)
{
}
const IDataObject* addDataBlob(const void* data, std::size_t length)
const IDataObject* addDataBlob(const void* data, size_t length)
{
}

View File

@@ -13,7 +13,7 @@ class CPackedDatabase final : public IDatabase
CSQLite m_sql;
public:
CPackedDatabase(const std::string& path)
: m_sql(path.c_str(), (m_access == READONLY) ? true : false)
: m_sql(path.c_str(), true)
{
}
@@ -33,7 +33,7 @@ public:
return READONLY;
}
const IDataObject* lookupObject(std::size_t id) const
const IDataObject* lookupObject(size_t id) const
{
}
@@ -41,11 +41,11 @@ public:
{
}
const IDataObject* addDataBlob(const std::string& name, const void* data, std::size_t length)
const IDataObject* addDataBlob(const std::string& name, const void* data, size_t length)
{
}
const IDataObject* addDataBlob(const void* data, std::size_t length)
const IDataObject* addDataBlob(const void* data, size_t length)
{
}

View File

@@ -5,6 +5,9 @@
#include <stdexcept>
#include <functional>
#include "HECLDatabase.hpp"
#include "sqlite_hecl_vfs.h"
namespace HECLDatabase
{
@@ -36,21 +39,35 @@ if (sqlite3_prepare_v2(m_db, stmtSrc, 0, &outVar, NULL) != SQLITE_OK)\
class CSQLite
{
sqlite3* m_db;
sqlite3_stmt* m_selObjects;
sqlite3_stmt* m_selObjectByName;
sqlite3_stmt* m_selDistictDepGroups;
sqlite3_stmt* m_selDepGroupObjects;
sqlite3_stmt* m_insObject;
struct SCloseBuf
{
void* buf = NULL;
size_t sz = 0;
};
static void _vfsClose(void* buf, size_t bufSz, SCloseBuf* ctx)
{
ctx->buf = buf;
ctx->sz = bufSz;
}
public:
CSQLite(const char* path, bool readonly)
{
/* Open database connection */
if (sqlite3_open_v2(path, &m_db, readonly ?
SQLITE_OPEN_READONLY :
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE, NULL) != SQLITE_OK)
int errCode = 0;
if ((errCode = sqlite3_open_v2(path, &m_db, readonly ?
SQLITE_OPEN_READONLY :
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE, NULL)) != SQLITE_OK)
{
throw std::runtime_error(sqlite3_errmsg(m_db));
throw std::runtime_error(sqlite3_errstr(errCode));
sqlite3_close(m_db);
return;
}
@@ -71,6 +88,7 @@ public:
PREPSTMT("SELECT rowid FROM objects WHERE name=?1", m_selObjectByName);
PREPSTMT("SELECT DISTINCT groupId FROM deplinks", m_selDistictDepGroups);
PREPSTMT("SELECT DISTINCT objId FROM deplinks WHERE groupId=?1", m_selDepGroupObjects);
PREPSTMT("INSERT INTO objects(name,type4cc,hash64,compLen,decompLen) VALUES (?1,?2,?3,?4,?5)", m_insObject);
}
~CSQLite()
@@ -79,19 +97,21 @@ public:
sqlite3_finalize(m_selObjectByName);
sqlite3_finalize(m_selDistictDepGroups);
sqlite3_finalize(m_selDepGroupObjects);
sqlite3_finalize(m_insObject);
sqlite3_close(m_db);
}
void buildMemoryIndex(const std::function<void(std::size_t&&, // id
void buildMemoryIndex(const std::function<void(size_t&&, // id
const std::string&&, // name
uint32_t&&, // type4cc
uint64_t&&, // hash64
std::size_t&&, // compLen
std::size_t&&)>& // decompLen
size_t&&, // compLen
size_t&&)>& // decompLen
objectAdder)
{
while (sqlite3_step(m_selObjects) == SQLITE_ROW)
{
/* <3 Move Lambdas!! */
objectAdder(sqlite3_column_int64(m_selObjects, 0),
(const char*)sqlite3_column_text(m_selObjects, 1),
sqlite3_column_int(m_selObjects, 2),
@@ -102,16 +122,68 @@ public:
sqlite3_reset(m_selObjects);
}
std::size_t objectIdFromName(const std::string& name)
size_t objectIdFromName(const std::string& name)
{
sqlite3_bind_text(m_selObjectByName, 1, name.c_str(), name.length(), NULL);
std::size_t retval = 0;
size_t retval = 0;
if (sqlite3_step(m_selObjectByName) == SQLITE_ROW)
retval = sqlite3_column_int64(m_selObjectByName, 0);
sqlite3_reset(m_selObjectByName);
return retval;
}
bool insertObject(const std::string& name, const FourCC& type, const ObjectHash& hash, size_t compLen, size_t decompLen)
{
}
void* fillDBBuffer(size_t& bufSzOut) const
{
/* Instructs vfs that a close operation is premature and buffer should be freed */
sqlite_hecl_mem_vfs_register(NULL, NULL);
/* Open pure-memory DB */
sqlite3* memDb;
int errCode;
if ((errCode = sqlite3_open_v2("", &memDb, SQLITE_OPEN_READWRITE, "hecl_mem")) != SQLITE_OK)
{
throw std::runtime_error(sqlite3_errstr(errCode));
sqlite3_close(memDb);
return NULL;
}
/* Perform backup (row copy) */
sqlite3_backup* backup = sqlite3_backup_init(memDb, "main", m_db, "main");
if (!backup)
{
throw std::runtime_error(sqlite3_errmsg(memDb));
sqlite3_close(memDb);
return NULL;
}
sqlite3_backup_step(backup, -1);
sqlite3_backup_finish(backup);
/* Now a close operation is useful; register close callback */
SCloseBuf closeBuf;
sqlite_hecl_mem_vfs_register((TCloseCallback)_vfsClose, &closeBuf);
sqlite3_close(memDb);
/* This should be set by close callback */
if (!closeBuf.buf)
{
throw std::runtime_error("close operation did not write buffer");
return NULL;
}
/* All good! */
bufSzOut = closeBuf.sz;
return closeBuf.buf;
}
static void freeDBBuffer(void* buf)
{
sqlite3_free(buf);
}
};
}

View File

@@ -2,7 +2,9 @@ HEADERS += \
$$PWD/CPackedDatabase.hpp \
$$PWD/CMemoryDatabase.hpp \
$$PWD/CLooseDatabase.hpp \
$$PWD/CSQLite.hpp
$$PWD/CSQLite.hpp \
$$PWD/sqlite_hecl_vfs.h
SOURCES += \
$$PWD/HECLDatabase.cpp
$$PWD/HECLDatabase.cpp \
$$PWD/sqlite_hecl_mem_vfs.c

View File

@@ -0,0 +1,361 @@
#include "sqlite_hecl_vfs.h"
#include "sqlite3.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/*
* Modified test_onefile.c VFS for sqlite3
*
* This VFS gets registered with sqlite to access an in-memory,
* block-compressed LBA. It's designed for read-only access of
* a packed object-database.
*
* Journal and temp read/write is unsupported and will call abort
* if attempted.
*/
/*
* App-supplied callback called when file is closed (ready to access)
*/
static TCloseCallback CLOSE_CALLBACK = NULL;
static void* CLOSE_CTX = NULL;
typedef struct mem_file mem_file;
struct mem_file {
sqlite3_file base;
int nSize;
int nAlloc;
char *zAlloc;
};
/*
** Method declarations for mem_file.
*/
static int memClose(sqlite3_file*);
static int memRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int memWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
static int memTruncate(sqlite3_file*, sqlite3_int64 size);
static int memSync(sqlite3_file*, int flags);
static int memFileSize(sqlite3_file*, sqlite3_int64 *pSize);
static int memLock(sqlite3_file*, int);
static int memUnlock(sqlite3_file*, int);
static int memCheckReservedLock(sqlite3_file*, int *pResOut);
static int memFileControl(sqlite3_file*, int op, void *pArg);
static int memSectorSize(sqlite3_file*);
static int memDeviceCharacteristics(sqlite3_file*);
/*
** Method declarations for fs_vfs.
*/
static int memOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int memDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int memAccess(sqlite3_vfs*, const char *zName, int flags, int *);
static int memFullPathname(sqlite3_vfs*, const char *zName, int nOut,char *zOut);
static void *memDlOpen(sqlite3_vfs*, const char *zFilename);
static void memDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void (*memDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
static void memDlClose(sqlite3_vfs*, void*);
static int memRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int memSleep(sqlite3_vfs*, int microseconds);
static int memCurrentTime(sqlite3_vfs*, double*);
static sqlite3_vfs mem_vfs = {
1, /* iVersion */
0, /* szOsFile */
0, /* mxPathname */
0, /* pNext */
"hecl_mem", /* zName */
0, /* pAppData */
memOpen, /* xOpen */
memDelete, /* xDelete */
memAccess, /* xAccess */
memFullPathname, /* xFullPathname */
memDlOpen, /* xDlOpen */
memDlError, /* xDlError */
memDlSym, /* xDlSym */
memDlClose, /* xDlClose */
memRandomness, /* xRandomness */
memSleep, /* xSleep */
memCurrentTime, /* xCurrentTime */
0 /* xCurrentTimeInt64 */
};
static sqlite3_io_methods mem_io_methods = {
1, /* iVersion */
memClose, /* xClose */
memRead, /* xRead */
memWrite, /* xWrite */
memTruncate, /* xTruncate */
memSync, /* xSync */
memFileSize, /* xFileSize */
memLock, /* xLock */
memUnlock, /* xUnlock */
memCheckReservedLock, /* xCheckReservedLock */
memFileControl, /* xFileControl */
memSectorSize, /* xSectorSize */
memDeviceCharacteristics, /* xDeviceCharacteristics */
0, /* xShmMap */
0, /* xShmLock */
0, /* xShmBarrier */
0, /* xShmUnmap */
0,
0
};
/* Useful macros used in several places */
#define MIN(x,y) ((x)<(y)?(x):(y))
#define MAX(x,y) ((x)>(y)?(x):(y))
/*
** Close a mem-file.
*/
static int memClose(sqlite3_file *pFile){
mem_file *pTmp = (mem_file *)pFile;
if (CLOSE_CALLBACK)
CLOSE_CALLBACK(pTmp->zAlloc, pTmp->nSize, CLOSE_CTX);
else
sqlite3_free(pTmp->zAlloc);
return SQLITE_OK;
}
/*
** Read data from a mem-file.
*/
static int memRead(
sqlite3_file *pFile,
void *zBuf,
int iAmt,
sqlite_int64 iOfst
){
mem_file *pTmp = (mem_file *)pFile;
if( (iAmt+iOfst)>pTmp->nSize ){
return SQLITE_IOERR_SHORT_READ;
}
memcpy(zBuf, &pTmp->zAlloc[iOfst], iAmt);
return SQLITE_OK;
}
/*
** Write data to a mem-file.
*/
static int memWrite(
sqlite3_file *pFile,
const void *zBuf,
int iAmt,
sqlite_int64 iOfst
){
mem_file *pTmp = (mem_file *)pFile;
if( (iAmt+iOfst)>pTmp->nAlloc ){
int nNew = (int)(2*(iAmt+iOfst+pTmp->nAlloc));
char *zNew = sqlite3_realloc(pTmp->zAlloc, nNew);
if( !zNew ){
return SQLITE_NOMEM;
}
pTmp->zAlloc = zNew;
pTmp->nAlloc = nNew;
}
memcpy(&pTmp->zAlloc[iOfst], zBuf, iAmt);
pTmp->nSize = (int)MAX(pTmp->nSize, iOfst+iAmt);
return SQLITE_OK;
}
/*
** Truncate a mem-file.
*/
static int memTruncate(sqlite3_file *pFile, sqlite_int64 size){
mem_file *pTmp = (mem_file *)pFile;
pTmp->nSize = (int)MIN(pTmp->nSize, size);
return SQLITE_OK;
}
/*
** Sync a mem-file.
*/
static int memSync(sqlite3_file *pFile, int flags){
return SQLITE_OK;
}
/*
** Return the current file-size of a mem-file.
*/
static int memFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
mem_file *pTmp = (mem_file *)pFile;
*pSize = pTmp->nSize;
return SQLITE_OK;
}
/*
** Lock a mem-file.
*/
static int memLock(sqlite3_file *pFile, int eLock){
return SQLITE_OK;
}
/*
** Unlock a mem-file.
*/
static int memUnlock(sqlite3_file *pFile, int eLock){
return SQLITE_OK;
}
/*
** Check if another file-handle holds a RESERVED lock on a mem-file.
*/
static int memCheckReservedLock(sqlite3_file *pFile, int *pResOut){
*pResOut = 0;
return SQLITE_OK;
}
/*
** File control method. For custom operations on a mem-file.
*/
static int memFileControl(sqlite3_file *pFile, int op, void *pArg){
return SQLITE_OK;
}
/*
** Return the sector-size in bytes for a mem-file.
*/
static int memSectorSize(sqlite3_file *pFile){
return 0;
}
/*
** Return the device characteristic flags supported by a mem-file.
*/
static int memDeviceCharacteristics(sqlite3_file *pFile){
return 0;
}
/*
** Open an mem file handle.
*/
static int memOpen(
sqlite3_vfs *pVfs,
const char *zName,
sqlite3_file *pFile,
int flags,
int *pOutFlags
){
if (flags != SQLITE_OPEN_MAIN_DB)
{
fprintf(stderr, "the sqlite hecl mem VFS only supports main-db writing\n");
abort();
}
mem_file *p2 = (mem_file *)pFile;
memset(p2, 0, sizeof(*p2));
p2->base.pMethods = &mem_io_methods;
return SQLITE_OK;
}
/*
** Delete the file located at zPath. If the dirSync argument is true,
** ensure the file-system modifications are synced to disk before
** returning.
*/
static int memDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
return SQLITE_OK;
}
/*
** Test for access permissions. Return true if the requested permission
** is available, or false otherwise.
*/
static int memAccess(
sqlite3_vfs *pVfs,
const char *zPath,
int flags,
int *pResOut
){
if (flags & SQLITE_ACCESS_READ | SQLITE_ACCESS_READWRITE)
return 1;
return 0;
}
/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (FS_MAX_PATHNAME+1) bytes.
*/
static int memFullPathname(
sqlite3_vfs *pVfs, /* Pointer to vfs object */
const char *zPath, /* Possibly relative input path */
int nOut, /* Size of output buffer in bytes */
char *zOut /* Output buffer */
){
strncpy(zOut, zPath, nOut);
return SQLITE_OK;
}
/*
** Open the dynamic library located at zPath and return a handle.
*/
static void *memDlOpen(sqlite3_vfs *pVfs, const char *zPath){
return NULL;
}
/*
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
** utf-8 string describing the most recent error encountered associated
** with dynamic libraries.
*/
static void memDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
}
/*
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
*/
static void (*memDlSym(sqlite3_vfs *pVfs, void *pH, const char *zSym))(void){
}
/*
** Close the dynamic library handle pHandle.
*/
static void memDlClose(sqlite3_vfs *pVfs, void *pHandle){
}
/*
** Populate the buffer pointed to by zBufOut with nByte bytes of
** random data.
*/
static int memRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
for (int i=0 ; i<nByte ; ++i)
zBufOut[i] = rand();
return nByte;
}
/*
** Sleep for nMicro microseconds. Return the number of microseconds
** actually slept.
*/
static int memSleep(sqlite3_vfs *pVfs, int nMicro){
int seconds = (nMicro+999999)/1000000;
sleep(seconds);
return seconds*1000000;
}
/*
** Return the current time as a Julian Day number in *pTimeOut.
*/
static int memCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
*pTimeOut = 0.0;
return 0;
}
/*
** This procedure registers the mem vfs with SQLite. If the argument is
** true, the mem vfs becomes the new default vfs. It is the only publicly
** available function in this file.
*/
int sqlite_hecl_mem_vfs_register(TCloseCallback closeCb, void* ctx){
CLOSE_CALLBACK = closeCb;
CLOSE_CTX = ctx;
if (mem_vfs.szOsFile) return SQLITE_OK;
mem_vfs.szOsFile = sizeof(mem_file);
return sqlite3_vfs_register(&mem_vfs, 0);
}

View File

@@ -0,0 +1,17 @@
#ifndef SQLITE_HECL_VFS
#define SQLITE_HECL_VFS
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
typedef void(*TCloseCallback)(void* buf, size_t bufLen, void* ctx);
int sqlite_hecl_mem_vfs_register(TCloseCallback closeCb, void* ctx);
int sqlite_hecl_memlba_vfs_register(TCloseCallback closeCb, void* ctx);
#ifdef __cplusplus
}
#endif
#endif // SQLITE_HECL_VFS