Skip to content

Instantly share code, notes, and snippets.

@RoyBellingan
Created May 18, 2022 22:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RoyBellingan/c5940570de535c7ed3617d947807ada9 to your computer and use it in GitHub Desktop.
Save RoyBellingan/c5940570de535c7ed3617d947807ada9 to your computer and use it in GitHub Desktop.
enum unroller
#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