/***************************************************************************
UlxrIdlParser.cpp - parse Ulxr idl files
-------------------
begin : Sun May 27 2007
copyright : (C) 2002-2007 by Ewald Arnold
email : ulxmlrpcpp@ewald-arnold.de
$Id: UlxrIdlClass.cpp 1016 2007-07-22 15:03:44Z ewald-arnold $
***************************************************************************/
/**************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
***************************************************************************/
#include "UlxrIdlClass.h"
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iostream>
struct MethodComp
{
bool operator()(const Method *lhs, const Method *rhs)
{
return lhs->getName() < rhs->getName();
}
};
Type::Type()
{
}
void Type::setProperty(const std::string &in_left, const std::string &in_right)
{
left = in_left;
right = in_right;
}
void Type::setName(const std::string &in_name)
{
name = in_name;
simplename = in_name;
unsigned pos;
const std::string spaces = " ";
while ((pos = simplename.find(spaces)) != std::string::npos)
simplename.erase(pos, 1);
const std::string unsigneds = "unsigned";
while ((pos = simplename.find(unsigneds)) != std::string::npos)
simplename.erase(pos, unsigneds.length());
const std::string signeds = "signed";
while ((pos = simplename.find(signeds)) != std::string::npos)
simplename.erase(pos, signeds.length());
const std::string consts = "const";
while ((pos = simplename.find(consts)) != std::string::npos)
simplename.erase(pos, consts.length());
}
std::string Type::getRpcName() const
{
if ( simplename == "char"
&& isPointer())
return "ulxr::RpcString";
else if ( simplename == "wchar_t"
&& isPointer())
return "ulxr::RpcString";
else if ( simplename == "int"
|| simplename == "long int"
|| simplename == "short int"
|| simplename == "char"
|| simplename == "wchar_t"
|| simplename == "long")
return "ulxr::Integer";
else if (simplename == "std::string"
|| simplename == "std::wstring"
|| simplename == "std::basic_string<char>"
|| simplename == "std::basic_string<wchar_t>")
return "ulxr::RpcString";
else if ( simplename == "float"
|| simplename == "double")
return "ulxr::Double";
else if (simplename == "bool")
return "ulxr::Boolean";
else if (simplename == "void")
return "ulxr::Void";
return std::string("??") + simplename + "/" + name + "??";
}
std::string Type::getRpcAccessor() const
{
if ( simplename == "char"
&& isPointer())
return "getString";
else if ( simplename == "wchar_t"
&& isPointer())
return "getString";
else if ( simplename == "int"
|| simplename == "long int"
|| simplename == "short int"
|| simplename == "char"
|| simplename == "wchar_t"
|| simplename == "long")
return "getInteger";
else if (simplename == "std::string"
|| simplename == "std::wstring"
|| simplename == "std::basic_string<char>"
|| simplename == "std::basic_string<wchar_t>")
return "getString";
else if ( simplename == "float"
|| simplename == "double")
return "getDouble";
else if (simplename == "bool")
return "getBoolean";
return std::string("??") + simplename + "/" + name + "??";
}
std::string Type::getProxyType() const
{
if ( simplename == "char"
&& isPointer())
return "std::string";
else if ( simplename == "wchar_t"
&& isPointer())
return "std::wstring";
else if ( simplename == "int"
|| simplename == "long int"
|| simplename == "short int"
|| simplename == "char"
|| simplename == "wchar_t"
|| simplename == "long")
return "long int";
else if (simplename == "std::basic_string<char>"
|| simplename == "std::string")
return "std::string";
else if ( simplename == "std::wstring"
|| simplename == "std::basic_string<wchar_t>")
return "std::wstring";
else if ( simplename == "float"
|| simplename == "double")
return "double";
else if ( simplename == "bool"
/* || simplename == "double" */)
return "bool";
return std::string("??") + simplename + "/" + name + "??";
}
std::string Type::getTypeDereference() const
{
if ( simplename == "char"
&& isPointer())
return "";
else if ( simplename == "wchar_t"
&& isPointer())
return "";
if (isPointer())
return "*";
else
return "";
}
std::string Type::getTypeAccessor() const
{
if ( simplename == "char"
&& isPointer())
return ".c_str()";
else if ( simplename == "wchar_t"
&& isPointer())
return ".c_str()";
return "";
}
std::string Type::getTypeAdapter() const
{
if ( simplename == "char"
&& isPointer())
return "ulxr::getLatin1";
else if ( simplename == "wchar_t"
&& isPointer())
return "ulxr::getUnicode";
else if ( simplename == "std::basic_string<char>"
|| simplename == "std::string")
return "ulxr::getLatin1";
else if ( simplename == "std::wstring"
|| simplename == "std::basic_string<wchar_t>")
return "ulxr::getUnicode";
return "";
}
std::string Type::getInversTypeAdapter() const
{
if ( simplename == "char"
&& isPointer())
return "ULXR_GET_STRING";
else if ( simplename == "wchar_t"
&& isPointer())
return "ULXR_GET_STRING";
else if ( simplename == "std::basic_string<char>"
|| simplename == "std::string")
return "ULXR_GET_STRING";
else if ( simplename == "std::wstring"
|| simplename == "std::basic_string<wchar_t>")
return "ULXR_GET_STRING";
return "";
}
std::string Type::getLeft() const
{
return left;
}
std::string Type::getRight() const
{
return right;
}
bool Type::isReference() const
{
return getRight().find("&") != std::string::npos;
}
bool Type::isPointer() const
{
return getRight().find("*") != std::string::npos;
}
std::string Type::getName() const
{
return name;
}
void Type::clear()
{
name.clear();
left.clear();
right.clear();
}
std::string Type::getCppString() const
{
std::string ret;
if (left.length() != 0)
ret += left + " ";
ret += name;
if (right.length() != 0)
ret += " " + right;
return ret;
}
//////////////////////////////////////////////////////////
Argument::Argument()
{
}
void Argument::setName(const std::string &in_name)
{
name = in_name;
}
std::string Argument::getConstCastedName() const
{
return Argument::getConstCastedName(name, getType());
}
std::string Argument::getConstCastedName(const std::string &name,
const Type &type,
const std::string &prefix,
const std::string &suffix)
{
static std::string sconst = "const";
static unsigned lconst = sconst.length();
bool consttype = false;
std::string sleft = type.getLeft();
unsigned pos;
while ((pos = sleft.find(sconst)) != std::string::npos)
{
consttype = true;
sleft.erase(pos, lconst);
}
std::string sright = type.getRight();
while ((pos = sright.find(sconst)) != std::string::npos)
{
consttype = true;
sright.erase(pos, lconst);
}
if (!consttype)
return name;
while ((pos = sright.find("&")) != std::string::npos)
sright.erase(pos, 1);
// return std::string("const_cast<") + prefix + sleft + " " + type.getName() + " " + sright + suffix + ">(" + name + ")";
return std::string("(") + prefix + sleft + " " + type.getName() + " " + sright + suffix + ")(" + name + ")";
}
std::string Argument::getName() const
{
return name;
}
void Argument::setType(const Type &in_type)
{
type = in_type;
}
Type Argument::getType() const
{
return type;
}
std::string Argument::getCppString() const
{
return type.getCppString() + " " + name;
}
void Argument::clear()
{
type.clear();
name.clear();
}
//////////////////////////////////////////////////////////
Method::Method()
: isfunction(false)
{
}
void Method::setProperty(bool constructor,
bool in_virtual,
bool in_const)
{
isvirtual = in_virtual;
isconst = in_const;
isconstructor = constructor;
}
void Method::setName(const std::string &in_classname, const std::string &in_name)
{
name = in_name;
setOverloadName(in_name);
classname = in_classname;
}
void Method::setName(const std::string &in_name)
{
name = in_name;
setOverloadName(in_name);
}
std::string Method::extractNamespace()
{
std::string ns;
unsigned pos;
while ((pos = name.find("::")) != std::string::npos)
{
if (ns.length() != 0)
ns += "::";
ns += name.substr(0, pos);
name.erase(0, pos+2);
}
while ((pos = classname.find("::")) != std::string::npos)
classname.erase(0, pos+2);
// setOverloadName(name);
return ns;
}
std::string Method::getName(bool fully) const
{
if (fully)
return classname + "::" + name;
else
return name;
}
void Method::setOverloadName(const std::string &in_name)
{
overloadname = in_name;
unsigned pos = 0;
while ((pos = overloadname.find(":")) != std::string::npos)
overloadname[pos] = '_';
}
std::string Method::getOverloadName(bool fully,
const std::string &suffix,
const std::string &binder) const
{
if (fully && !isfunction)
return classname + suffix + binder + overloadname;
else
return overloadname;
}
void Method::setType(const Type &in_type)
{
type = in_type;
}
Type Method::getType() const
{
return type;
}
void Method::addArgument(const Argument &arg)
{
args.push_back(arg);
}
std::string Method::getTemplateSignature() const
{
static std::string sconst = "const";
static unsigned lconst = sconst.length();
std::string s;
for (unsigned i = 0; i < args.size(); ++i)
{
if (i != 0)
s += ", ";
bool reftype = args[i].getType().getRight().find("&") != std::string::npos;
std::string left = args[i].getType().getLeft();
unsigned pos;
while ((pos = left.find(sconst)) != std::string::npos)
left.erase(pos, lconst);
if (left.length() != 0)
s += left + " ";
s += args[i].getType().getName();
std::string right = args[i].getType().getRight();
while ((pos = right.find(sconst)) != std::string::npos)
right.erase(pos, lconst);
if (!reftype && right.length() != 0)
s += " " + right;
}
//
std::string left = getType().getLeft();
std::string right = getType().getRight();
bool reftype = right.find("&") != std::string::npos;
std::string ret;
unsigned pos;
if ((pos = left.find(sconst)) != std::string::npos)
left.erase(pos, lconst);
if (left.length() != 0)
ret += left + " ";
ret += getType().getName();
while ((pos = right.find(sconst)) != std::string::npos)
right.erase(pos, lconst);
if (!reftype && right.length() != 0)
ret += " " + right;
if (s.length() != 0)
ret += std::string(", ") + s;
return ret;
}
std::string Method::getSignature() const
{
std::string ret;
for (unsigned i = 0; i < args.size(); ++i)
{
if (i != 0)
ret += ", ";
ret += args[i].getType().getCppString();
}
return ret;
}
void Method::setFunction(bool isfunc)
{
isfunction = isfunc;
}
std::string Method::getCppString(unsigned indent,
bool impl,
const std::string &suffix) const
{
return getCppString(name, indent, impl, suffix);
}
std::string Method::getCppString(const std::string &my_name,
unsigned indent,
bool impl,
const std::string &suffix) const
{
std::string ret;
// if (isvirtual && !impl)
// ret += "virtual ";
if (!isconstructor)
ret += type.getCppString() + " ";
else
ret += "/*ctor*/ ";
if (impl && !isfunction)
ret += classname + suffix + "::" + my_name;
else
ret += my_name;
ret += "(";
for (unsigned i = 0; i < args.size(); ++i)
{
if (i != 0)
ret += ", ";
ret += args[i].getCppString();
}
ret += ")";
if (isconst)
ret += " const";
if (!impl)
ret += ";";
return ret;
}
bool Method::isConstructor() const
{
return isconstructor;
}
bool Method::isVirtual() const
{
return isvirtual;
}
unsigned Method::numArgs() const
{
return args.size();
}
Argument Method::getArg(unsigned i) const
{
return args[i];
}
bool Method::operator<(const Method &rhs) const
{
return name < rhs.name;
}
void Method::clear()
{
args.clear();
name.clear();
overloadname.clear();
classname.clear();
// sourcefile
}
void Method::OverloadRename(Method *method, unsigned ctr)
{
std::stringstream ss;
ss << method->getName() << "_ovr" << ctr;
std::cout << "Function overload remapped: "
<< method->getCppString(0, true, "") << " --> "
<< ss.str() << std::endl;
method->setOverloadName(ss.str());
}
void Method::resolveOverloaded(std::vector<Method> &methods)
{
// Workaround BCB5: intermediate vector with pointer
std::vector<Method*> overp;
for (unsigned i = 0; i < methods.size(); ++i)
overp.push_back(&methods[i]);
if (overp.size() != 0)
{
std::sort(overp.begin(), overp.end(), MethodComp());
for (unsigned i = 0; i < overp.size(); ++i)
{
std::string s = overp[i]->getName();
unsigned ctr = 0;
if (i < overp.size()-1 && s == overp[i+1]->getName())
{
OverloadRename(overp[i], ctr);
++ctr;
++i;
while (i < overp.size() && s == overp[i]->getName())
{
OverloadRename(overp[i], ctr);
++ctr;
++i;
}
}
}
}
}
std::string Method::getSource() const
{
return sourcefile;
}
void Method::setSource(const std::string &in_name)
{
sourcefile = in_name;
}
//////////////////////////////////////////////////////////
UlxrIdlClass::UlxrIdlClass()
{
}
void UlxrIdlClass::setName(const std::string &in_name)
{
name = in_name;
}
std::string UlxrIdlClass::getName() const
{
return name;
}
std::string UlxrIdlClass::getBaseName() const
{
std::string rem = name;
unsigned pos;
while ((pos = rem.find("::")) != std::string::npos)
rem.erase(0, pos+2);
return rem;
}
std::string UlxrIdlClass::getNamespace() const
{
std::string ns;
std::string s = name;
unsigned pos;
while ((pos = s.find("::")) != std::string::npos)
{
if (ns.length() != 0)
ns += "::";
ns += name.substr(0, pos);
s.erase(0, pos+2);
}
return ns;
}
void UlxrIdlClass::addMethod(const Method &method)
{
if (method.isConstructor())
ctors.push_back(method);
else
methods.push_back(method);
unsigned cnt = method.numArgs();
if (std::find(argsCnt.begin(), argsCnt.end(), cnt) == argsCnt.end())
argsCnt.push_back(cnt);
}
std::vector<unsigned> UlxrIdlClass::getArgsCount() const
{
return argsCnt;
}
void UlxrIdlClass::clear()
{
methods.clear();
ctors.clear();
argsCnt.clear();
}
unsigned UlxrIdlClass::numMethods() const
{
return methods.size();
}
Method UlxrIdlClass::getMethod(unsigned i) const
{
return methods[i];
}
const std::vector<Method> &
UlxrIdlClass::getAllMethods() const
{
return methods;
}
unsigned UlxrIdlClass::numCtors() const
{
return ctors.size();
}
Method UlxrIdlClass::getCtor(unsigned i) const
{
return ctors[i];
}
void UlxrIdlClass::OverloadRename(Method *method, unsigned ctr)
{
std::stringstream ss;
ss << method->getName() << "_ovr" << ctr;
std::cout << "Method overload remapped: "
<< method->getCppString(0, true, "") << " --> "
<< ss.str() << std::endl;
method->setOverloadName(ss.str());
}
void UlxrIdlClass::resolveOverloaded()
{
// Workaround BCB5: intermediate vector with pointer
std::vector<Method*> overp;
for (unsigned i = 0; i < methods.size(); ++i)
overp.push_back(&methods[i]);
if (overp.size() != 0)
{
std::sort(overp.begin(), overp.end(), MethodComp());
for (unsigned i = 0; i < overp.size(); ++i)
{
std::string s = overp[i]->getName();
unsigned ctr = 0;
if (i < overp.size()-1 && s == overp[i+1]->getName())
{
OverloadRename(overp[i], ctr);
++ctr;
++i;
while (i < overp.size() && s == overp[i]->getName())
{
OverloadRename(overp[i], ctr);
++ctr;
++i;
}
}
}
}
}
std::string UlxrIdlClass::getSource() const
{
return sourcefile;
}
void UlxrIdlClass::setSource(const std::string &in_name)
{
sourcefile = in_name;
}
syntax highlighted by Code2HTML, v. 0.9.1