Created
May 18, 2022 22:50
-
-
Save RoyBellingan/c5940570de535c7ed3617d947807ada9 to your computer and use it in GitHub Desktop.
enum unroller
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "enum.h" //this is https://github.com/aantron/better-enums https://raw.githubusercontent.com/aantron/better-enums/master/enum.h | |
#include "fmt/format.h" | |
#include <fmt/ranges.h> //of course remember to link -lmft | |
#include <vector> | |
BETTER_ENUM(Channel, int, | |
Red = 1, | |
Green = 1 << 2, | |
Blue = 1 << 3, | |
Boom = 1 << 16, | |
Zomg = 1 << 24) | |
BETTER_ENUM(ChOpt, uint, | |
NOT_SET = 0, | |
jsTracker = 1, //traffic saved starting from the tracking.php js | |
/** | |
* normally the feed are served in a s2s called to bing, so we have info about how many they are ecc | |
* but in this case they are shown using a bing JS, thus an iFrame is beeing composed in the page, and we have way less introspection | |
*/ | |
jsFeed = 2, | |
proxedSite = 4, //Website managed by agencies, so they call us via s2s we call bing and send to them a JSON to be used | |
RESERVED = 8, //old deprecated logic, still old data whit this value, ignore it | |
noAds = 16, //related to the JS if has NOT detected ads in page after the timeout | |
adsLoaded = 32, //related to the JS if has detected ads in page | |
jsRequest = 64, //initial request of the JS | |
s2s = 128, //if those even arrives to us from the s2s | |
jsStage2 = 256, | |
js2ch = 512 //the iacm endpoint is called, when the stage2 is executed to send us loggin information | |
); | |
template <class T1, class T2> | |
void addFlag(T1& t, T2 x) { | |
//For some reason -Wall and -pedantic-errors only print a warning here... so we enforce it | |
static_assert(std::is_same_v<T1, T2> || std::is_same_v<typename T1::_enumerated, T2>, "The two enum MUST be the same"); | |
t = static_cast<typename T1::_enumerated>(x | t); | |
} | |
template <typename T, typename... Types> | |
void addFlag(T& var1, Types... var2) { | |
for (const auto p : {var2...}) { | |
addFlag(var1, p); | |
} | |
} | |
template <class T> | |
concept isBetterEnum = requires(const T& t) { | |
//just check if some of the better enum function are defined or not | |
t._from_index(1); | |
t._value; | |
}; | |
template <typename Type> | |
requires isBetterEnum<Type> | |
std::vector<Type> getEnabled(Type& t) { | |
static const auto& values = t._values(); | |
std::vector<Type> set; | |
for (const auto& c : values) { | |
if (t & c) { | |
set.push_back(c); | |
} | |
} | |
return set; | |
} | |
template <typename Type> | |
requires isBetterEnum<Type> | |
std::vector<std::string> asString(const std::vector<Type>& t, bool verbose = false) { | |
std::vector<std::string> res; | |
//miserable hack to init the enum, not sure if is ok, but I have no better idea | |
Type sum = Type::_from_index(0); | |
sum._value = 0; //And reset immediately | |
for (const auto& c : t) { | |
if (verbose) { | |
auto s = fmt::format("{} ({})", c._to_string(), c._to_integral()); | |
res.push_back(s); | |
addFlag(sum, c); | |
} else { | |
res.push_back(c._to_string()); | |
} | |
} | |
if (verbose) { | |
auto s = fmt::format("sum: {}", sum._value); | |
res.push_back(s); | |
} | |
return res; | |
}; | |
int main() { | |
ChOpt c = ChOpt::NOT_SET; | |
addFlag(c, ChOpt::proxedSite, ChOpt::noAds, ChOpt::js2ch, ChOpt::jsRequest); | |
//uncomment to trigger error | |
//addFlag(c, Channel::Red); | |
auto en = getEnabled(c); | |
auto en2 = asString(en, true); | |
fmt::print("{}\n", fmt::join(en2, " | ")); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment