161 lines
3.8 KiB
C++
161 lines
3.8 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "filesystem/data_store.h"
|
|
#include "rand/rand.h"
|
|
#include "memory/nauto_ptr.h"
|
|
|
|
using namespace GS;
|
|
using namespace GS::IO;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
DataStore::Entry *DataStore::GetEntry(const String &id) const
|
|
{
|
|
ListForeachPtr(Entry *, e, entries)
|
|
if (e->id == id)
|
|
return e;
|
|
return NULL;
|
|
}
|
|
String DataStore::GetNewId()
|
|
{
|
|
for ( ; ; ++id_seed)
|
|
{
|
|
String id = String::Format("store_%012d", id_seed);
|
|
if (GetEntry(id) == NULL)
|
|
return id;
|
|
}
|
|
return String();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
size_t DataStore::GetEntrySize(const String &id) const
|
|
{
|
|
if (Entry *e = GetEntry(id))
|
|
return e->size;
|
|
return 0;
|
|
}
|
|
size_t DataStore::GetStoreSize() const
|
|
{
|
|
size_t size = 0;
|
|
ListForeachPtr(Entry *, e, entries)
|
|
size += e->size;
|
|
return size;
|
|
}
|
|
size_t DataStore::GetFreeStore() const
|
|
{ return limit - GetStoreSize(); }
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
String DataStore::Reserve(size_t size)
|
|
{
|
|
Threading::MutexLock lock(&mutex);
|
|
|
|
if (limit > 0) // enforce size limit
|
|
{
|
|
size_t store_size = GetStoreSize();
|
|
if (size > (limit - store_size))
|
|
return String(); // store is full
|
|
}
|
|
|
|
// Reserve a new entry.
|
|
Entry *entry = new Entry;
|
|
|
|
entry->id = GetNewId();
|
|
entry->size = size;
|
|
entries.Add(entry);
|
|
|
|
return entry->id;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool DataStore::Store(const String &id, const void *data, size_t size, const char *user)
|
|
{
|
|
Threading::MutexLock lock(&mutex);
|
|
|
|
Entry *entry = GetEntry(id);
|
|
if ((entry == NULL) || (entry->size != size))
|
|
return false; // invalid id/store size
|
|
|
|
lock.Unlock();
|
|
|
|
entry->user = user;
|
|
|
|
AutoPtr <Handle> h(io->Open(id, ModeWrite));
|
|
return h.IsValid() && (h->Write(data, size) == size);
|
|
}
|
|
bool DataStore::Free(const String &id)
|
|
{
|
|
Threading::MutexLock lock(&mutex);
|
|
|
|
Entry *entry = GetEntry(id);
|
|
if (entry == NULL)
|
|
return false; // invalid id
|
|
|
|
if (!io->Delete(id))
|
|
return false;
|
|
|
|
return entries.Remove(entry);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Store format
|
|
//
|
|
// 18 bytes - id
|
|
// 4 bytes - size in bytes
|
|
// -----------------------------
|
|
bool DataStore::Load(const char *path)
|
|
{
|
|
AutoPtr <Handle> h(io->Open(path));
|
|
if (h.IsNull())
|
|
return true; // nothing to restore
|
|
|
|
entries.Clear();
|
|
|
|
char id[18];
|
|
while (!h->IsEOF())
|
|
{
|
|
if (h->Read((void *)id, 18) != 18)
|
|
return false;
|
|
|
|
Entry *e = new Entry;
|
|
|
|
e->id.Set(id, id + 18);
|
|
e->size = h->Read <size_t> ();
|
|
|
|
uint user_data_size = h->Read <uint> ();
|
|
if (!e->user.Allocate(user_data_size))
|
|
return false;
|
|
|
|
h->Read((void *)e->user.c_str(), user_data_size);
|
|
|
|
entries.Add(e);
|
|
}
|
|
return true;
|
|
}
|
|
bool DataStore::Save(const char *path)
|
|
{
|
|
AutoPtr <Handle> h(io->Open(path, ModeWrite));
|
|
if (h.IsNull())
|
|
return false;
|
|
|
|
ListForeachPtr(Entry *, e, entries)
|
|
{
|
|
h->Write(e->id.c_str(), 18);
|
|
h->Write(&e->size, 4);
|
|
|
|
uint user_data_size = e->user.Len();
|
|
h->Write(user_data_size);
|
|
if (user_data_size > 0)
|
|
h->Write(e->user.c_str(), user_data_size);
|
|
}
|
|
return true;
|
|
}
|
|
//------------------------------------------------------------------------------
|