Skip to content

Instantly share code, notes, and snippets.

@matteblair
Last active April 19, 2018 23:25
Show Gist options
  • Save matteblair/54a19f8e795b45f122df3d531692f16d to your computer and use it in GitHub Desktop.
Save matteblair/54a19f8e795b45f122df3d531692f16d to your computer and use it in GitHub Desktop.
Playing with style parameter access using templates
#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