2016-06-25 17:58:52 +02:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cmath>
|
|
|
|
#include <cctype>
|
|
|
|
|
|
|
|
#include "rwbase.h"
|
|
|
|
#include "rwerror.h"
|
|
|
|
#include "rwplg.h"
|
2017-08-24 15:10:34 +02:00
|
|
|
#include "rwpipeline.h"
|
|
|
|
#include "rwobjects.h"
|
|
|
|
#include "rwengine.h"
|
2016-06-25 17:58:52 +02:00
|
|
|
|
|
|
|
namespace rw {
|
|
|
|
|
|
|
|
static void *defCtor(void *object, int32, int32) { return object; }
|
|
|
|
static void *defDtor(void *object, int32, int32) { return object; }
|
|
|
|
static void *defCopy(void *dst, void*, int32, int32) { return dst; }
|
|
|
|
|
2020-04-25 00:37:49 +02:00
|
|
|
static LinkList allPlugins;
|
|
|
|
|
|
|
|
#define PLG(lnk) LLLinkGetData(lnk, Plugin, inParentList)
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginList::open(void)
|
|
|
|
{
|
|
|
|
allPlugins.init();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginList::close(void)
|
|
|
|
{
|
|
|
|
PluginList *l;
|
|
|
|
Plugin *p;
|
|
|
|
FORLIST(lnk, allPlugins){
|
|
|
|
p = LLLinkGetData(lnk, Plugin, inGlobalList);
|
|
|
|
l = p->parentList;
|
|
|
|
p->inParentList.remove();
|
|
|
|
p->inGlobalList.remove();
|
|
|
|
rwFree(p);
|
|
|
|
if(l->plugins.isEmpty())
|
|
|
|
l->size = l->defaultSize;
|
|
|
|
}
|
|
|
|
assert(allPlugins.isEmpty());
|
|
|
|
}
|
|
|
|
|
2016-06-25 17:58:52 +02:00
|
|
|
void
|
|
|
|
PluginList::construct(void *object)
|
|
|
|
{
|
2020-04-25 00:37:49 +02:00
|
|
|
FORLIST(lnk, this->plugins){
|
|
|
|
Plugin *p = PLG(lnk);
|
2016-06-25 17:58:52 +02:00
|
|
|
p->constructor(object, p->offset, p->size);
|
2020-04-25 00:37:49 +02:00
|
|
|
}
|
2016-06-25 17:58:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginList::destruct(void *object)
|
|
|
|
{
|
2020-04-25 00:37:49 +02:00
|
|
|
FORLIST(lnk, this->plugins){
|
|
|
|
Plugin *p = PLG(lnk);
|
2016-06-25 17:58:52 +02:00
|
|
|
p->destructor(object, p->offset, p->size);
|
2020-04-25 00:37:49 +02:00
|
|
|
}
|
2016-06-25 17:58:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginList::copy(void *dst, void *src)
|
|
|
|
{
|
2020-04-25 00:37:49 +02:00
|
|
|
FORLIST(lnk, this->plugins){
|
|
|
|
Plugin *p = PLG(lnk);
|
2016-06-25 17:58:52 +02:00
|
|
|
p->copy(dst, src, p->offset, p->size);
|
2020-04-25 00:37:49 +02:00
|
|
|
}
|
2016-06-25 17:58:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
PluginList::streamRead(Stream *stream, void *object)
|
|
|
|
{
|
|
|
|
int32 length;
|
|
|
|
ChunkHeaderInfo header;
|
|
|
|
if(!findChunk(stream, ID_EXTENSION, (uint32*)&length, nil))
|
|
|
|
return false;
|
|
|
|
while(length > 0){
|
|
|
|
if(!readChunkHeaderInfo(stream, &header))
|
|
|
|
return false;
|
|
|
|
length -= 12;
|
2020-04-25 00:37:49 +02:00
|
|
|
FORLIST(lnk, this->plugins){
|
|
|
|
Plugin *p = PLG(lnk);
|
2016-06-25 17:58:52 +02:00
|
|
|
if(p->id == header.type && p->read){
|
|
|
|
p->read(stream, header.length,
|
|
|
|
object, p->offset, p->size);
|
|
|
|
goto cont;
|
|
|
|
}
|
2020-04-25 00:37:49 +02:00
|
|
|
}
|
2016-06-25 17:58:52 +02:00
|
|
|
stream->seek(header.length);
|
|
|
|
cont:
|
|
|
|
length -= header.length;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginList::streamWrite(Stream *stream, void *object)
|
|
|
|
{
|
|
|
|
int size = this->streamGetSize(object);
|
|
|
|
writeChunkHeader(stream, ID_EXTENSION, size);
|
2020-04-25 00:37:49 +02:00
|
|
|
FORLIST(lnk, this->plugins){
|
|
|
|
Plugin *p = PLG(lnk);
|
2016-06-25 17:58:52 +02:00
|
|
|
if(p->getSize == nil ||
|
|
|
|
(size = p->getSize(object, p->offset, p->size)) <= 0)
|
|
|
|
continue;
|
|
|
|
writeChunkHeader(stream, p->id, size);
|
|
|
|
p->write(stream, size, object, p->offset, p->size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
PluginList::streamGetSize(void *object)
|
|
|
|
{
|
|
|
|
int32 size = 0;
|
|
|
|
int32 plgsize;
|
2020-04-25 00:37:49 +02:00
|
|
|
FORLIST(lnk, this->plugins){
|
|
|
|
Plugin *p = PLG(lnk);
|
2016-06-25 17:58:52 +02:00
|
|
|
if(p->getSize &&
|
|
|
|
(plgsize = p->getSize(object, p->offset, p->size)) > 0)
|
|
|
|
size += 12 + plgsize;
|
2020-04-25 00:37:49 +02:00
|
|
|
}
|
2016-06-25 17:58:52 +02:00
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2017-09-16 23:19:54 +02:00
|
|
|
void
|
|
|
|
PluginList::streamSkip(Stream *stream)
|
|
|
|
{
|
|
|
|
int32 length;
|
|
|
|
ChunkHeaderInfo header;
|
|
|
|
if(!findChunk(stream, ID_EXTENSION, (uint32*)&length, nil))
|
|
|
|
return;
|
|
|
|
while(length > 0){
|
|
|
|
if(!readChunkHeaderInfo(stream, &header))
|
|
|
|
return;
|
|
|
|
stream->seek(header.length);
|
|
|
|
length -= 12 + header.length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-25 17:58:52 +02:00
|
|
|
void
|
|
|
|
PluginList::assertRights(void *object, uint32 pluginID, uint32 data)
|
|
|
|
{
|
2020-04-25 00:37:49 +02:00
|
|
|
FORLIST(lnk, this->plugins){
|
|
|
|
Plugin *p = PLG(lnk);
|
2016-06-25 17:58:52 +02:00
|
|
|
if(p->id == pluginID){
|
|
|
|
if(p->rightsCallback)
|
|
|
|
p->rightsCallback(object,
|
|
|
|
p->offset, p->size, data);
|
|
|
|
return;
|
|
|
|
}
|
2020-04-25 00:37:49 +02:00
|
|
|
}
|
2016-06-25 17:58:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int32
|
|
|
|
PluginList::registerPlugin(int32 size, uint32 id,
|
|
|
|
Constructor ctor, Destructor dtor, CopyConstructor copy)
|
|
|
|
{
|
2017-08-24 15:10:34 +02:00
|
|
|
Plugin *p = (Plugin*)rwMalloc(sizeof(Plugin), MEMDUR_GLOBAL);
|
2016-06-25 17:58:52 +02:00
|
|
|
p->offset = this->size;
|
|
|
|
this->size += size;
|
2016-07-21 17:06:56 +02:00
|
|
|
int32 round = sizeof(void*)-1;
|
|
|
|
this->size = (this->size + round)&~round;
|
2016-06-25 17:58:52 +02:00
|
|
|
|
|
|
|
p->size = size;
|
|
|
|
p->id = id;
|
|
|
|
p->constructor = ctor ? ctor : defCtor;
|
|
|
|
p->destructor = dtor ? dtor : defDtor;
|
|
|
|
p->copy = copy ? copy : defCopy;
|
|
|
|
p->read = nil;
|
|
|
|
p->write = nil;
|
|
|
|
p->getSize = nil;
|
|
|
|
p->rightsCallback = nil;
|
2020-04-25 00:37:49 +02:00
|
|
|
p->parentList = this;
|
|
|
|
this->plugins.add(&p->inParentList);
|
|
|
|
allPlugins.add(&p->inGlobalList);
|
2016-06-25 17:58:52 +02:00
|
|
|
return p->offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32
|
|
|
|
PluginList::registerStream(uint32 id,
|
|
|
|
StreamRead read, StreamWrite write, StreamGetSize getSize)
|
|
|
|
{
|
2020-04-25 00:37:49 +02:00
|
|
|
FORLIST(lnk, this->plugins){
|
|
|
|
Plugin *p = PLG(lnk);
|
2016-06-25 17:58:52 +02:00
|
|
|
if(p->id == id){
|
|
|
|
p->read = read;
|
|
|
|
p->write = write;
|
|
|
|
p->getSize = getSize;
|
|
|
|
return p->offset;
|
|
|
|
}
|
2020-04-25 00:37:49 +02:00
|
|
|
}
|
2016-06-25 17:58:52 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32
|
|
|
|
PluginList::setStreamRightsCallback(uint32 id, RightsCallback cb)
|
|
|
|
{
|
2020-04-25 00:37:49 +02:00
|
|
|
FORLIST(lnk, this->plugins){
|
|
|
|
Plugin *p = PLG(lnk);
|
2016-06-25 17:58:52 +02:00
|
|
|
if(p->id == id){
|
|
|
|
p->rightsCallback = cb;
|
|
|
|
return p->offset;
|
|
|
|
}
|
2020-04-25 00:37:49 +02:00
|
|
|
}
|
2016-06-25 17:58:52 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32
|
|
|
|
PluginList::getPluginOffset(uint32 id)
|
|
|
|
{
|
2020-04-25 00:37:49 +02:00
|
|
|
FORLIST(lnk, this->plugins){
|
|
|
|
Plugin *p = PLG(lnk);
|
2016-06-25 17:58:52 +02:00
|
|
|
if(p->id == id)
|
|
|
|
return p->offset;
|
2020-04-25 00:37:49 +02:00
|
|
|
}
|
2016-06-25 17:58:52 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|