Files
tdesktop/cmake/external/glib/cppgir/tools/genutils.hpp
allhaileris afb81b8278
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
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
init
2026-02-16 15:50:16 +03:00

193 lines
4.4 KiB
C++

#ifndef GENUTILS_HPP
#define GENUTILS_HPP
#include "common.hpp"
#include <fstream>
#include <regex>
#include <set>
#include <sstream>
#include <string>
class skip : public std::runtime_error
{
public:
static const int TODO = 0;
static const int OK = 0;
static const int INVALID = 1;
static const int IGNORE = 2;
int cause;
skip(const std::string &reason, int _cause = INVALID)
: std::runtime_error(reason), cause(_cause)
{}
};
class ScopeGuard
{
private:
std::function<void()> cleanup_;
public:
ScopeGuard(std::function<void()> &&cleanup) : cleanup_(std::move(cleanup)) {}
~ScopeGuard() noexcept(false)
{
#if __cplusplus >= 201703L
auto pending = std::uncaught_exceptions();
#else
auto pending = std::uncaught_exception();
#endif
try {
cleanup_();
} catch (...) {
if (!pending)
throw;
}
}
};
class NamespaceGuard
{
typedef std::vector<std::string> ns_list;
private:
ns_list ns_;
std::ostream &out_;
void push(const ns_list &ns)
{
for (auto &&v : ns) {
out_ << "namespace " << v << " {" << std::endl << std::endl;
ns_.push_back(v);
}
}
public:
NamespaceGuard(std::ostream &_out) : out_(_out) {}
void push(const std::string &ns, bool autodetect = true)
{
if (ns_.empty() && autodetect) {
ns_list l{GI_NS, GI_REPOSITORY_NS};
if (ns == GI_NS)
l.pop_back();
else if (ns != GI_REPOSITORY_NS)
l.push_back(ns);
push(l);
} else {
push(ns_list{ns});
}
}
void pop(int count = -1)
{
while (!ns_.empty() && (count > 0 || count < 0)) {
out_ << "} // namespace";
if (ns_.back().size())
out_ << ' ' << ns_.back();
out_ << std::endl << std::endl;
ns_.pop_back();
--count;
}
}
~NamespaceGuard() { pop(); }
};
class Matcher
{
std::regex pattern_;
static std::vector<std::string> readfile(std::istream &input)
{
std::vector<std::string> result;
for (std::string line; std::getline(input, line);) {
result.emplace_back(line);
}
return result;
}
public:
Matcher(const std::vector<std::string> &paths,
const std::string &patterns = {},
const std::function<void(const std::string &)> &custom = {})
{
std::set<std::string> lines;
for (auto &fpath : paths) {
if (fpath.size()) {
std::ifstream input(fpath);
auto flines = readfile(input);
logger(Log::DEBUG, "read {} lines from {}", flines.size(), fpath);
std::copy(
flines.begin(), flines.end(), std::inserter(lines, lines.begin()));
}
}
if (patterns.size()) {
std::istringstream iss(patterns);
auto flines = readfile(iss);
logger(Log::DEBUG, "read {} data lines", flines.size());
std::copy(
flines.begin(), flines.end(), std::inserter(lines, lines.begin()));
}
std::string lpatterns;
for (auto &&l : lines) {
if (!l.empty() && l[0] != '#') {
// combine all expressions into 1 expression
// so we only need to call once to check for matching
lpatterns += (lpatterns.size() ? "|" : "") + l;
} else if (custom && l.size() > 2 && l[0] == '#' && l[1] == '!') {
custom(l);
}
}
if (lpatterns.size())
pattern_ = std::regex(lpatterns, std::regex::optimize);
}
static std::string format(const std::string &first, const std::string &second,
const std::string name)
{
return first + ":" + second + ":" + name;
}
bool matches(const std::string &first, const std::string &second,
const std::vector<std::string> &options) const
{
for (auto &&c : options) {
// assemble string to match
auto find = format(first, second, c);
if (std::regex_match(find, pattern_))
return true;
}
return false;
}
};
inline bool
is_const(const std::string &ctype)
{
return (ctype.find("const ") != ctype.npos) || ctype == "gconstpointer";
}
inline bool
is_volatile(const std::string &ctype)
{
return ctype.find("volatile ") != ctype.npos;
}
inline int
get_pointer_depth(const std::string &ctype)
{
int pointer = ctype.find("gpointer") != ctype.npos ||
ctype.find("gconstpointer") != ctype.npos;
// note that things like const gchar* const* are also possible
return std::count(ctype.begin(), ctype.end(), GI_PTR) + !!pointer;
}
// check if @s is somehow special
// and mangle it a bit if so
std::string unreserve(const std::string &s, bool force = false);
#endif // GENUTILS_HPP