init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
222
cmake/external/glib/cppgir/tools/genbase.cpp
vendored
Normal file
222
cmake/external/glib/cppgir/tools/genbase.cpp
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
#include "genbase.hpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
static std::string
|
||||
qualify(const std::string &ns, const std::string &cpptype, int flags)
|
||||
{
|
||||
if (cpptype.find(':') == cpptype.npos && !cpptype.empty() &&
|
||||
!(flags & TYPE_BASIC))
|
||||
return ns + "::" + cpptype;
|
||||
return cpptype;
|
||||
}
|
||||
|
||||
GeneratorBase::GeneratorBase(GeneratorContext &_ctx, const std::string _ns)
|
||||
: ctx(_ctx), ns(_ns)
|
||||
{}
|
||||
|
||||
std::string
|
||||
GeneratorBase::qualify(const std::string &cpptype, int flags) const
|
||||
{
|
||||
return ::qualify(ns, cpptype, flags);
|
||||
}
|
||||
|
||||
void
|
||||
GeneratorBase::parse_typeinfo(
|
||||
const std::string &girname, TypeInfo &result) const
|
||||
{
|
||||
auto ti = ctx.repo.lookup(girname);
|
||||
if (ti && ti->info)
|
||||
result = *ti->info;
|
||||
}
|
||||
|
||||
GeneratorBase::ArgInfo
|
||||
GeneratorBase::parse_arginfo(const pt::ptree &node, ArgInfo *routput) const
|
||||
{
|
||||
ArgInfo lresult;
|
||||
ArgInfo &result = routput ? *routput : lresult;
|
||||
|
||||
const pt::ptree *pntype{};
|
||||
std::string kind;
|
||||
// try most likely in turn
|
||||
for (auto &&v : {EL_TYPE, EL_ARRAY, EL_VARARGS}) {
|
||||
const auto &ntypeo = node.get_child_optional(v);
|
||||
if (ntypeo.is_initialized()) {
|
||||
kind = v;
|
||||
pntype = &ntypeo.get();
|
||||
}
|
||||
}
|
||||
if (kind.empty() || !pntype)
|
||||
throw skip("type info not found");
|
||||
if (kind == EL_VARARGS)
|
||||
throw skip("varargs not supported", skip::OK);
|
||||
auto &ntype = *pntype;
|
||||
bool discard_element = false;
|
||||
// no name for array
|
||||
if (kind == EL_ARRAY) {
|
||||
result.flags = TYPE_ARRAY;
|
||||
result.length = get_attribute<int>(ntype, AT_LENGTH, -10);
|
||||
result.zeroterminated = get_attribute<int>(ntype, AT_ZERO_TERMINATED, 1);
|
||||
result.fixedsize = get_attribute<int>(ntype, AT_FIXED_SIZE, 0);
|
||||
if (result.length < 0 && !result.zeroterminated && !result.fixedsize)
|
||||
throw skip("inconsistent array info");
|
||||
auto name = get_name(ntype, std::nothrow);
|
||||
// could be GBytes, etc
|
||||
if (name.size()) {
|
||||
// transform to plain argument if not ignored
|
||||
// FIXME maybe custom wrappers might be more convenient ??
|
||||
if (ctx.match_ignore.matches(ns, EL_RECORD, {name}))
|
||||
throw skip(name + " array not supported", skip::OK);
|
||||
// fresh state and discard element info processing
|
||||
result = ArgInfo{};
|
||||
discard_element = true;
|
||||
parse_typeinfo(name, result);
|
||||
}
|
||||
} else {
|
||||
parse_typeinfo(get_name(ntype), result);
|
||||
}
|
||||
// should be present (but not so for signal)
|
||||
// though const info seems to be missing in array case
|
||||
result.ctype = get_attribute(ntype, AT_CTYPE, "");
|
||||
|
||||
// special case where const is preserved for the cpp type
|
||||
if (result.girname == "gpointer" && is_const(result.ctype))
|
||||
parse_typeinfo("gconstpointer", result);
|
||||
|
||||
// handle element type info
|
||||
int i = 0;
|
||||
for (const auto &n : ntype) {
|
||||
if (n.first == "type" && !discard_element) {
|
||||
ArgTypeInfo &ti = i == 0 ? result.first : result.second;
|
||||
auto elname = get_name(n.second);
|
||||
parse_typeinfo(elname, ti);
|
||||
if (!ti.flags)
|
||||
throw skip("container element not supported", skip::OK);
|
||||
// probably not, but give it a shot
|
||||
ti.ctype = get_attribute(n.second, AT_CTYPE, "");
|
||||
// avoid specialized bool vector
|
||||
if (ti.cpptype == "bool")
|
||||
ti.cpptype = "gboolean";
|
||||
// some char arrays (e.g. g_regex* parameters) specify utf8 element type
|
||||
// along with ctype char rather than char*
|
||||
// so discard utf8 in that case and go for a plain array
|
||||
if (kind == EL_ARRAY && elname == "utf8" && ti.ctype == "gchar")
|
||||
parse_typeinfo(ti.ctype, ti);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
// sanity checks
|
||||
if ((result.flags & (TYPE_ARRAY | TYPE_LIST))) {
|
||||
if (i != 1)
|
||||
throw skip("inconsistent list element info");
|
||||
if (result.flags & TYPE_ARRAY) {
|
||||
// NOTE apparently both are possible, see e.g. g_shell_parse_arg*
|
||||
// in that case it is handled zeroterminated
|
||||
// and the size param becomes a regular one
|
||||
if (result.zeroterminated) {
|
||||
result.length = -1;
|
||||
result.fixedsize = 0;
|
||||
}
|
||||
// 1 pointer level more than the basic type
|
||||
result.pdepth = ((result.first.flags & TYPE_CLASS) ? 1 : 0) + 1;
|
||||
}
|
||||
} else if (result.flags & TYPE_MAP) {
|
||||
if (i != 2)
|
||||
throw skip("inconsistent map element info");
|
||||
} else {
|
||||
if (i != 0)
|
||||
throw skip("inconsistent type info");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string
|
||||
GeneratorBase::make_ctype(
|
||||
const ArgInfo &info, const std::string &direction, bool callerallocates)
|
||||
{
|
||||
std::string result;
|
||||
bool out = !(direction == DIR_IN || direction == DIR_RETURN);
|
||||
if (info.flags & TYPE_ARRAY) {
|
||||
auto ret = info.first.argtype + GI_PTR;
|
||||
if (out && !callerallocates)
|
||||
ret += GI_PTR;
|
||||
result = ret;
|
||||
} else if (info.flags & TYPE_CALLBACK) {
|
||||
result = info.cpptype + "::cfunction_type";
|
||||
} else {
|
||||
if (!out || callerallocates) {
|
||||
result = info.argtype;
|
||||
} else {
|
||||
result = info.argtype + GI_PTR;
|
||||
}
|
||||
}
|
||||
return (is_const(info.ctype) ? std::string("const ") : EMPTY) + result;
|
||||
}
|
||||
|
||||
void
|
||||
GeneratorBase::track_dependency(DepsSet &deps, const ArgInfo &info) const
|
||||
{
|
||||
auto track = [&](const std::string &cpptype, int flags) {
|
||||
// other items (e.g. enums) are included before anyway
|
||||
if (flags & TYPE_CLASS && !(flags & (TYPE_BASIC | TYPE_TYPEDEF))) {
|
||||
// always track scoped
|
||||
assert(is_qualified(cpptype));
|
||||
deps.insert({"", cpptype});
|
||||
if (flags & TYPE_BOXED)
|
||||
deps.insert({"", cpptype + GI_SUFFIX_REF});
|
||||
}
|
||||
};
|
||||
if (!(info.flags & TYPE_CONTAINER)) {
|
||||
track(info.cpptype, info.flags);
|
||||
} else {
|
||||
track(info.first.cpptype, info.first.flags);
|
||||
if (info.flags & TYPE_MAP)
|
||||
track(info.second.cpptype, info.second.flags);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GeneratorBase::check_suppression(const std::string &ns, const std::string &kind,
|
||||
const std::string &name) const
|
||||
{
|
||||
// always generate
|
||||
ctx.suppressions.insert(ctx.match_sup.format(ns, kind, name));
|
||||
return ctx.match_sup.matches(ns, kind, {name});
|
||||
}
|
||||
|
||||
std::string
|
||||
GeneratorBase::make_wrap_format(const ArgInfo &info,
|
||||
const std::string &transfer, const std::string &outtype)
|
||||
{
|
||||
std::string fmts;
|
||||
auto format = "{}";
|
||||
if (info.flags & TYPE_CLASS) {
|
||||
fmts = fmt::format(GI_NS_SCOPED + "wrap ({}, {})", format,
|
||||
get_transfer_parameter(transfer));
|
||||
} else if (info.flags & TYPE_ENUM) {
|
||||
fmts = GI_NS_SCOPED + "wrap ({})";
|
||||
} else if (info.flags & (TYPE_LIST | TYPE_ARRAY | TYPE_MAP)) {
|
||||
assert(!outtype.empty());
|
||||
fmts = fmt::format(GI_NS_SCOPED + "wrap_to<{}>({}, {})", outtype, format,
|
||||
get_transfer_parameter(transfer));
|
||||
} else {
|
||||
fmts = format;
|
||||
}
|
||||
return fmts;
|
||||
}
|
||||
|
||||
std::string
|
||||
GeneratorBase::get_transfer_parameter(const std::string &transfer, bool _type)
|
||||
{
|
||||
std::map<std::string, std::string> m{
|
||||
{TRANSFER_NOTHING, "transfer_none"},
|
||||
{TRANSFER_FULL, "transfer_full"},
|
||||
{TRANSFER_CONTAINER, "transfer_container"},
|
||||
};
|
||||
auto it = m.find(transfer);
|
||||
if (it == m.end())
|
||||
throw std::runtime_error("invalid transfer " + transfer);
|
||||
return GI_NS_SCOPED + it->second + (_type ? "_t" : "");
|
||||
}
|
||||
Reference in New Issue
Block a user