librw/src/rwplugin.h

187 lines
4.4 KiB
C
Raw Normal View History

2014-12-18 16:26:57 +00:00
namespace Rw {
#define PLUGINOFFSET(type, base, offset) \
((type*)((char*)(base) + (offset)))
typedef void *(*Constructor)(void *object, int32 offset, int32 size);
typedef void *(*Destructor)(void *object, int32 offset, int32 size);
typedef void *(*CopyConstructor)(void *dst, void *src, int32 offset, int32 size);
typedef void (*StreamRead)(Stream *stream, int32 length, void *object, int32 offset, int32 size);
typedef void (*StreamWrite)(Stream *stream, int32 length, void *object, int32 offset, int32 size);
typedef int32 (*StreamGetSize)(void *object, int32 offset, int32 size);
2014-12-18 16:26:57 +00:00
struct Plugin
{
int offset;
int size;
uint id;
Constructor constructor;
Destructor destructor;
CopyConstructor copy;
StreamRead read;
StreamWrite write;
StreamGetSize getSize;
Plugin *next;
};
template <typename T>
struct PluginBase
{
static int s_defaultSize;
static int s_size;
static Plugin *s_plugins;
void constructPlugins(void);
void destructPlugins(void);
void copyPlugins(T *t);
void streamReadPlugins(Stream *stream);
void streamWritePlugins(Stream *stream);
2014-12-18 16:26:57 +00:00
int streamGetPluginSize(void);
static int registerPlugin(int size, uint id,
Constructor, Destructor, CopyConstructor);
static int registerPluginStream(uint id,
StreamRead, StreamWrite, StreamGetSize);
static int getPluginOffset(uint id);
static void *operator new(size_t size);
static void operator delete(void *p);
};
template <typename T>
int PluginBase<T>::s_defaultSize = sizeof(T);
template <typename T>
int PluginBase<T>::s_size = sizeof(T);
template <typename T>
Plugin *PluginBase<T>::s_plugins = 0;
template <typename T> void
PluginBase<T>::constructPlugins(void)
{
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->constructor)
p->constructor((void*)this, p->offset, p->size);
}
template <typename T> void
PluginBase<T>::destructPlugins(void)
{
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->destructor)
p->destructor((void*)this, p->offset, p->size);
}
template <typename T> void
PluginBase<T>::copyPlugins(T *t)
{
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->copy)
p->copy((void*)this, (void*)t, p->offset, p->size);
}
template <typename T> void
PluginBase<T>::streamReadPlugins(Stream *stream)
2014-12-18 16:26:57 +00:00
{
int32 length;
2014-12-18 16:26:57 +00:00
Rw::ChunkHeaderInfo header;
if(!Rw::FindChunk(stream, Rw::ID_EXTENSION, (uint32*)&length, NULL))
2014-12-18 16:26:57 +00:00
return;
while(length > 0){
2014-12-18 16:26:57 +00:00
Rw::ReadChunkHeaderInfo(stream, &header);
length -= 12;
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->id == header.type){
p->read(stream, header.length,
(void*)this, p->offset, p->size);
goto cont;
}
stream->seek(header.length);
2014-12-18 16:26:57 +00:00
cont:
length -= header.length;
}
}
template <typename T> void
PluginBase<T>::streamWritePlugins(Stream *stream)
2014-12-18 16:26:57 +00:00
{
int size = this->streamGetPluginSize();
Rw::WriteChunkHeader(stream, Rw::ID_EXTENSION, size);
for(Plugin *p = this->s_plugins; p; p = p->next){
if((size = p->getSize(this, p->offset, p->size)) < 0)
continue;
Rw::WriteChunkHeader(stream, p->id, size);
p->write(stream, size, this, p->offset, p->size);
}
}
template <typename T> int
PluginBase<T>::streamGetPluginSize(void)
{
int size = 0;
int plgsize;
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->getSize &&
(plgsize = p->getSize(this, p->offset, p->size)) >= 0)
size += 12 + plgsize;
return size;
}
template <typename T> int
PluginBase<T>::registerPlugin(int size, uint id,
Constructor ctor, Destructor dtor, CopyConstructor cctor)
{
Plugin *p = new Plugin;
p->offset = s_size;
s_size += size;
p->size = size;
p->id = id;
p->constructor = ctor;
p->copy = cctor;
p->destructor = dtor;
p->read = NULL;
p->write = NULL;
p->getSize = NULL;
p->next = s_plugins;
s_plugins = p;
return p->offset;
}
template <typename T> int
PluginBase<T>::registerPluginStream(uint id,
StreamRead read, StreamWrite write, StreamGetSize getSize)
{
for(Plugin *p = PluginBase<T>::s_plugins; p; p = p->next)
if(p->id == id){
p->read = read;
p->write = write;
p->getSize = getSize;
return p->offset;
}
return -1;
}
template <typename T> int
PluginBase<T>::getPluginOffset(uint id)
{
for(Plugin *p = PluginBase<T>::s_plugins; p; p = p->next)
if(p->id == id)
return p->offset;
return -1;
}
template <typename T> void*
PluginBase<T>::operator new(size_t)
{
void *m = malloc(T::s_size);
if(!m)
throw std::bad_alloc();
return m;
}
template <typename T> void
PluginBase<T>::operator delete(void *p)
{
free(p);
}
}