Commit cb6a8d61 authored by fallenstardust's avatar fallenstardust Committed by GitHub

Merge pull request #22 from mercury233/patch-zip

merge zip support
parents 445e34ac 592058c4
...@@ -7,19 +7,37 @@ namespace ygo { ...@@ -7,19 +7,37 @@ namespace ygo {
const wchar_t* DataManager::unknown_string = L"???"; const wchar_t* DataManager::unknown_string = L"???";
wchar_t DataManager::strBuffer[4096]; wchar_t DataManager::strBuffer[4096];
byte DataManager::scriptBuffer[0x20000]; byte DataManager::scriptBuffer[0x20000];
IFileSystem* DataManager::FileSystem;
DataManager dataManager; DataManager dataManager;
bool DataManager::LoadDB(const char* file) { bool DataManager::LoadDB(const wchar_t* wfile) {
sqlite3* pDB; char file[256];
BufferIO::EncodeUTF8(wfile, file);
#ifdef _WIN32
IReadFile* reader = FileSystem->createAndOpenFile(wfile);
#else
IReadFile* reader = FileSystem->createAndOpenFile(file);
#endif
if(reader == NULL)
return false;
spmemvfs_db_t db;
spmembuffer_t* mem = (spmembuffer_t*)calloc(sizeof(spmembuffer_t), 1);
spmemvfs_env_init();
mem->total = mem->used = reader->getSize();
mem->data = (char*)malloc(mem->total + 1);
reader->read(mem->data, mem->total);
reader->drop();
(mem->data)[mem->total] = '\0';
int err = 0; int err = 0;
if((err = sqlite3_open_v2(file, &pDB, SQLITE_OPEN_READONLY, 0)) != SQLITE_OK) if((err = spmemvfs_open_db(&db, file, mem)) != SQLITE_OK)
return Error(pDB, NULL, err); return Error(&db, NULL, err);
sqlite3* pDB = db.handle;
sqlite3_stmt* pStmt; sqlite3_stmt* pStmt;
const char* sql_2 = "select datas._id, ot, alias, setcode, type, atk, def, level, race, attribute, category, texts.* from datas,texts where datas._id = texts._id;"; const char* sql_2 = "select datas._id, ot, alias, setcode, type, atk, def, level, race, attribute, category, texts.* from datas,texts where datas._id = texts._id;";
const char* sql = "select datas.id, ot, alias, setcode, type, atk, def, level, race, attribute, category, texts.* from datas,texts where datas.id = texts.id;"; const char* sql = "select datas.id, ot, alias, setcode, type, atk, def, level, race, attribute, category, texts.* from datas,texts where datas.id = texts.id;";
if((err = sqlite3_prepare_v2(pDB, sql, -1, &pStmt, 0)) != SQLITE_OK){ if((err = sqlite3_prepare_v2(pDB, sql, -1, &pStmt, 0)) != SQLITE_OK){
if((err = sqlite3_prepare_v2(pDB,sql_2, -1, &pStmt, 0)) != SQLITE_OK){ if((err = sqlite3_prepare_v2(pDB,sql_2, -1, &pStmt, 0)) != SQLITE_OK){
return Error(pDB, NULL, err); return Error(&db, NULL, err);
} }
} }
CardDataC cd; CardDataC cd;
...@@ -28,7 +46,7 @@ bool DataManager::LoadDB(const char* file) { ...@@ -28,7 +46,7 @@ bool DataManager::LoadDB(const char* file) {
do { do {
step = sqlite3_step(pStmt); step = sqlite3_step(pStmt);
if(step == SQLITE_BUSY || step == SQLITE_ERROR || step == SQLITE_MISUSE) if(step == SQLITE_BUSY || step == SQLITE_ERROR || step == SQLITE_MISUSE)
return Error(pDB, pStmt); return Error(&db, pStmt);
else if(step == SQLITE_ROW) { else if(step == SQLITE_ROW) {
cd.code = sqlite3_column_int(pStmt, 0); cd.code = sqlite3_column_int(pStmt, 0);
cd.ot = sqlite3_column_int(pStmt, 1); cd.ot = sqlite3_column_int(pStmt, 1);
...@@ -68,7 +86,8 @@ bool DataManager::LoadDB(const char* file) { ...@@ -68,7 +86,8 @@ bool DataManager::LoadDB(const char* file) {
} }
} while(step != SQLITE_DONE); } while(step != SQLITE_DONE);
sqlite3_finalize(pStmt); sqlite3_finalize(pStmt);
sqlite3_close(pDB); spmemvfs_close_db(&db);
spmemvfs_env_fini();
return true; return true;
} }
bool DataManager::LoadStrings(const char* file) { bool DataManager::LoadStrings(const char* file) {
...@@ -76,11 +95,34 @@ bool DataManager::LoadStrings(const char* file) { ...@@ -76,11 +95,34 @@ bool DataManager::LoadStrings(const char* file) {
if(!fp) if(!fp)
return false; return false;
char linebuf[256]; char linebuf[256];
char strbuf[256];
int value;
while(fgets(linebuf, 256, fp)) { while(fgets(linebuf, 256, fp)) {
ReadStringConfLine(linebuf);
}
fclose(fp);
for(int i = 0; i < 255; ++i)
myswprintf(numStrings[i], L"%d", i);
return true;
}
bool DataManager::LoadStrings(IReadFile* reader) {
char ch[2] = " ";
char linebuf[256] = "";
while(reader->read(&ch[0], 1)) {
if(ch[0] == '\0')
break;
strcat(linebuf, ch);
if(ch[0] == '\n') {
ReadStringConfLine(linebuf);
linebuf[0] = '\0';
}
}
reader->drop();
return true;
}
void DataManager::ReadStringConfLine(const char* linebuf) {
if(linebuf[0] != '!') if(linebuf[0] != '!')
continue; return;
char strbuf[256];
int value;
sscanf(linebuf, "!%s", strbuf); sscanf(linebuf, "!%s", strbuf);
if(!strcmp(strbuf, "system")) { if(!strcmp(strbuf, "system")) {
sscanf(&linebuf[7], "%d %240[^\n]", &value, strbuf); sscanf(&linebuf[7], "%d %240[^\n]", &value, strbuf);
...@@ -99,14 +141,9 @@ bool DataManager::LoadStrings(const char* file) { ...@@ -99,14 +141,9 @@ bool DataManager::LoadStrings(const char* file) {
BufferIO::DecodeUTF8(strbuf, strBuffer); BufferIO::DecodeUTF8(strbuf, strBuffer);
_setnameStrings[value] = strBuffer; _setnameStrings[value] = strBuffer;
} }
}
fclose(fp);
for(int i = 0; i < 255; ++i)
myswprintf(numStrings[i], L"%d", i);
return true;
} }
bool DataManager::Error(sqlite3* pDB, sqlite3_stmt* pStmt, int errNo) { bool DataManager::Error(spmemvfs_db_t* pDB, sqlite3_stmt* pStmt, int errNo) {
const char* msg = sqlite3_errmsg(pDB); const char* msg = sqlite3_errmsg(pDB->handle);
BufferIO::DecodeUTF8(msg, strBuffer); BufferIO::DecodeUTF8(msg, strBuffer);
if(pStmt) if(pStmt)
sqlite3_finalize(pStmt); sqlite3_finalize(pStmt);
...@@ -114,7 +151,8 @@ bool DataManager::Error(sqlite3* pDB, sqlite3_stmt* pStmt, int errNo) { ...@@ -114,7 +151,8 @@ bool DataManager::Error(sqlite3* pDB, sqlite3_stmt* pStmt, int errNo) {
char buff[len+32]; char buff[len+32];
sprintf(buff, "cdb Error code=%d,msg=%s", errNo, msg); sprintf(buff, "cdb Error code=%d,msg=%s", errNo, msg);
os::Printer::log(buff); os::Printer::log(buff);
sqlite3_close(pDB); spmemvfs_close_db(pDB);
spmemvfs_env_fini();
return false; return false;
} }
bool DataManager::GetData(int code, CardData* pData) { bool DataManager::GetData(int code, CardData* pData) {
...@@ -344,14 +382,7 @@ byte* DataManager::ScriptReaderEx(const char* script_name, int* slen) { ...@@ -344,14 +382,7 @@ byte* DataManager::ScriptReaderEx(const char* script_name, int* slen) {
return ScriptReaderZip(second, slen); return ScriptReaderZip(second, slen);
} }
byte* DataManager::ScriptReader(const char* script_name, int* slen) { byte* DataManager::ScriptReader(const char* script_name, int* slen) {
FILE *fp; FILE *fp = fopen(script_name, "rb");
#ifdef _WIN32
wchar_t fname[256];
BufferIO::DecodeUTF8(script_name, fname);
fp = _wfopen(fname, L"rb");
#else
fp = fopen(script_name, "rb");
#endif
if(!fp) if(!fp)
return 0; return 0;
int len = fread(scriptBuffer, 1, sizeof(scriptBuffer), fp); int len = fread(scriptBuffer, 1, sizeof(scriptBuffer), fp);
...@@ -362,10 +393,7 @@ byte* DataManager::ScriptReader(const char* script_name, int* slen) { ...@@ -362,10 +393,7 @@ byte* DataManager::ScriptReader(const char* script_name, int* slen) {
return scriptBuffer; return scriptBuffer;
} }
byte* DataManager::ScriptReaderZip(const char* script_name, int* slen) { byte* DataManager::ScriptReaderZip(const char* script_name, int* slen) {
wchar_t fname[256]; IReadFile* reader = FileSystem->createAndOpenFile(script_name);
BufferIO::DecodeUTF8(script_name, fname);
IFileSystem* fs = mainGame->device->getFileSystem();
IReadFile* reader = fs->createAndOpenFile(fname);
if(reader == NULL) if(reader == NULL)
return 0; return 0;
size_t size = reader->getSize(); size_t size = reader->getSize();
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#else #else
#include "sqlite3.h" #include "sqlite3.h"
#endif #endif
#include "spmemvfs/spmemvfs.h"
#include "client_card.h" #include "client_card.h"
#include <unordered_map> #include <unordered_map>
...@@ -15,9 +16,11 @@ namespace ygo { ...@@ -15,9 +16,11 @@ namespace ygo {
class DataManager { class DataManager {
public: public:
DataManager(): _datas(8192), _strings(8192) {} DataManager(): _datas(8192), _strings(8192) {}
bool LoadDB(const char* file); bool LoadDB(const wchar_t* wfile);
bool LoadStrings(const char* file); bool LoadStrings(const char* file);
bool Error(sqlite3* pDB, sqlite3_stmt* pStmt = 0, int err=0); bool LoadStrings(IReadFile* reader);
void ReadStringConfLine(const char* linebuf);
bool Error(spmemvfs_db_t* pDB, sqlite3_stmt* pStmt = 0, int err = 0);
bool GetData(int code, CardData* pData); bool GetData(int code, CardData* pData);
code_pointer GetCodePointer(int code); code_pointer GetCodePointer(int code);
bool GetString(int code, CardString* pStr); bool GetString(int code, CardString* pStr);
...@@ -59,7 +62,7 @@ public: ...@@ -59,7 +62,7 @@ public:
static byte* ScriptReaderEx(const char* script_name, int* slen); static byte* ScriptReaderEx(const char* script_name, int* slen);
static byte* ScriptReader(const char* script_name, int* slen); static byte* ScriptReader(const char* script_name, int* slen);
static byte* ScriptReaderZip(const char* script_name, int* slen); static byte* ScriptReaderZip(const char* script_name, int* slen);
static IFileSystem* FileSystem;
}; };
extern DataManager dataManager; extern DataManager dataManager;
......
...@@ -73,7 +73,7 @@ bool Game::Initialize() { ...@@ -73,7 +73,7 @@ bool Game::Initialize() {
ILogger* logger = device->getLogger(); ILogger* logger = device->getLogger();
// logger->setLogLevel(ELL_WARNING); // logger->setLogLevel(ELL_WARNING);
isPSEnabled = options->isPendulumScaleEnabled(); isPSEnabled = options->isPendulumScaleEnabled();
IFileSystem * fs = device->getFileSystem(); dataManager.FileSystem = device->getFileSystem();
xScale = android::getScreenHeight(app) / 1024.0; xScale = android::getScreenHeight(app) / 1024.0;
yScale = android::getScreenWidth(app) / 640.0; yScale = android::getScreenWidth(app) / 640.0;
/* if (xScale < yScale) { /* if (xScale < yScale) {
...@@ -88,7 +88,7 @@ bool Game::Initialize() { ...@@ -88,7 +88,7 @@ bool Game::Initialize() {
char log_working[256] = {0}; char log_working[256] = {0};
sprintf(log_working, "workingDir= %s", workingDir.c_str()); sprintf(log_working, "workingDir= %s", workingDir.c_str());
Printer::log(log_working); Printer::log(log_working);
fs->changeWorkingDirectoryTo(workingDir); dataManager.FileSystem->changeWorkingDirectoryTo(workingDir);
/* Your media must be somewhere inside the assets folder. The assets folder is the root for the file system. /* Your media must be somewhere inside the assets folder. The assets folder is the root for the file system.
This example copies the media in the Android.mk makefile. */ This example copies the media in the Android.mk makefile. */
...@@ -97,9 +97,9 @@ bool Game::Initialize() { ...@@ -97,9 +97,9 @@ bool Game::Initialize() {
// The Android assets file-system does not know which sub-directories it has (blame google). // The Android assets file-system does not know which sub-directories it has (blame google).
// So we have to add all sub-directories in assets manually. Otherwise we could still open the files, // So we have to add all sub-directories in assets manually. Otherwise we could still open the files,
// but existFile checks will fail (which are for example needed by getFont). // but existFile checks will fail (which are for example needed by getFont).
for ( u32 i=0; i < fs->getFileArchiveCount(); ++i ) for ( u32 i=0; i < dataManager.FileSystem->getFileArchiveCount(); ++i )
{ {
IFileArchive* archive = fs->getFileArchive(i); IFileArchive* archive = dataManager.FileSystem->getFileArchive(i);
if ( archive->getType() == EFAT_ANDROID_ASSET ) if ( archive->getType() == EFAT_ANDROID_ASSET )
{ {
archive->addDirectoryToFileList(mediaPath); archive->addDirectoryToFileList(mediaPath);
...@@ -111,7 +111,7 @@ bool Game::Initialize() { ...@@ -111,7 +111,7 @@ bool Game::Initialize() {
int len = options->getArchiveCount(); int len = options->getArchiveCount();
for(int i=0;i<len;i++){ for(int i=0;i<len;i++){
io::path zip_path = zips[i]; io::path zip_path = zips[i];
if(fs->addFileArchive(zip_path.c_str(), false, false, EFAT_ZIP)) { if(dataManager.FileSystem->addFileArchive(zip_path.c_str(), false, false, EFAT_ZIP)) {
os::Printer::log("add arrchive ok ", zip_path.c_str()); os::Printer::log("add arrchive ok ", zip_path.c_str());
}else{ }else{
os::Printer::log("add arrchive fail ", zip_path.c_str()); os::Printer::log("add arrchive fail ", zip_path.c_str());
...@@ -170,12 +170,16 @@ bool Game::Initialize() { ...@@ -170,12 +170,16 @@ bool Game::Initialize() {
imageManager.SetDevice(device); imageManager.SetDevice(device);
if(!imageManager.Initial(workingDir)) if(!imageManager.Initial(workingDir))
return false; return false;
LoadExpansions();
// LoadExpansions only load zips, the other cdb databases are still loaded by getDBFiles
io::path* cdbs = options->getDBFiles(); io::path* cdbs = options->getDBFiles();
len = options->getDbCount(); len = options->getDbCount();
//os::Printer::log("load cdbs count %d", len); //os::Printer::log("load cdbs count %d", len);
for(int i=0;i<len;i++){ for(int i=0;i<len;i++){
io::path cdb_path = cdbs[i]; io::path cdb_path = cdbs[i];
if(dataManager.LoadDB(cdb_path.c_str())) { wchar_t wpath[1024];
BufferIO::DecodeUTF8(cdb_path.c_str(), wpath);
if(dataManager.LoadDB(wpath)) {
os::Printer::log("add cdb ok ", cdb_path.c_str()); os::Printer::log("add cdb ok ", cdb_path.c_str());
}else{ }else{
os::Printer::log("add cdb fail ", cdb_path.c_str()); os::Printer::log("add cdb fail ", cdb_path.c_str());
...@@ -190,10 +194,10 @@ bool Game::Initialize() { ...@@ -190,10 +194,10 @@ bool Game::Initialize() {
return false; return false;
env = device->getGUIEnvironment(); env = device->getGUIEnvironment();
bool isAntialias = options->isFontAntiAliasEnabled(); bool isAntialias = options->isFontAntiAliasEnabled();
numFont = irr::gui::CGUITTFont::createTTFont(driver, fs, gameConf.numfont, (int)16 * yScale, isAntialias, false); numFont = irr::gui::CGUITTFont::createTTFont(driver, dataManager.FileSystem, gameConf.numfont, (int)16 * yScale, isAntialias, false);
adFont = irr::gui::CGUITTFont::createTTFont(driver, fs, gameConf.numfont, (int)12 * yScale, isAntialias, false); adFont = irr::gui::CGUITTFont::createTTFont(driver, dataManager.FileSystem, gameConf.numfont, (int)12 * yScale, isAntialias, false);
lpcFont = irr::gui::CGUITTFont::createTTFont(driver, fs, gameConf.numfont, (int)48 * yScale, isAntialias, true); lpcFont = irr::gui::CGUITTFont::createTTFont(driver, dataManager.FileSystem, gameConf.numfont, (int)48 * yScale, isAntialias, true);
guiFont = irr::gui::CGUITTFont::createTTFont(driver, fs, gameConf.textfont, (int)gameConf.textfontsize * yScale, isAntialias, true); guiFont = irr::gui::CGUITTFont::createTTFont(driver, dataManager.FileSystem, gameConf.textfont, (int)gameConf.textfontsize * yScale, isAntialias, true);
textFont = guiFont; textFont = guiFont;
if(!numFont || !textFont) { if(!numFont || !textFont) {
os::Printer::log("add font fail "); os::Printer::log("add font fail ");
...@@ -1259,6 +1263,46 @@ void Game::SetStaticText(irr::gui::IGUIStaticText* pControl, u32 cWidth, irr::gu ...@@ -1259,6 +1263,46 @@ void Game::SetStaticText(irr::gui::IGUIStaticText* pControl, u32 cWidth, irr::gu
dataManager.strBuffer[pbuffer] = 0; dataManager.strBuffer[pbuffer] = 0;
pControl->setText(dataManager.strBuffer); pControl->setText(dataManager.strBuffer);
} }
void Game::LoadExpansions() {
// TODO: get isUseExtraCards
#ifdef _IRR_ANDROID_PLATFORM_
DIR * dir;
struct dirent * dirp;
if((dir = opendir("./expansions/")) == NULL)
return;
while((dirp = readdir(dir)) != NULL) {
size_t len = strlen(dirp->d_name);
if(len < 5 || strcasecmp(dirp->d_name + len - 4, ".zip") != 0)
continue;
char upath[1024];
sprintf(upath, "./expansions/%s", dirp->d_name);
dataManager.FileSystem->addFileArchive(upath, true, false);
}
closedir(dir);
#endif
for(u32 i = 0; i < DataManager::FileSystem->getFileArchiveCount(); ++i) {
const IFileList* archive = DataManager::FileSystem->getFileArchive(i)->getFileList();
for(u32 j = 0; j < archive->getFileCount(); ++j) {
#ifdef _WIN32
const wchar_t* fname = archive->getFullFileName(j).c_str();
#else
wchar_t fname[1024];
const char* uname = archive->getFullFileName(j).c_str();
BufferIO::DecodeUTF8(uname, fname);
#endif
if(wcsrchr(fname, '.') && !wcsncasecmp(wcsrchr(fname, '.'), L".cdb", 4))
dataManager.LoadDB(fname);
if(wcsrchr(fname, '.') && !wcsncasecmp(wcsrchr(fname, '.'), L".conf", 5)) {
#ifdef _WIN32
IReadFile* reader = DataManager::FileSystem->createAndOpenFile(fname);
#else
IReadFile* reader = DataManager::FileSystem->createAndOpenFile(uname);
#endif
dataManager.LoadStrings(reader);
}
}
}
}
void Game::RefreshDeck(irr::gui::IGUIComboBox* cbDeck) { void Game::RefreshDeck(irr::gui::IGUIComboBox* cbDeck) {
cbDeck->clear(); cbDeck->clear();
#ifdef _WIN32 #ifdef _WIN32
......
...@@ -118,7 +118,7 @@ public: ...@@ -118,7 +118,7 @@ public:
void BuildProjectionMatrix(irr::core::matrix4& mProjection, f32 left, f32 right, f32 bottom, f32 top, f32 znear, f32 zfar); void BuildProjectionMatrix(irr::core::matrix4& mProjection, f32 left, f32 right, f32 bottom, f32 top, f32 znear, f32 zfar);
void InitStaticText(irr::gui::IGUIStaticText* pControl, u32 cWidth, u32 cHeight, irr::gui::CGUITTFont* font, const wchar_t* text); void InitStaticText(irr::gui::IGUIStaticText* pControl, u32 cWidth, u32 cHeight, irr::gui::CGUITTFont* font, const wchar_t* text);
void SetStaticText(irr::gui::IGUIStaticText* pControl, u32 cWidth, irr::gui::CGUITTFont* font, const wchar_t* text, u32 pos = 0); void SetStaticText(irr::gui::IGUIStaticText* pControl, u32 cWidth, irr::gui::CGUITTFont* font, const wchar_t* text, u32 pos = 0);
void LoadExpansionDB(); void LoadExpansions();
void RefreshDeck(irr::gui::IGUIComboBox* cbDeck); void RefreshDeck(irr::gui::IGUIComboBox* cbDeck);
void RefreshReplay(); void RefreshReplay();
void RefreshSingleplay(); void RefreshSingleplay();
......
# File: Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cspmemvfs
LOCAL_SRC_FILES := spmemvfs.c
LOCAL_CFLAGS := -O2
include $(BUILD_STATIC_LIBRARY)
project "cspmemvfs"
kind "StaticLib"
files { "**.c", "**.h" }
configuration "windows"
includedirs { "../../sqlite3" }
/*
* BSD 2-Clause License
*
* Copyright 2009 Stephen Liu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "spmemvfs.h"
#include "../../sqlite3/sqlite3.h"
/* Useful macros used in several places */
#define SPMEMVFS_MIN(x,y) ((x)<(y)?(x):(y))
#define SPMEMVFS_MAX(x,y) ((x)>(y)?(x):(y))
static void spmemvfsDebug(const char *format, ...){
#if defined(SPMEMVFS_DEBUG)
char logTemp[ 1024 ] = { 0 };
va_list vaList;
va_start( vaList, format );
vsnprintf( logTemp, sizeof( logTemp ), format, vaList );
va_end ( vaList );
if( strchr( logTemp, '\n' ) ) {
printf( "%s", logTemp );
} else {
printf( "%s\n", logTemp );
}
#endif
}
//===========================================================================
typedef struct spmemfile_t {
sqlite3_file base;
char * path;
int flags;
spmembuffer_t * mem;
} spmemfile_t;
static int spmemfileClose( sqlite3_file * file );
static int spmemfileRead( sqlite3_file * file, void * buffer, int len, sqlite3_int64 offset );
static int spmemfileWrite( sqlite3_file * file, const void * buffer, int len, sqlite3_int64 offset );
static int spmemfileTruncate( sqlite3_file * file, sqlite3_int64 size );
static int spmemfileSync( sqlite3_file * file, int flags );
static int spmemfileFileSize( sqlite3_file * file, sqlite3_int64 * size );
static int spmemfileLock( sqlite3_file * file, int type );
static int spmemfileUnlock( sqlite3_file * file, int type );
static int spmemfileCheckReservedLock( sqlite3_file * file, int * result );
static int spmemfileFileControl( sqlite3_file * file, int op, void * arg );
static int spmemfileSectorSize( sqlite3_file * file );
static int spmemfileDeviceCharacteristics( sqlite3_file * file );
static sqlite3_io_methods g_spmemfile_io_memthods = {
1, /* iVersion */
spmemfileClose, /* xClose */
spmemfileRead, /* xRead */
spmemfileWrite, /* xWrite */
spmemfileTruncate, /* xTruncate */
spmemfileSync, /* xSync */
spmemfileFileSize, /* xFileSize */
spmemfileLock, /* xLock */
spmemfileUnlock, /* xUnlock */
spmemfileCheckReservedLock, /* xCheckReservedLock */
spmemfileFileControl, /* xFileControl */
spmemfileSectorSize, /* xSectorSize */
spmemfileDeviceCharacteristics /* xDeviceCharacteristics */
};
int spmemfileClose( sqlite3_file * file )
{
spmemfile_t * memfile = (spmemfile_t*)file;
spmemvfsDebug( "call %s( %p )", __func__, memfile );
if( SQLITE_OPEN_MAIN_DB & memfile->flags ) {
// noop
} else {
if( NULL != memfile->mem ) {
if( memfile->mem->data ) free( memfile->mem->data );
free( memfile->mem );
}
}
free( memfile->path );
return SQLITE_OK;
}
int spmemfileRead( sqlite3_file * file, void * buffer, int len, sqlite3_int64 offset )
{
spmemfile_t * memfile = (spmemfile_t*)file;
spmemvfsDebug( "call %s( %p, ..., %d, %lld ), len %d",
__func__, memfile, len, offset, memfile->mem->used );
if( ( offset + len ) > memfile->mem->used ) {
return SQLITE_IOERR_SHORT_READ;
}
memcpy( buffer, memfile->mem->data + offset, len );
return SQLITE_OK;
}
int spmemfileWrite( sqlite3_file * file, const void * buffer, int len, sqlite3_int64 offset )
{
spmemfile_t * memfile = (spmemfile_t*)file;
spmembuffer_t * mem = memfile->mem;
spmemvfsDebug( "call %s( %p, ..., %d, %lld ), len %d",
__func__, memfile, len, offset, mem->used );
if( ( offset + len ) > mem->total ) {
int newTotal = 2 * ( offset + len + mem->total );
char * newBuffer = (char*)realloc( mem->data, newTotal );
if( NULL == newBuffer ) {
return SQLITE_NOMEM;
}
mem->total = newTotal;
mem->data = newBuffer;
}
memcpy( mem->data + offset, buffer, len );
mem->used = SPMEMVFS_MAX( mem->used, offset + len );
return SQLITE_OK;
}
int spmemfileTruncate( sqlite3_file * file, sqlite3_int64 size )
{
spmemfile_t * memfile = (spmemfile_t*)file;
spmemvfsDebug( "call %s( %p )", __func__, memfile );
memfile->mem->used = SPMEMVFS_MIN( memfile->mem->used, size );
return SQLITE_OK;
}
int spmemfileSync( sqlite3_file * file, int flags )
{
spmemvfsDebug( "call %s( %p )", __func__, file );
return SQLITE_OK;
}
int spmemfileFileSize( sqlite3_file * file, sqlite3_int64 * size )
{
spmemfile_t * memfile = (spmemfile_t*)file;
spmemvfsDebug( "call %s( %p )", __func__, memfile );
* size = memfile->mem->used;
return SQLITE_OK;
}
int spmemfileLock( sqlite3_file * file, int type )
{
spmemvfsDebug( "call %s( %p )", __func__, file );
return SQLITE_OK;
}
int spmemfileUnlock( sqlite3_file * file, int type )
{
spmemvfsDebug( "call %s( %p )", __func__, file );
return SQLITE_OK;
}
int spmemfileCheckReservedLock( sqlite3_file * file, int * result )
{
spmemvfsDebug( "call %s( %p )", __func__, file );
*result = 0;
return SQLITE_OK;
}
int spmemfileFileControl( sqlite3_file * file, int op, void * arg )
{
spmemvfsDebug( "call %s( %p )", __func__, file );
return SQLITE_OK;
}
int spmemfileSectorSize( sqlite3_file * file )
{
spmemvfsDebug( "call %s( %p )", __func__, file );
return 0;
}
int spmemfileDeviceCharacteristics( sqlite3_file * file )
{
spmemvfsDebug( "call %s( %p )", __func__, file );
return 0;
}
//===========================================================================
typedef struct spmemvfs_cb_t {
void * arg;
spmembuffer_t * ( * load ) ( void * args, const char * path );
} spmemvfs_cb_t;
typedef struct spmemvfs_t {
sqlite3_vfs base;
spmemvfs_cb_t cb;
sqlite3_vfs * parent;
} spmemvfs_t;
static int spmemvfsOpen( sqlite3_vfs * vfs, const char * path, sqlite3_file * file, int flags, int * outflags );
static int spmemvfsDelete( sqlite3_vfs * vfs, const char * path, int syncDir );
static int spmemvfsAccess( sqlite3_vfs * vfs, const char * path, int flags, int * result );
static int spmemvfsFullPathname( sqlite3_vfs * vfs, const char * path, int len, char * fullpath );
static void * spmemvfsDlOpen( sqlite3_vfs * vfs, const char * path );
static void spmemvfsDlError( sqlite3_vfs * vfs, int len, char * errmsg );
static void ( * spmemvfsDlSym ( sqlite3_vfs * vfs, void * handle, const char * symbol ) ) ( void );
static void spmemvfsDlClose( sqlite3_vfs * vfs, void * handle );
static int spmemvfsRandomness( sqlite3_vfs * vfs, int len, char * buffer );
static int spmemvfsSleep( sqlite3_vfs * vfs, int microseconds );
static int spmemvfsCurrentTime( sqlite3_vfs * vfs, double * result );
static spmemvfs_t g_spmemvfs = {
{
1, /* iVersion */
0, /* szOsFile */
0, /* mxPathname */
0, /* pNext */
SPMEMVFS_NAME, /* zName */
0, /* pAppData */
spmemvfsOpen, /* xOpen */
spmemvfsDelete, /* xDelete */
spmemvfsAccess, /* xAccess */
spmemvfsFullPathname, /* xFullPathname */
spmemvfsDlOpen, /* xDlOpen */
spmemvfsDlError, /* xDlError */
spmemvfsDlSym, /* xDlSym */
spmemvfsDlClose, /* xDlClose */
spmemvfsRandomness, /* xRandomness */
spmemvfsSleep, /* xSleep */
spmemvfsCurrentTime /* xCurrentTime */
},
{ 0 },
0 /* pParent */
};
int spmemvfsOpen( sqlite3_vfs * vfs, const char * path, sqlite3_file * file, int flags, int * outflags )
{
spmemvfs_t * memvfs = (spmemvfs_t*)vfs;
spmemfile_t * memfile = (spmemfile_t*)file;
spmemvfsDebug( "call %s( %p(%p), %s, %p, %x, %p )\n",
__func__, vfs, &g_spmemvfs, path, file, flags, outflags );
memset( memfile, 0, sizeof( spmemfile_t ) );
memfile->base.pMethods = &g_spmemfile_io_memthods;
memfile->flags = flags;
memfile->path = strdup( path );
if( SQLITE_OPEN_MAIN_DB & memfile->flags ) {
memfile->mem = memvfs->cb.load( memvfs->cb.arg, path );
} else {
memfile->mem = (spmembuffer_t*)calloc( sizeof( spmembuffer_t ), 1 );
}
return memfile->mem ? SQLITE_OK : SQLITE_ERROR;
}
int spmemvfsDelete( sqlite3_vfs * vfs, const char * path, int syncDir )
{
spmemvfsDebug( "call %s( %p(%p), %s, %d )\n",
__func__, vfs, &g_spmemvfs, path, syncDir );
return SQLITE_OK;
}
int spmemvfsAccess( sqlite3_vfs * vfs, const char * path, int flags, int * result )
{
* result = 0;
return SQLITE_OK;
}
int spmemvfsFullPathname( sqlite3_vfs * vfs, const char * path, int len, char * fullpath )
{
strncpy( fullpath, path, len );
fullpath[ len - 1 ] = '\0';
return SQLITE_OK;
}
void * spmemvfsDlOpen( sqlite3_vfs * vfs, const char * path )
{
return NULL;
}
void spmemvfsDlError( sqlite3_vfs * vfs, int len, char * errmsg )
{
// noop
}
void ( * spmemvfsDlSym ( sqlite3_vfs * vfs, void * handle, const char * symbol ) ) ( void )
{
return NULL;
}
void spmemvfsDlClose( sqlite3_vfs * vfs, void * handle )
{
// noop
}
int spmemvfsRandomness( sqlite3_vfs * vfs, int len, char * buffer )
{
return SQLITE_OK;
}
int spmemvfsSleep( sqlite3_vfs * vfs, int microseconds )
{
return SQLITE_OK;
}
int spmemvfsCurrentTime( sqlite3_vfs * vfs, double * result )
{
return SQLITE_OK;
}
//===========================================================================
int spmemvfs_init( spmemvfs_cb_t * cb )
{
sqlite3_vfs * parent = NULL;
if( g_spmemvfs.parent ) return SQLITE_OK;
parent = sqlite3_vfs_find( 0 );
g_spmemvfs.parent = parent;
g_spmemvfs.base.mxPathname = parent->mxPathname;
g_spmemvfs.base.szOsFile = sizeof( spmemfile_t );
g_spmemvfs.cb = * cb;
return sqlite3_vfs_register( (sqlite3_vfs*)&g_spmemvfs, 0 );
}
//===========================================================================
typedef struct spmembuffer_link_t {
char * path;
spmembuffer_t * mem;
struct spmembuffer_link_t * next;
} spmembuffer_link_t;
spmembuffer_link_t * spmembuffer_link_remove( spmembuffer_link_t ** head, const char * path )
{
spmembuffer_link_t * ret = NULL;
spmembuffer_link_t ** iter = head;
for( ; NULL != *iter; ) {
spmembuffer_link_t * curr = *iter;
if( 0 == strcmp( path, curr->path ) ) {
ret = curr;
*iter = curr->next;
break;
} else {
iter = &( curr->next );
}
}
return ret;
}
void spmembuffer_link_free( spmembuffer_link_t * iter )
{
free( iter->path );
free( iter->mem->data );
free( iter->mem );
free( iter );
}
//===========================================================================
typedef struct spmemvfs_env_t {
spmembuffer_link_t * head;
sqlite3_mutex * mutex;
} spmemvfs_env_t;
static spmemvfs_env_t * g_spmemvfs_env = NULL;
static spmembuffer_t * load_cb( void * arg, const char * path )
{
spmembuffer_t * ret = NULL;
spmemvfs_env_t * env = (spmemvfs_env_t*)arg;
sqlite3_mutex_enter( env->mutex );
{
spmembuffer_link_t * toFind = spmembuffer_link_remove( &( env->head ), path );
if( NULL != toFind ) {
ret = toFind->mem;
free( toFind->path );
free( toFind );
}
}
sqlite3_mutex_leave( env->mutex );
return ret;
}
int spmemvfs_env_init()
{
int ret = 0;
if( NULL == g_spmemvfs_env ) {
spmemvfs_cb_t cb;
g_spmemvfs_env = (spmemvfs_env_t*)calloc( sizeof( spmemvfs_env_t ), 1 );
g_spmemvfs_env->mutex = sqlite3_mutex_alloc( SQLITE_MUTEX_FAST );
cb.arg = g_spmemvfs_env;
cb.load = load_cb;
ret = spmemvfs_init( &cb );
}
return ret;
}
void spmemvfs_env_fini()
{
if( NULL != g_spmemvfs_env ) {
spmembuffer_link_t * iter = NULL;
sqlite3_vfs_unregister( (sqlite3_vfs*)&g_spmemvfs );
g_spmemvfs.parent = NULL;
sqlite3_mutex_free( g_spmemvfs_env->mutex );
iter = g_spmemvfs_env->head;
for( ; NULL != iter; ) {
spmembuffer_link_t * next = iter->next;
spmembuffer_link_free( iter );
iter = next;
}
free( g_spmemvfs_env );
g_spmemvfs_env = NULL;
}
}
int spmemvfs_open_db( spmemvfs_db_t * db, const char * path, spmembuffer_t * mem )
{
int ret = 0;
spmembuffer_link_t * iter = NULL;
memset( db, 0, sizeof( spmemvfs_db_t ) );
iter = (spmembuffer_link_t*)calloc( sizeof( spmembuffer_link_t ), 1 );
iter->path = strdup( path );
iter->mem = mem;
sqlite3_mutex_enter( g_spmemvfs_env->mutex );
{
iter->next = g_spmemvfs_env->head;
g_spmemvfs_env->head = iter;
}
sqlite3_mutex_leave( g_spmemvfs_env->mutex );
ret = sqlite3_open_v2( path, &(db->handle),
SQLITE_OPEN_READONLY, SPMEMVFS_NAME);
//SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, SPMEMVFS_NAME );
if( 0 == ret ) {
db->mem = mem;
} else {
sqlite3_mutex_enter( g_spmemvfs_env->mutex );
{
iter = spmembuffer_link_remove( &(g_spmemvfs_env->head), path );
if( NULL != iter ) spmembuffer_link_free( iter );
}
sqlite3_mutex_leave( g_spmemvfs_env->mutex );
}
return ret;
}
int spmemvfs_close_db( spmemvfs_db_t * db )
{
int ret = 0;
if( NULL == db ) return 0;
if( NULL != db->handle ) {
ret = sqlite3_close( db->handle );
db->handle = NULL;
}
if( NULL != db->mem ) {
if( NULL != db->mem->data ) free( db->mem->data );
free( db->mem );
db->mem = NULL;
}
return ret;
}
/*
* BSD 2-Clause License
*
* Copyright 2009 Stephen Liu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __spmemvfs_h__
#define __spmemvfs_h__
#ifdef __cplusplus
extern "C" {
#endif
#include "../../sqlite3/sqlite3.h"
#define SPMEMVFS_NAME "spmemvfs"
typedef struct spmembuffer_t {
char * data;
int used;
int total;
} spmembuffer_t;
typedef struct spmemvfs_db_t {
sqlite3 * handle;
spmembuffer_t * mem;
} spmemvfs_db_t;
int spmemvfs_env_init();
void spmemvfs_env_fini();
int spmemvfs_open_db( spmemvfs_db_t * db, const char * path, spmembuffer_t * mem );
int spmemvfs_close_db( spmemvfs_db_t * db );
#ifdef __cplusplus
}
#endif
#endif
...@@ -85,6 +85,7 @@ LOCAL_STATIC_LIBRARIES += libevent2 ...@@ -85,6 +85,7 @@ LOCAL_STATIC_LIBRARIES += libevent2
LOCAL_STATIC_LIBRARIES += libocgcore_static LOCAL_STATIC_LIBRARIES += libocgcore_static
LOCAL_STATIC_LIBRARIES += liblua5.3 LOCAL_STATIC_LIBRARIES += liblua5.3
LOCAL_STATIC_LIBRARIES += clzma LOCAL_STATIC_LIBRARIES += clzma
LOCAL_STATIC_LIBRARIES += cspmemvfs
LOCAL_STATIC_LIBRARIES += sqlite3 LOCAL_STATIC_LIBRARIES += sqlite3
LOCAL_STATIC_LIBRARIES += libft2 LOCAL_STATIC_LIBRARIES += libft2
...@@ -100,6 +101,7 @@ $(call import-module,ocgcore) ...@@ -100,6 +101,7 @@ $(call import-module,ocgcore)
$(call import-module,lua) $(call import-module,lua)
$(call import-module,freetype) $(call import-module,freetype)
$(call import-module,gframe/lzma) $(call import-module,gframe/lzma)
$(call import-module,gframe/spmemvfs)
$(call import-module,android/native_app_glue) $(call import-module,android/native_app_glue)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment