305 lines
12 KiB
C++
305 lines
12 KiB
C++
#include <vector>
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <Eina.h>
|
|
#include <Eina.hh>
|
|
#include <Eo.h>
|
|
#include <Eolian.h>
|
|
|
|
#include "eo_types.hh"
|
|
#include "safe_strings.hh"
|
|
#include "comments.hh"
|
|
|
|
static std::string
|
|
_resolve_param_type(Eolian_Function_Parameter id, bool is_get)
|
|
{
|
|
Eolian_Parameter_Dir dir;
|
|
const char *type;
|
|
bool is_const;
|
|
std::string res;
|
|
|
|
eolian_parameter_information_get(id, &dir, &type, NULL, NULL);
|
|
is_const = eolian_parameter_const_attribute_get(id, is_get);
|
|
res = safe_str(type);
|
|
assert(res != "");
|
|
if (is_const) res = std::string("const ") + res;
|
|
if (dir == EOLIAN_OUT_PARAM || dir == EOLIAN_INOUT_PARAM) res += "*";
|
|
return res;
|
|
}
|
|
|
|
static efl::eolian::parameters_container_type
|
|
_get_params(const Eina_List *eolian_params, bool is_get = false)
|
|
{
|
|
const Eina_List *it;
|
|
void *curr;
|
|
if (eolian_params == NULL)
|
|
{
|
|
return efl::eolian::parameters_container_type();
|
|
}
|
|
efl::eolian::parameters_container_type list;
|
|
EINA_LIST_FOREACH (eolian_params, it, curr)
|
|
{
|
|
Eolian_Function_Parameter id =
|
|
(static_cast<Eolian_Function_Parameter>(curr));
|
|
list.push_back({
|
|
_resolve_param_type(id, is_get),
|
|
safe_strshare(eolian_parameter_name_get(id))
|
|
});
|
|
}
|
|
return list;
|
|
}
|
|
|
|
static efl::eolian::functions_container_type
|
|
_get_properties(const char *classname)
|
|
{
|
|
efl::eolian::functions_container_type container;
|
|
|
|
std::string cxx_classname = classname;
|
|
std::transform(cxx_classname.begin(), cxx_classname.end(),
|
|
cxx_classname.begin(), ::tolower);
|
|
|
|
const Eina_List *properties;
|
|
properties = eolian_class_functions_list_get(classname, EOLIAN_PROPERTY);
|
|
|
|
const Eina_List *it;
|
|
void *curr;
|
|
std::string prefix(safe_str(eolian_class_eo_prefix_get(classname)));
|
|
EINA_LIST_FOREACH (properties, it, curr)
|
|
{
|
|
Eolian_Function property = static_cast<Eolian_Function>(curr);
|
|
Eolian_Function_Type type = eolian_function_type_get(property);
|
|
std::string name = safe_str(eolian_function_name_get(property));
|
|
if (type == EOLIAN_PROP_GET || type == EOLIAN_PROPERTY)
|
|
{
|
|
const Eina_List *keys_ = eolian_property_keys_list_get(property);
|
|
efl::eolian::parameters_container_type params = _get_params
|
|
(eolian_parameters_list_get(property), true);
|
|
efl::eolian::eo_function getter;
|
|
getter.type = efl::eolian::eo_function::regular_;
|
|
getter.name = name + "_get";
|
|
getter.impl = (prefix != "" ? prefix : cxx_classname) + "_" + getter.name;
|
|
std::string ret = safe_str
|
|
(eolian_function_return_type_get(property, EOLIAN_PROP_GET));
|
|
if (ret == "") ret = "void";
|
|
|
|
// if the getter has a single parameter and void return
|
|
// we translate it to a getter with no parameters that
|
|
// returns its type.
|
|
if ((ret == "void") && params.size() == 1)
|
|
{
|
|
getter.ret = params[0].type;
|
|
getter.params.clear();
|
|
}
|
|
else // otherwise just create the described getter
|
|
{
|
|
getter.ret = ret;
|
|
getter.params = params;
|
|
std::transform
|
|
(params.begin(), params.end(), getter.params.begin(),
|
|
[](efl::eolian::eo_parameter const& param)
|
|
{
|
|
return efl::eolian::eo_parameter
|
|
{ param.type + "*", param.name };
|
|
});
|
|
}
|
|
if (eina_list_count(keys_) > 0)
|
|
{
|
|
efl::eolian::parameters_container_type keys = _get_params(keys_, true);
|
|
keys.reserve(keys.size() + getter.params.size());
|
|
keys.insert(keys.end(), getter.params.begin(), getter.params.end());
|
|
getter.params = keys;
|
|
}
|
|
getter.comment = detail::eolian_property_getter_comment(property);
|
|
container.push_back(getter);
|
|
}
|
|
if (type == EOLIAN_PROP_SET || type == EOLIAN_PROPERTY)
|
|
{
|
|
const Eina_List *keys_ = eolian_property_keys_list_get(property);
|
|
const Eina_List *args_ = eolian_parameters_list_get(property);
|
|
Eina_List *params_ = eina_list_merge(eina_list_clone(keys_), eina_list_clone(args_));
|
|
efl::eolian::parameters_container_type params = _get_params(params_);
|
|
eina_list_free(params_);
|
|
efl::eolian::eo_function setter;
|
|
setter.type = efl::eolian::eo_function::regular_;
|
|
setter.name = name + "_set";
|
|
setter.impl = (prefix != "" ? prefix : cxx_classname) + "_" + setter.name;
|
|
setter.params = params;
|
|
setter.ret = safe_str(eolian_function_return_type_get
|
|
(property, EOLIAN_PROP_SET));
|
|
if (setter.ret == "") setter.ret = "void";
|
|
setter.comment = detail::eolian_property_setter_comment(property);
|
|
container.push_back(setter);
|
|
}
|
|
}
|
|
return container;
|
|
}
|
|
|
|
namespace detail {
|
|
|
|
void
|
|
convert_eolian_inheritances(efl::eolian::eo_class& cls, const char *classname)
|
|
{
|
|
const Eina_List *inheritances = eolian_class_inherits_list_get(classname);
|
|
const Eina_List *it;
|
|
void *curr;
|
|
|
|
if (eina_list_count(inheritances) == 0
|
|
|| eina_list_data_get(inheritances) == NULL)
|
|
{
|
|
cls.parent = "efl::eo::base";
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
std::string parent =
|
|
static_cast<const char*>(eina_list_data_get(inheritances));
|
|
std::transform(parent.begin(), parent.end(), parent.begin(), ::tolower);
|
|
// "eo_base" is the Eolian name for EO_BASE_CLASS.
|
|
cls.parent = (parent == "eo_base" || parent == "") ? "efl::eo::base" : parent;
|
|
}
|
|
|
|
inheritances = eina_list_next(inheritances);
|
|
EINA_LIST_FOREACH (inheritances, it, curr)
|
|
{
|
|
std::string extension = static_cast<const char*>(curr);
|
|
std::transform
|
|
(extension.begin(), extension.end(), extension.begin(), ::tolower);
|
|
cls.extensions.push_back(extension);
|
|
}
|
|
}
|
|
|
|
void
|
|
convert_eolian_implements(efl::eolian::eo_class& cls, const char *classname)
|
|
{
|
|
const Eina_List *it;
|
|
void *curr;
|
|
std::string prefix(safe_str(eolian_class_eo_prefix_get(classname)));
|
|
const Eina_List *implements = eolian_class_implements_list_get(classname);
|
|
Eolian_Implement impl_desc;
|
|
void *impl_desc_;
|
|
EINA_LIST_FOREACH(eolian_class_implements_list_get(classname), it, impl_desc_)
|
|
{
|
|
Eolian_Implement impl_desc = static_cast<Eolian_Implement>(impl_desc_);
|
|
Eolian_Function_Type func_type;
|
|
const char *func_name;
|
|
const char *impl_class;
|
|
eolian_implement_information_get
|
|
(impl_desc, &impl_class, &func_name, &func_type);
|
|
#if 1 // XXX only due to a bug in Eolian we have to double-check
|
|
if(func_type == EOLIAN_UNRESOLVED &&
|
|
eolian_class_function_find_by_name(impl_class, func_name, EOLIAN_CTOR) != NULL)
|
|
func_type = EOLIAN_CTOR;
|
|
#endif
|
|
if (func_type == EOLIAN_CTOR)
|
|
{
|
|
efl::eolian::eo_constructor constructor;
|
|
Eolian_Function eolian_constructor = eolian_class_function_find_by_name
|
|
(impl_class, func_name, func_type);
|
|
assert(eolian_constructor != NULL);
|
|
std::string parent = safe_str(impl_class);
|
|
if(parent == "Eo_Base") parent = "eo";
|
|
else std::transform(parent.begin(), parent.end(), parent.begin(), ::tolower);
|
|
constructor.name = parent + "_" + safe_str(func_name);
|
|
constructor.params = _get_params
|
|
(eolian_parameters_list_get(eolian_constructor));
|
|
constructor.comment = detail::eolian_constructor_comment
|
|
(eolian_constructor);
|
|
cls.constructors.push_back(constructor);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
convert_eolian_constructors(efl::eolian::eo_class& cls, const char *classname)
|
|
{
|
|
const Eina_List *it;
|
|
void *curr;
|
|
std::string prefix(safe_str(eolian_class_eo_prefix_get(classname)));
|
|
const Eina_List *constructors =
|
|
eolian_class_functions_list_get(classname, EOLIAN_CTOR);
|
|
EINA_LIST_FOREACH (constructors, it, curr)
|
|
{
|
|
Eolian_Function eolian_constructor = static_cast<Eolian_Function>(curr);
|
|
efl::eolian::eo_constructor constructor;
|
|
constructor.name = (prefix != "" ? prefix : cls.name) + "_" + safe_str
|
|
(eolian_function_name_get(eolian_constructor));
|
|
constructor.params = _get_params
|
|
(eolian_parameters_list_get(eolian_constructor));
|
|
constructor.comment = detail::eolian_constructor_comment
|
|
(eolian_constructor);
|
|
cls.constructors.push_back(constructor);
|
|
}
|
|
}
|
|
|
|
void
|
|
convert_eolian_functions(efl::eolian::eo_class& cls, const char *classname)
|
|
{
|
|
const Eina_List *it;
|
|
void *curr;
|
|
|
|
const Eina_List *eolian_functions =
|
|
eolian_class_functions_list_get(classname, EOLIAN_METHOD);
|
|
EINA_LIST_FOREACH (eolian_functions, it, curr)
|
|
{
|
|
efl::eolian::eo_function function;
|
|
Eolian_Function eolian_function = static_cast<Eolian_Function>(curr);
|
|
std::string prefix(safe_str(eolian_class_eo_prefix_get(classname)));
|
|
// XXX Eolian only provides regular methods so far
|
|
function.type = efl::eolian::eo_function::regular_;
|
|
function.name = safe_str(eolian_function_name_get(eolian_function));
|
|
function.impl = ( prefix != "" ? prefix : cls.name ) + "_" + function.name;
|
|
function.ret = safe_str(eolian_function_return_type_get
|
|
(eolian_function, EOLIAN_METHOD));
|
|
if(function.ret == "") function.ret = "void";
|
|
function.params = _get_params(eolian_parameters_list_get(eolian_function));
|
|
function.comment = detail::eolian_function_comment(eolian_function);
|
|
cls.functions.push_back(function);
|
|
}
|
|
}
|
|
|
|
void
|
|
convert_eolian_properties(efl::eolian::eo_class& cls, const char *classname)
|
|
{
|
|
efl::eolian::functions_container_type properties = _get_properties(classname);
|
|
cls.functions.insert(cls.functions.end(), properties.begin(), properties.end());
|
|
}
|
|
|
|
} // namespace detail {
|
|
|
|
efl::eolian::eo_class
|
|
_cxx_new(const char *classname)
|
|
{
|
|
using namespace efl::eolian;
|
|
eo_class cls;
|
|
Eolian_Class_Type cls_type = ::eolian_class_type_get(classname);
|
|
if (cls_type == EOLIAN_CLASS_REGULAR) cls.type = eo_class::regular_;
|
|
else if (cls_type == EOLIAN_CLASS_ABSTRACT) cls.type = eo_class::regular_noninst_;
|
|
else if (cls_type == EOLIAN_CLASS_MIXIN) cls.type = eo_class::mixin_;
|
|
else if (cls_type == EOLIAN_CLASS_INTERFACE) cls.type = eo_class::interface_;
|
|
else { assert(false); }
|
|
std::string prefix(safe_str(eolian_class_eo_prefix_get(classname)));
|
|
cls.name = classname;
|
|
cls.eo_name = (prefix != "" ? prefix : cls.name) + "_CLASS";
|
|
cls.comment = detail::eolian_class_comment(classname);
|
|
std::transform(cls.name.begin(), cls.name.end(), cls.name.begin(), ::tolower);
|
|
std::transform(cls.eo_name.begin(), cls.eo_name.end(), cls.eo_name.begin(), ::toupper);
|
|
return cls;
|
|
}
|
|
|
|
efl::eolian::eo_class
|
|
c_to_cxx(const char *classname)
|
|
{
|
|
efl::eolian::eo_class cls(_cxx_new(classname));
|
|
detail::convert_eolian_inheritances(cls, classname);
|
|
detail::convert_eolian_implements(cls, classname);
|
|
detail::convert_eolian_constructors(cls, classname);
|
|
detail::convert_eolian_functions(cls, classname);
|
|
detail::convert_eolian_properties(cls, classname);
|
|
return cls;
|
|
}
|