librw/src/rwplugin.h

220 lines
5.4 KiB
C
Raw Normal View History

namespace rw {
2014-12-18 16:26:57 +00:00
#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);
2015-01-10 21:13:27 +00:00
typedef void (*RightsCallback)(void *object, int32 offset, int32 size, uint32 data);
2014-12-18 16:26:57 +00:00
struct Plugin
{
int32 offset;
int32 size;
uint32 id;
2014-12-18 16:26:57 +00:00
Constructor constructor;
Destructor destructor;
CopyConstructor copy;
StreamRead read;
StreamWrite write;
StreamGetSize getSize;
2015-01-10 21:13:27 +00:00
RightsCallback rightsCallback;
2014-12-18 16:26:57 +00:00
Plugin *next;
};
template <typename T>
struct PluginBase
{
static int32 s_defaultSize;
static int32 s_size;
2014-12-18 16:26:57 +00:00
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);
2015-01-10 21:13:27 +00:00
void assertRights(uint32 pluginID, uint32 data);
2014-12-18 16:26:57 +00:00
static int registerPlugin(int32 size, uint32 id,
2014-12-18 16:26:57 +00:00
Constructor, Destructor, CopyConstructor);
static int registerPluginStream(uint32 id,
2014-12-18 16:26:57 +00:00
StreamRead, StreamWrite, StreamGetSize);
static int setStreamRightsCallback(uint32 id, RightsCallback cb);
static int getPluginOffset(uint32 id);
2014-12-18 16:26:57 +00:00
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;
ChunkHeaderInfo header;
if(!findChunk(stream, ID_EXTENSION, (uint32*)&length, NULL))
2014-12-18 16:26:57 +00:00
return;
while(length > 0){
readChunkHeaderInfo(stream, &header);
2014-12-18 16:26:57 +00:00
length -= 12;
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->id == header.type && p->read){
2014-12-18 16:26:57 +00:00
p->read(stream, header.length,
(void*)this, p->offset, p->size);
goto cont;
}
2015-12-21 19:11:55 +00:00
//printf("skipping plugin %X\n", header.type);
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();
writeChunkHeader(stream, ID_EXTENSION, size);
2014-12-18 16:26:57 +00:00
for(Plugin *p = this->s_plugins; p; p = p->next){
2015-01-09 19:17:32 +00:00
if(p->getSize == NULL ||
(size = p->getSize(this, p->offset, p->size)) <= 0)
2014-12-18 16:26:57 +00:00
continue;
writeChunkHeader(stream, p->id, size);
2014-12-18 16:26:57 +00:00
p->write(stream, size, this, p->offset, p->size);
}
}
template <typename T> int32
2014-12-18 16:26:57 +00:00
PluginBase<T>::streamGetPluginSize(void)
{
int32 size = 0;
int32 plgsize;
2014-12-18 16:26:57 +00:00
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->getSize &&
(plgsize = p->getSize(this, p->offset, p->size)) > 0)
2014-12-18 16:26:57 +00:00
size += 12 + plgsize;
return size;
}
2015-01-10 21:13:27 +00:00
template <typename T> void
PluginBase<T>::assertRights(uint32 pluginID, uint32 data)
{
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->id == pluginID){
if(p->rightsCallback)
p->rightsCallback(this,
p->offset, p->size, data);
return;
}
}
template <typename T> int32
PluginBase<T>::registerPlugin(int32 size, uint32 id,
2014-12-18 16:26:57 +00:00
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;
2015-01-10 21:13:27 +00:00
p->rightsCallback = NULL;
2014-12-18 16:26:57 +00:00
Plugin **next;
for(next = &s_plugins; *next; next = &(*next)->next)
;
*next = p;
p->next = NULL;
2014-12-18 16:26:57 +00:00
return p->offset;
}
template <typename T> int32
PluginBase<T>::registerPluginStream(uint32 id,
2014-12-18 16:26:57 +00:00
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> int32
PluginBase<T>::setStreamRightsCallback(uint32 id, RightsCallback cb)
2015-01-10 21:13:27 +00:00
{
for(Plugin *p = PluginBase<T>::s_plugins; p; p = p->next)
if(p->id == id){
p->rightsCallback = cb;
return p->offset;
}
return -1;
}
template <typename T> int32
PluginBase<T>::getPluginOffset(uint32 id)
2014-12-18 16:26:57 +00:00
{
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);
}
}