2015-01-25 21:27:03 +00:00
|
|
|
namespace rw {
|
2014-12-18 16:26:57 +00:00
|
|
|
|
|
|
|
#define PLUGINOFFSET(type, base, offset) \
|
|
|
|
((type*)((char*)(base) + (offset)))
|
|
|
|
|
2014-12-19 15:24:29 +00:00
|
|
|
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);
|
2016-06-17 15:20:02 +01:00
|
|
|
typedef Stream *(*StreamRead)(Stream *stream, int32 length, void *object, int32 offset, int32 size);
|
|
|
|
typedef Stream *(*StreamWrite)(Stream *stream, int32 length, void *object, int32 offset, int32 size);
|
2014-12-19 15:24:29 +00:00
|
|
|
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
|
|
|
|
{
|
2015-09-06 12:31:42 +01:00
|
|
|
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
|
|
|
|
{
|
2015-09-06 12:31:42 +01:00
|
|
|
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);
|
2016-06-17 12:29:49 +01:00
|
|
|
bool streamReadPlugins(Stream *stream);
|
2014-12-27 22:18:10 +00:00
|
|
|
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
|
|
|
|
2015-09-06 12:31:42 +01:00
|
|
|
static int registerPlugin(int32 size, uint32 id,
|
2014-12-18 16:26:57 +00:00
|
|
|
Constructor, Destructor, CopyConstructor);
|
2015-09-06 12:31:42 +01:00
|
|
|
static int registerPluginStream(uint32 id,
|
2014-12-18 16:26:57 +00:00
|
|
|
StreamRead, StreamWrite, StreamGetSize);
|
2015-09-06 12:31:42 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-06-17 12:29:49 +01:00
|
|
|
template <typename T> bool
|
2014-12-27 22:18:10 +00:00
|
|
|
PluginBase<T>::streamReadPlugins(Stream *stream)
|
2014-12-18 16:26:57 +00:00
|
|
|
{
|
2014-12-24 22:52:03 +00:00
|
|
|
int32 length;
|
2015-01-25 21:27:03 +00:00
|
|
|
ChunkHeaderInfo header;
|
2016-06-21 22:16:09 +01:00
|
|
|
if(!findChunk(stream, ID_EXTENSION, (uint32*)&length, nil))
|
2016-06-17 12:29:49 +01:00
|
|
|
return false;
|
2014-12-24 22:52:03 +00:00
|
|
|
while(length > 0){
|
2016-06-17 12:29:49 +01:00
|
|
|
if(!readChunkHeaderInfo(stream, &header))
|
|
|
|
return false;
|
2014-12-18 16:26:57 +00:00
|
|
|
length -= 12;
|
|
|
|
for(Plugin *p = this->s_plugins; p; p = p->next)
|
2015-09-09 22:26:16 +01:00
|
|
|
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);
|
2014-12-27 22:18:10 +00:00
|
|
|
stream->seek(header.length);
|
2014-12-18 16:26:57 +00:00
|
|
|
cont:
|
|
|
|
length -= header.length;
|
|
|
|
}
|
2016-06-17 12:29:49 +01:00
|
|
|
return true;
|
2014-12-18 16:26:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T> void
|
2014-12-27 22:18:10 +00:00
|
|
|
PluginBase<T>::streamWritePlugins(Stream *stream)
|
2014-12-18 16:26:57 +00:00
|
|
|
{
|
|
|
|
int size = this->streamGetPluginSize();
|
2015-01-25 21:27:03 +00:00
|
|
|
writeChunkHeader(stream, ID_EXTENSION, size);
|
2014-12-18 16:26:57 +00:00
|
|
|
for(Plugin *p = this->s_plugins; p; p = p->next){
|
2016-06-21 22:16:09 +01:00
|
|
|
if(p->getSize == nil ||
|
2015-09-09 22:26:16 +01:00
|
|
|
(size = p->getSize(this, p->offset, p->size)) <= 0)
|
2014-12-18 16:26:57 +00:00
|
|
|
continue;
|
2015-01-25 21:27:03 +00:00
|
|
|
writeChunkHeader(stream, p->id, size);
|
2014-12-18 16:26:57 +00:00
|
|
|
p->write(stream, size, this, p->offset, p->size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-06 12:31:42 +01:00
|
|
|
template <typename T> int32
|
2014-12-18 16:26:57 +00:00
|
|
|
PluginBase<T>::streamGetPluginSize(void)
|
|
|
|
{
|
2015-09-06 12:31:42 +01:00
|
|
|
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 &&
|
2015-09-09 22:26:16 +01:00
|
|
|
(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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-06 12:31:42 +01:00
|
|
|
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;
|
2016-06-21 22:16:09 +01:00
|
|
|
p->read = nil;
|
|
|
|
p->write = nil;
|
|
|
|
p->getSize = nil;
|
|
|
|
p->rightsCallback = nil;
|
2014-12-18 16:26:57 +00:00
|
|
|
|
2015-09-09 22:26:16 +01:00
|
|
|
Plugin **next;
|
|
|
|
for(next = &s_plugins; *next; next = &(*next)->next)
|
|
|
|
;
|
|
|
|
*next = p;
|
2016-06-21 22:16:09 +01:00
|
|
|
p->next = nil;
|
2014-12-18 16:26:57 +00:00
|
|
|
return p->offset;
|
|
|
|
}
|
|
|
|
|
2015-09-06 12:31:42 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-09-06 12:31:42 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-09-06 12:31:42 +01:00
|
|
|
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)
|
|
|
|
{
|
2016-06-16 23:06:37 +01:00
|
|
|
abort();
|
2016-06-21 22:16:09 +01:00
|
|
|
return nil;
|
2014-12-18 16:26:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T> void
|
|
|
|
PluginBase<T>::operator delete(void *p)
|
|
|
|
{
|
2016-06-16 23:06:37 +01:00
|
|
|
abort();
|
2014-12-18 16:26:57 +00:00
|
|
|
}
|
|
|
|
}
|