Last active
April 19, 2018 23:25
-
-
Save matteblair/54a19f8e795b45f122df3d531692f16d to your computer and use it in GitHub Desktop.
Playing with style parameter access using templates
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 <cassert> | |
#include <cstdint> | |
#include <cstdio> | |
#include <string> | |
#include <vector> | |
enum class StyleKey : uint8_t { | |
anchor, | |
angle, | |
buffer, | |
cap, | |
collide, | |
color, | |
extrude, | |
flat, | |
interactive, | |
join, | |
miter_limit, | |
none, | |
offset, | |
order, | |
outline_cap, | |
outline_color, | |
outline_join, | |
outline_miter_limit, | |
outline_order, | |
outline_style, | |
outline_visible, | |
outline_width, | |
placement, | |
placement_min_length_ratio, | |
placement_spacing, | |
point_text, | |
priority, | |
repeat_distance, | |
repeat_group, | |
size, | |
sprite, | |
sprite_default, | |
style, | |
text_align, | |
text_anchor, | |
text_buffer, | |
text_collide, | |
text_font_family, | |
text_font_fill, | |
text_font_size, | |
text_font_stroke_color, | |
text_font_stroke_width, | |
text_font_style, | |
text_font_weight, | |
text_interactive, | |
text_max_lines, | |
text_offset, | |
text_optional, | |
text_order, | |
text_priority, | |
text_repeat_distance, | |
text_repeat_group, | |
text_source, | |
text_source_left, | |
text_source_right, | |
text_transform, | |
text_transition_hide_time, | |
text_transition_selected_time, | |
text_transition_show_time, | |
text_visible, | |
text_wrap, | |
texture, | |
tile_edges, | |
transition_hide_time, | |
transition_selected_time, | |
transition_show_time, | |
visible, | |
width, | |
NUM_ELEMENTS | |
}; | |
// StyleValue declarations associate a StyleKey with the data type that it uses. | |
// Because the type information about the data is erased during storage, only | |
// "plain old data" types will work (i.e. nothing that allocates on the heap). | |
template<StyleKey K> struct StyleValue { using type = void; }; | |
template<> struct StyleValue<StyleKey::color> { using type = uint32_t; }; | |
template<> struct StyleValue<StyleKey::outline_color> { using type = uint32_t; }; | |
template<> struct StyleValue<StyleKey::point_text> { using type = std::string*; }; | |
// StyleParameter holds a StyleKey, some flags (e.g. whether there is a JS function | |
// or stops for the parameter), and a small buffer for the parameter data. | |
struct StyleParameter { | |
char data[14]; | |
uint8_t flags; | |
StyleKey key; | |
template<typename T> | |
void setValue(T value) { | |
static_assert(sizeof(T) <= sizeof(data), "Stored type must be no larger than the data buffer."); | |
*(reinterpret_cast<T*>(data)) = value; | |
} | |
template<typename T> | |
T getValue() { | |
static_assert(sizeof(T) <= sizeof(data), "Stored type must be no larger than the data buffer."); | |
return *(reinterpret_cast<T*>(data)); | |
} | |
}; | |
// DrawRule holds the parameters and providers accessors to them. | |
struct DrawRule { | |
std::vector<StyleParameter> parameters; | |
StyleParameter* findParameter(StyleKey key) { | |
for (auto& p : parameters) { | |
if (p.key == key) { | |
return &p; | |
} | |
} | |
return nullptr; | |
} | |
template<StyleKey K> | |
void addParameter(typename StyleValue<K>::type value) { | |
auto parameter = StyleParameter{ {}, 0, K }; | |
parameter.setValue<typename StyleValue<K>::type>(value); | |
parameters.push_back(parameter); | |
} | |
template<StyleKey K> | |
typename StyleValue<K>::type getParameter(typename StyleValue<K>::type fallback) { | |
auto p = findParameter(K); | |
if (p) { | |
return p->getValue<typename StyleValue<K>::type>(); | |
} | |
return fallback; | |
} | |
}; | |
int main() { | |
printf("sizeof(StyleParameter) = %lu\n", sizeof(StyleParameter)); | |
printf("sizeof(DrawRule) = %lu\n", sizeof(DrawRule)); | |
std::string text = "Globey"; | |
std::string error = "bad"; | |
DrawRule rule; | |
rule.addParameter<StyleKey::color>(4096); | |
rule.addParameter<StyleKey::point_text>(&text); | |
auto color = rule.getParameter<StyleKey::color>(0); | |
printf("getParameter<StyleKey::color> result: %d\n", color); | |
auto string = rule.getParameter<StyleKey::point_text>(&error); | |
printf("getParameter<StyleKey::point_text> result: %s\n", string->c_str()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment