You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
arts/soundserver/tradercheck.cc

214 lines
5.3 KiB

/*
Copyright (C) 2000-2003 Stefan Westerfeld
stefan@space.twc.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "common.h"
#include "debug.h"
#include "tradercheck.h"
#include <stdio.h>
#include <stdarg.h>
#include <map>
using namespace Arts;
using namespace std;
bool TraderCheck::haveProperty(TraderOffer& offer, const string& property)
{
vector<string>* plist = offer.getProperty(property);
bool result = !plist->empty();
delete plist;
return result;
}
string TraderCheck::getSingleProperty(TraderOffer& offer, const string& property)
{
string result="";
vector<string>* plist = offer.getProperty(property);
if(!plist->empty())
result = plist->front();
delete plist;
return result;
}
bool TraderCheck::findFile(const vector<string> *path, const string& filename)
{
vector<string>::const_iterator pi;
for(pi = path->begin(); pi != path->end(); pi++)
{
string pfilename = *pi + "/" + filename;
if(access(pfilename.c_str(),F_OK) == 0)
return true;
}
return false;
}
void TraderCheck::collectInterfaces(const string& interfaceName, map<string, int>& i)
{
InterfaceDef idef = interfaceRepo.queryInterface(interfaceName);
if(!idef.name.empty())
{
if(i[idef.name] == 1) return;
i[idef.name]++;
}
vector<string>::const_iterator ii;
for(ii = idef.inheritedInterfaces.begin(); ii != idef.inheritedInterfaces.end(); ii++)
collectInterfaces(*ii, i);
collectInterfaces("Arts::Object", i);
}
void
#ifdef __GNUC__
__attribute__ ( ( format ( printf, 3, 4 ) ) )
#endif
TraderCheck::check(bool cond, const char *fmt, ...)
{
if(cond)
return;
if(!wroteHeader)
{
wroteHeader = true;
printf("Trader inconsistency in \'%s\':\n", interfaceName.c_str());
}
printf(" * ");
va_list ap;
va_start(ap, fmt);
vfprintf(stdout, fmt, ap);
va_end(ap);
printf("\n");
}
void TraderCheck::run()
{
interfaceRepo = DynamicCast(Dispatcher::the()->interfaceRepo());
/* prevent the screen from being filled with aRts warnings */
Debug::init("", Debug::lFatal);
TraderQuery everything; /* a query without any restriction */
vector<TraderOffer> *allObjects = everything.query();
vector<TraderOffer>::iterator i;
for(i = allObjects->begin(); i != allObjects->end(); i++)
{
TraderOffer& offer = *i;
wroteHeader = false;
interfaceName = offer.interfaceName();
if(haveProperty(offer,"Type"))
{
// check type file consistency
check(haveProperty(offer,"TypeFile"),
"trader entries with a Type entry MUST have a TypeFile entry");
check(!haveProperty(offer,"Language"),
"trader entries with a Type entry MUST NOT have a Language entry");
}
else if(haveProperty(offer,"Language") || haveProperty(offer,"Library"))
{
// check class file consistency
InterfaceDef idef = interfaceRepo.queryInterface(offer.interfaceName());
if(idef.name.empty())
{
check(false, "interface type not found");
}
else
{
// verify correctness of the Interface= line
map<string,int> ifaces;
collectInterfaces(offer.interfaceName(), ifaces);
vector<string>* plist = offer.getProperty("Interface");
vector<string>::iterator pi;
for(pi = plist->begin(); pi != plist->end(); pi++)
{
ifaces[*pi]+=2;
}
delete plist;
map<string,int>::iterator ii;
for(ii = ifaces.begin(); ii != ifaces.end(); ii++)
{
switch(ii->second)
{
case 0:
check(false, "INTERNAL verification error");
break;
case 1:
check(false, "missing interface %s in Interface entry",
ii->first.c_str());
break;
case 2:
check(false, "given unimplemented(?) interface %s in Interface entry",
ii->first.c_str());
break;
case 3:
/* the way things should be */
break;
default:
check(false, "given interface %s in Interface entry more than once?",
ii->first.c_str());
break;
}
}
}
if(haveProperty(offer,"Library"))
{
check(getSingleProperty(offer,"Language") == "C++",
"trader entries with a Library entry SHOULD have a Language=C++ entry");
}
if (getSingleProperty(offer,"Language") == "C++")
{
string library = getSingleProperty(offer,"Library");
check(!library.empty(),
"entries with a Language entry must have a Library entry");
check(findFile(MCOPUtils::extensionPath(), library),
"Library entry MUST be loadable via extension path");
}
check(haveProperty(offer, "Interface"),
"entries with Language/Library MUST have an Interface entry");
}
else
{
check(false,"entry MUST have either Language or Type entry");
}
}
delete allObjects;
}