genutils.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #ifndef GENUTILS_HPP
  2. #define GENUTILS_HPP
  3. #include "common.hpp"
  4. #include <fstream>
  5. #include <regex>
  6. #include <set>
  7. #include <sstream>
  8. #include <string>
  9. class skip : public std::runtime_error
  10. {
  11. public:
  12. static const int TODO = 0;
  13. static const int OK = 0;
  14. static const int INVALID = 1;
  15. static const int IGNORE = 2;
  16. int cause;
  17. skip(const std::string &reason, int _cause = INVALID)
  18. : std::runtime_error(reason), cause(_cause)
  19. {}
  20. };
  21. class ScopeGuard
  22. {
  23. private:
  24. std::function<void()> cleanup_;
  25. public:
  26. ScopeGuard(std::function<void()> &&cleanup) : cleanup_(std::move(cleanup)) {}
  27. ~ScopeGuard() noexcept(false)
  28. {
  29. #if __cplusplus >= 201703L
  30. auto pending = std::uncaught_exceptions();
  31. #else
  32. auto pending = std::uncaught_exception();
  33. #endif
  34. try {
  35. cleanup_();
  36. } catch (...) {
  37. if (!pending)
  38. throw;
  39. }
  40. }
  41. };
  42. class NamespaceGuard
  43. {
  44. typedef std::vector<std::string> ns_list;
  45. private:
  46. ns_list ns_;
  47. std::ostream &out_;
  48. void push(const ns_list &ns)
  49. {
  50. for (auto &&v : ns) {
  51. out_ << "namespace " << v << " {" << std::endl << std::endl;
  52. ns_.push_back(v);
  53. }
  54. }
  55. public:
  56. NamespaceGuard(std::ostream &_out) : out_(_out) {}
  57. void push(const std::string &ns, bool autodetect = true)
  58. {
  59. if (ns_.empty() && autodetect) {
  60. ns_list l{GI_NS, GI_REPOSITORY_NS};
  61. if (ns == GI_NS)
  62. l.pop_back();
  63. else if (ns != GI_REPOSITORY_NS)
  64. l.push_back(ns);
  65. push(l);
  66. } else {
  67. push(ns_list{ns});
  68. }
  69. }
  70. void pop(int count = -1)
  71. {
  72. while (!ns_.empty() && (count > 0 || count < 0)) {
  73. out_ << "} // namespace";
  74. if (ns_.back().size())
  75. out_ << ' ' << ns_.back();
  76. out_ << std::endl << std::endl;
  77. ns_.pop_back();
  78. --count;
  79. }
  80. }
  81. ~NamespaceGuard() { pop(); }
  82. };
  83. class Matcher
  84. {
  85. std::regex pattern_;
  86. static std::vector<std::string> readfile(std::istream &input)
  87. {
  88. std::vector<std::string> result;
  89. for (std::string line; std::getline(input, line);) {
  90. result.emplace_back(line);
  91. }
  92. return result;
  93. }
  94. public:
  95. Matcher(
  96. const std::vector<std::string> &paths, const std::string &patterns = {})
  97. {
  98. std::set<std::string> lines;
  99. for (auto &fpath : paths) {
  100. if (fpath.size()) {
  101. std::ifstream input(fpath);
  102. auto flines = readfile(input);
  103. logger(Log::DEBUG, "read {} lines from {}", flines.size(), fpath);
  104. std::copy(
  105. flines.begin(), flines.end(), std::inserter(lines, lines.begin()));
  106. }
  107. }
  108. if (patterns.size()) {
  109. std::istringstream iss(patterns);
  110. auto flines = readfile(iss);
  111. logger(Log::DEBUG, "read {} data lines", flines.size());
  112. std::copy(
  113. flines.begin(), flines.end(), std::inserter(lines, lines.begin()));
  114. }
  115. std::string lpatterns;
  116. for (auto &&l : lines) {
  117. if (!l.empty() && l[0] != '#') {
  118. // combine all expressions into 1 expression
  119. // so we only need to call once to check for matching
  120. lpatterns += (lpatterns.size() ? "|" : "") + l;
  121. }
  122. }
  123. if (lpatterns.size())
  124. pattern_ = std::regex(lpatterns, std::regex::optimize);
  125. }
  126. static std::string format(const std::string &first, const std::string &second,
  127. const std::string name)
  128. {
  129. return first + ":" + second + ":" + name;
  130. }
  131. bool matches(const std::string &first, const std::string &second,
  132. const std::vector<std::string> &options) const
  133. {
  134. for (auto &&c : options) {
  135. // assemble string to match
  136. auto find = format(first, second, c);
  137. if (std::regex_match(find, pattern_))
  138. return true;
  139. }
  140. return false;
  141. }
  142. };
  143. inline bool
  144. is_const(const std::string &ctype)
  145. {
  146. return (ctype.find("const ") != ctype.npos) || ctype == "gconstpointer";
  147. }
  148. inline bool
  149. is_volatile(const std::string &ctype)
  150. {
  151. return ctype.find("volatile ") != ctype.npos;
  152. }
  153. inline int
  154. get_pointer_depth(const std::string &ctype)
  155. {
  156. int pointer = ctype.find("gpointer") != ctype.npos ||
  157. ctype.find("gconstpointer") != ctype.npos;
  158. // note that things like const gchar* const* are also possible
  159. return std::count(ctype.begin(), ctype.end(), GI_PTR) + !!pointer;
  160. }
  161. // check if @s is somehow special
  162. // and mangle it a bit if so
  163. std::string unreserve(const std::string &s, bool force = false);
  164. #endif // GENUTILS_HPP