Skip to content

Instantly share code, notes, and snippets.

@kkirby
Last active December 4, 2015 22:05
Show Gist options
  • Save kkirby/2c20298a5f12cabf4b6b to your computer and use it in GitHub Desktop.
Save kkirby/2c20298a5f12cabf4b6b to your computer and use it in GitHub Desktop.
#include <map>
#include <string>
#include <iostream>
#include <regex>
#include <math.h>
typedef enum {PX,CH,CW,VH,VW} unitsize_t;
struct SizeInfo {
unitsize_t unit;
double size;
std::string describe(){
char unitStr[3];
if(unit == PX){
strcpy(unitStr,"px");
}
else if(unit == CH){
strcpy(unitStr,"ch");
}
else if(unit == CW){
strcpy(unitStr,"cw");
}
else if(unit == VH){
strcpy(unitStr,"vh");
}
else if(unit == VW){
strcpy(unitStr,"vw");
}
else {
strcpy(unitStr,"--");
}
char output[255];
sprintf(output,"SizeInfo: Size(%f), Unit(%s)",size,unitStr);
return std::string(output);
}
};
struct SizeInfoMatch {
bool didMatch;
SizeInfo info;
std::string describe(){
char output[255];
sprintf(output,"SizeInfoMatch: DidMatch(%s), Info(%s)",didMatch ? "true" : "false",info.describe().c_str());
return std::string(output);
}
};
template <typename A,typename B> bool mapHasKey(const std::map<A,B>& map,A key){
return map.find(key) != map.end();
}
bool parseString(const char* str,SizeInfo& info){
std::cmatch matches;
if(std::regex_match(str,matches,std::regex("^(\\d+(?:\\.\\d+)?)(px|[cv][hw])$"))){
unitsize_t unit;
std::csub_match unitStr = matches[2];
double value = std::stod(matches[1].str());
if(unitStr.compare("px") == 0){
unit = PX;
}
else if(unitStr.compare("ch") == 0){
unit = CH;
}
else if(unitStr.compare("cw") == 0){
unit = CW;
}
else if(unitStr.compare("vw") == 0){
unit = VW;
}
else if(unitStr.compare("vh") == 0){
unit = VH;
}
else {
throw "no valid unit found.";
}
info.unit = unit;
info.size = value;
return true;
}
return false;
}
template <typename A,typename B> bool parseStringIfHas(std::map<A,B> props,const char* key,SizeInfo& info){
if(mapHasKey(props,key)){
return parseString(props[key],info);
}
else {
return false;
}
}
class Rect {
public:
SizeInfo top;
SizeInfo right;
SizeInfo bottom;
SizeInfo left;
SizeInfo width;
SizeInfo height;
std::string describe(){
char output[1024];
sprintf(
output,
"Rect: Top(%s), Right(%s), Bottom(%s), Left(%s), Width(%s), Height(%s)",
top.describe().c_str(),right.describe().c_str(),bottom.describe().c_str(),
left.describe().c_str(),width.describe().c_str(),height.describe().c_str()
);
return std::string(output);
}
};
class MyView : public Rect {};
template <typename T,typename... Args> T ViewBuilder(std::map<const char*,const char*> props,Args... args){
T instance = T(args...);
static_assert(
std::is_base_of<Rect, T>::value,
"T must be a descendant of Rect"
);
parseStringIfHas(props,"width",instance.width);
parseStringIfHas(props,"height",instance.height);
parseStringIfHas(props,"top",instance.top);
parseStringIfHas(props,"right",instance.right);
parseStringIfHas(props,"bottom",instance.bottom);
parseStringIfHas(props,"left",instance.left);
return instance;
}
int main(){
auto view = ViewBuilder<MyView>({
{"width","100.1234px"},
{"height","10vw"},
{"top","1024px"},
{"left","10px"}
});
std::cout << view.describe().c_str() << "\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment